-
Notifications
You must be signed in to change notification settings - Fork 295
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #326 from newrelic/develop
Merging develop to create v3.13.0
- Loading branch information
Showing
14 changed files
with
411 additions
and
423 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,17 +113,17 @@ jobs: | |
extratesting: go get -u github.com/sirupsen/logrus@master | ||
- go-version: 1.15.x | ||
dirs: v3/integrations/nrawssdk-v1 | ||
extratesting: go get -u github.com/aws/aws-sdk-go@master | ||
extratesting: go get -u github.com/aws/aws-sdk-go@main | ||
- go-version: 1.15.x | ||
dirs: v3/integrations/nrawssdk-v2 | ||
extratesting: go get -u github.com/aws/aws-sdk-go-v2@master | ||
extratesting: go get -u github.com/aws/aws-sdk-go-v2@main | ||
- go-version: 1.15.x | ||
dirs: v3/integrations/nrecho-v3 | ||
# Test against the latest v3 Echo: | ||
extratesting: go get -u github.com/labstack/echo@v3 | ||
- go-version: 1.15.x | ||
dirs: v3/integrations/nrecho-v4 | ||
extratesting: go get -u github.com/labstack/echo/v4@master | ||
extratesting: go get -u github.com/labstack/echo@master | ||
- go-version: 1.15.x | ||
dirs: v3/integrations/nrelasticsearch-v7 | ||
extratesting: go get -u github.com/elastic/go-elasticsearch/[email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"log" | ||
"os" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go-v2/aws" | ||
"github.com/aws/aws-sdk-go-v2/config" | ||
"github.com/aws/aws-sdk-go-v2/service/s3" | ||
nraws "github.com/newrelic/go-agent/v3/integrations/nrawssdk-v2" | ||
"github.com/newrelic/go-agent/v3/newrelic" | ||
) | ||
|
||
func main() { | ||
|
||
// Create a New Relic application. This will look for your license key in an | ||
// environment varluable called NEW_RELIC_LICENSE_KEY. This example turns on | ||
// Distributed Tracing, but that's not required. | ||
app, err := newrelic.NewApplication( | ||
newrelic.ConfigFromEnvironment(), | ||
newrelic.ConfigAppName("Example App"), | ||
newrelic.ConfigInfoLogger(os.Stdout), | ||
newrelic.ConfigDistributedTracerEnabled(true), | ||
) | ||
if nil != err { | ||
fmt.Println(err) | ||
os.Exit(1) | ||
} | ||
|
||
// For demo purposes only. Don't use the app.WaitForConnection call in | ||
// production unless this is a very short-lived process and the caller | ||
// doesn't block or exit if there's an error. | ||
app.WaitForConnection(5 * time.Second) | ||
|
||
// Start recording a New Relic transaction | ||
txn := app.StartTransaction("My sample transaction") | ||
|
||
ctx := context.Background() | ||
awsConfig, err := config.LoadDefaultConfig(ctx) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// Instrument all new AWS clients with New Relic | ||
nraws.AppendMiddlewares(&awsConfig.APIOptions, txn) | ||
|
||
s3Client := s3.NewFromConfig(awsConfig) | ||
output, err := s3Client.ListBuckets(ctx, nil) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
for _, object := range output.Buckets { | ||
log.Printf("Bucket name is %s\n", aws.ToString(object.Name)) | ||
} | ||
|
||
// End the New Relic transaction | ||
txn.End() | ||
|
||
// Force all the harvests and shutdown. Like the app.WaitForConnection call | ||
// above, this is for the purposes of this demo only and can be safely | ||
// removed for longer-running processes. | ||
app.Shutdown(10 * time.Second) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,18 @@ | ||
module github.com/newrelic/go-agent/v3/integrations/nrawssdk-v2 | ||
|
||
// As of Dec 2019, the aws-sdk-go-v2 go.mod file uses 1.12: | ||
// As of May 2021, the aws-sdk-go-v2 go.mod file uses 1.15: | ||
// https://github.com/aws/aws-sdk-go-v2/blob/master/go.mod | ||
go 1.12 | ||
go 1.15 | ||
|
||
replace github.com/newrelic/go-agent/v3 => ../../ | ||
|
||
require ( | ||
// v0.8.0 is the earliest aws-sdk-go-v2 version where | ||
// dynamodb.DescribeTableRequest.Send takes a context.Context parameter. | ||
github.com/aws/aws-sdk-go-v2 v0.8.0 | ||
github.com/aws/aws-sdk-go-v2 v1.4.0 | ||
github.com/aws/aws-sdk-go-v2/config v1.1.7 | ||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.2.3 | ||
github.com/aws/aws-sdk-go-v2/service/lambda v1.2.3 | ||
github.com/aws/aws-sdk-go-v2/service/s3 v1.6.0 | ||
github.com/aws/smithy-go v1.4.0 | ||
github.com/newrelic/go-agent/v3 v3.0.0 | ||
golang.org/x/tools v0.1.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,88 +1,124 @@ | ||
// Copyright 2020 New Relic Corporation. All rights reserved. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// Copyright The OpenTelemetry Authors | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Package nrawssdk instruments https://github.com/aws/aws-sdk-go-v2 requests. | ||
// Package nrawssdk instruments requests made by the | ||
// https://github.com/aws/aws-sdk-go-v2 library. | ||
// | ||
// For most operations, external segments and spans are automatically created | ||
// for display in the New Relic UI on the External services section. For | ||
// DynamoDB operations, datastore segements and spans are created and will be | ||
// displayed on the Databases page. All operations will also be displayed on | ||
// transaction traces and distributed traces. | ||
// | ||
// To use this integration, simply apply the AppendMiddlewares fuction to the apiOptions in | ||
// your AWS Config object before performing any AWS operations. See | ||
// example/main.go for a working sample. | ||
package nrawssdk | ||
|
||
import ( | ||
"github.com/aws/aws-sdk-go-v2/aws" | ||
"github.com/newrelic/go-agent/v3/internal" | ||
"github.com/newrelic/go-agent/v3/internal/awssupport" | ||
) | ||
"context" | ||
"strconv" | ||
|
||
func init() { internal.TrackUsage("integration", "library", "aws-sdk-go-v2") } | ||
awsmiddle "github.com/aws/aws-sdk-go-v2/aws/middleware" | ||
smithymiddle "github.com/aws/smithy-go/middleware" | ||
smithyhttp "github.com/aws/smithy-go/transport/http" | ||
"github.com/newrelic/go-agent/v3/internal/integrationsupport" | ||
"github.com/newrelic/go-agent/v3/newrelic" | ||
) | ||
|
||
func startSegment(req *aws.Request) { | ||
input := awssupport.StartSegmentInputs{ | ||
HTTPRequest: req.HTTPRequest, | ||
ServiceName: req.Metadata.ServiceName, | ||
Operation: req.Operation.Name, | ||
Region: req.Metadata.SigningRegion, | ||
Params: req.Params, | ||
} | ||
req.HTTPRequest = awssupport.StartSegment(input) | ||
type nrMiddleware struct { | ||
txn *newrelic.Transaction | ||
} | ||
|
||
func endSegment(req *aws.Request) { | ||
ctx := req.HTTPRequest.Context() | ||
awssupport.EndSegment(ctx, req.HTTPResponse.Header) | ||
type endable interface{ End() } | ||
|
||
// See https://aws.github.io/aws-sdk-go-v2/docs/middleware/ for a description of | ||
// AWS SDK V2 middleware. | ||
func (m nrMiddleware) deserializeMiddleware(stack *smithymiddle.Stack) error { | ||
return stack.Deserialize.Add(smithymiddle.DeserializeMiddlewareFunc("NRDeserializeMiddleware", func( | ||
ctx context.Context, in smithymiddle.DeserializeInput, next smithymiddle.DeserializeHandler) ( | ||
out smithymiddle.DeserializeOutput, metadata smithymiddle.Metadata, err error) { | ||
|
||
smithyRequest := in.Request.(*smithyhttp.Request) | ||
|
||
// The actual http.Request is inside the smithyhttp.Request | ||
httpRequest := smithyRequest.Request | ||
serviceName := awsmiddle.GetServiceID(ctx) | ||
operation := awsmiddle.GetOperationName(ctx) | ||
region := awsmiddle.GetRegion(ctx) | ||
|
||
var segment endable | ||
// Service name capitalization is different for v1 and v2. | ||
if serviceName == "dynamodb" || serviceName == "DynamoDB" { | ||
segment = &newrelic.DatastoreSegment{ | ||
Product: newrelic.DatastoreDynamoDB, | ||
Collection: "", // AWS SDK V2 doesn't expose TableName | ||
Operation: operation, | ||
ParameterizedQuery: "", | ||
QueryParameters: nil, | ||
Host: httpRequest.URL.Host, | ||
PortPathOrID: httpRequest.URL.Port(), | ||
DatabaseName: "", | ||
StartTime: m.txn.StartSegmentNow(), | ||
} | ||
} else { | ||
segment = newrelic.StartExternalSegment(m.txn, httpRequest) | ||
} | ||
|
||
// Hand off execution to other middlewares and then perform the request | ||
out, metadata, err = next.HandleDeserialize(ctx, in) | ||
|
||
// After the request | ||
response, ok := out.RawResponse.(*smithyhttp.Response) | ||
|
||
if ok { | ||
// Set additional span attributes | ||
integrationsupport.AddAgentSpanAttribute(m.txn, | ||
newrelic.AttributeResponseCode, strconv.Itoa(response.StatusCode)) | ||
integrationsupport.AddAgentSpanAttribute(m.txn, | ||
newrelic.SpanAttributeAWSOperation, operation) | ||
integrationsupport.AddAgentSpanAttribute(m.txn, | ||
newrelic.SpanAttributeAWSRegion, region) | ||
requestID, ok := awsmiddle.GetRequestIDMetadata(metadata) | ||
if ok { | ||
integrationsupport.AddAgentSpanAttribute(m.txn, | ||
newrelic.AttributeAWSRequestID, requestID) | ||
} | ||
} | ||
segment.End() | ||
return out, metadata, err | ||
}), | ||
smithymiddle.Before) | ||
} | ||
|
||
// InstrumentHandlers will add instrumentation to the given *aws.Handlers. | ||
// | ||
// A Segment will be created for each out going request. The Transaction must | ||
// be added to the `http.Request`'s Context in order for the segment to be | ||
// recorded. For DynamoDB calls, these segments will be | ||
// `newrelic.DatastoreSegment` type and for all others they will be | ||
// `newrelic.ExternalSegment` type. | ||
// | ||
// Additional attributes will be added to Transaction Trace Segments and Span | ||
// Events: aws.region, aws.requestId, and aws.operation. | ||
// | ||
// To add instrumentation to a Config and see segments created for each | ||
// invocation that uses that Config, call InstrumentHandlers with the config's | ||
// Handlers and add the current Transaction to the `http.Request`'s Context: | ||
// | ||
// cfg, _ := external.LoadDefaultAWSConfig() | ||
// cfg.Region = "us-west-2" | ||
// // Add instrumentation to handlers | ||
// nrawssdk.InstrumentHandlers(&cfg.Handlers) | ||
// lambdaClient = lambda.New(cfg) | ||
// AppendMiddlewares inserts New Relic middleware in the given `apiOptions` for | ||
// the AWS SDK V2 for Go. It must be called only once per AWS configuration. | ||
// | ||
// req := lambdaClient.InvokeRequest(&lambda.InvokeInput{ | ||
// ClientContext: aws.String("MyApp"), | ||
// FunctionName: aws.String("Function"), | ||
// InvocationType: lambda.InvocationTypeEvent, | ||
// LogType: lambda.LogTypeTail, | ||
// Payload: []byte("{}"), | ||
// } | ||
// // Add txn to http.Request's context | ||
// ctx := newrelic.NewContext(req.Context(), txn) | ||
// resp, err := req.Send(ctx) | ||
// Additional attributes will be added to transaction trace segments and span | ||
// events: aws.region, aws.requestId, and aws.operation. In addition, | ||
// http.statusCode will be added to span events. | ||
// | ||
// To add instrumentation to a Request and see a segment created just for the | ||
// individual request, call InstrumentHandlers with the `aws.Request`'s | ||
// Handlers and add the current Transaction to the `http.Request`'s Context: | ||
// To see segments and spans for each AWS invocation, call AppendMiddlewares | ||
// with the AWS Config `apiOptions` and pass in your current New Relic | ||
// transaction. For example: | ||
// | ||
// req := lambdaClient.InvokeRequest(&lambda.InvokeInput{ | ||
// ClientContext: aws.String("MyApp"), | ||
// FunctionName: aws.String("Function"), | ||
// InvocationType: lambda.InvocationTypeEvent, | ||
// LogType: lambda.LogTypeTail, | ||
// Payload: []byte("{}"), | ||
// } | ||
// // Add instrumentation to handlers | ||
// nrawssdk.InstrumentHandlers(&req.Handlers) | ||
// // Add txn to http.Request's context | ||
// ctx := newrelic.NewContext(req.Context(), txn) | ||
// resp, err := req.Send(ctx) | ||
func InstrumentHandlers(handlers *aws.Handlers) { | ||
handlers.Send.SetFrontNamed(aws.NamedHandler{ | ||
Name: "StartNewRelicSegment", | ||
Fn: startSegment, | ||
}) | ||
handlers.Send.SetBackNamed(aws.NamedHandler{ | ||
Name: "EndNewRelicSegment", | ||
Fn: endSegment, | ||
}) | ||
// awsConfig, err := config.LoadDefaultConfig(ctx) | ||
// if err != nil { | ||
// log.Fatal(err) | ||
// } | ||
// nraws.AppendMiddlewares(ctx, &awsConfig.APIOptions, txn) | ||
func AppendMiddlewares(apiOptions *[]func(*smithymiddle.Stack) error, txn *newrelic.Transaction) { | ||
m := nrMiddleware{txn: txn} | ||
*apiOptions = append(*apiOptions, m.deserializeMiddleware) | ||
} |
Oops, something went wrong.