Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

End to end tracing support - Lambda #983

Merged
merged 66 commits into from
Oct 25, 2021
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
dcc01de
added failure scenario when getting container fails
bhautikpip Feb 5, 2021
1dd54d9
fix test case failure
bhautikpip Feb 5, 2021
03f6fb4
add changelog
bhautikpip Feb 5, 2021
5919be5
Merge branch 'main' into main
bhautikpip Feb 5, 2021
ebd45b4
Merge branch 'main' into main
Aneurysm9 Feb 5, 2021
e1ff7d0
fix ecs resource detector bug
bhautikpip Feb 7, 2021
041d9b8
Merge branch 'main' of https://github.com/bhautikpip/opentelemetry-go…
bhautikpip Feb 7, 2021
e12a4b1
fix struct name as per golint suggestion
bhautikpip Feb 7, 2021
e906d2a
fix merge conflict
bhautikpip Feb 7, 2021
86c04d1
minor changes
bhautikpip Feb 7, 2021
047f5d0
added NewResourceDetector func and interface assertions
bhautikpip Feb 9, 2021
21db8fa
fix golint failure
bhautikpip Feb 9, 2021
5204d27
minor changes to address review comments
bhautikpip Feb 10, 2021
c9c1bca
Merge branch 'main' into main
MrAlias Feb 10, 2021
c956d4b
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Feb 10, 2021
12c6c74
Merge branch 'main' of https://github.com/bhautikpip/opentelemetry-go…
bhautikpip Feb 10, 2021
e042a6f
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Jun 3, 2021
1f6b745
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Jun 15, 2021
76a52a1
Implement Lambda instrumentation
garrettwegan Jul 22, 2021
f0ec58b
Merge branch 'open-telemetry:main' into main
garrettwegan Jul 22, 2021
f048e4b
Fix filepath
garrettwegan Jul 22, 2021
23638fb
Add Lambda Dependabot checks
garrettwegan Jul 22, 2021
439023e
Fix filepath from copy
garrettwegan Jul 22, 2021
f7ac5db
Decouple SDK from instrumentation
garrettwegan Jul 23, 2021
e932685
Improve usage of make
garrettwegan Jul 23, 2021
8c86bb4
Improve comment clarity
garrettwegan Jul 23, 2021
debba6c
Minor refactoring
garrettwegan Jul 23, 2021
d481dcb
Add example
garrettwegan Jul 26, 2021
fedb803
Add license
garrettwegan Jul 26, 2021
38a9e91
Add gomod checks for otellambda /example and /test modules
garrettwegan Jul 26, 2021
6cc43b2
Refactor entrypoints into seperate files and update entrypoint names
garrettwegan Jul 26, 2021
f0b4a7f
Remove redundant computations of lambda resources
garrettwegan Jul 26, 2021
6df424c
Create and store tracer upon entry
garrettwegan Jul 26, 2021
5b70dfe
Rename handler function wrapper to WrapHandlerFunction
garrettwegan Jul 27, 2021
9de0d34
Add go doc
garrettwegan Jul 27, 2021
51144f5
Correct for wrapper name changes
garrettwegan Jul 27, 2021
8f8e491
Further decouple instrumentation from SDK by supporting custom propag…
garrettwegan Jul 28, 2021
d3d2c18
Go format
garrettwegan Jul 28, 2021
e572b7b
Improve HTTP tracing usage
garrettwegan Jul 28, 2021
ac8b307
Bump dependencies for RC2
garrettwegan Jul 28, 2021
24c9108
Fix typo
garrettwegan Jul 28, 2021
7b4a00e
Refactor configuration design
garrettwegan Jul 28, 2021
2c391fc
Bump dependencies to RC2
garrettwegan Jul 28, 2021
b64863e
Add package READMEs
garrettwegan Jul 28, 2021
e463802
Downgrade go version to 1.15 for CI
garrettwegan Jul 28, 2021
804939b
Minor refactoring
garrettwegan Jul 28, 2021
0f51b45
Merge branch 'open-telemetry:main' into main
garrettwegan Jul 30, 2021
8226dd3
Add AWS Lambda Instrumentation - update CHANGELOG
garrettwegan Jul 30, 2021
986e366
Rename EventToTextMapCarrierConverter to EventToCarrier
garrettwegan Jul 30, 2021
af8a871
Merge branch 'main' into main
Aneurysm9 Aug 10, 2021
8e2c1de
Merge remote-tracking branch 'upstream/main'
garrettwegan Aug 11, 2021
8c53555
Merge branch 'open-telemetry:main' into main
garrettwegan Aug 12, 2021
e2a18cc
Merge branch 'main' into main
garrettwegan Aug 12, 2021
ada0137
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Aug 12, 2021
1a0457f
Merge branch 'main' of https://github.com/garrettwegan/opentelemetry-…
bhautikpip Aug 12, 2021
1754a23
Update CHANGELOG.md
bhautikpip Aug 13, 2021
8445736
Merge branch 'main' into tracing-support-lambda
bhautikpip Aug 13, 2021
c0c6f30
rebase and fix merge conflict with main branch
bhautikpip Oct 13, 2021
92b045b
updated dependencies to latest version
bhautikpip Oct 13, 2021
4df95c7
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Oct 19, 2021
93e9916
added logging library and minor changes
bhautikpip Oct 19, 2021
bd387fd
Merge branch 'main' of https://github.com/open-telemetry/opentelemetr…
bhautikpip Oct 21, 2021
cbc1242
modified lambda handler function name
bhautikpip Oct 21, 2021
8ee0d8a
Merge branch 'main' into tracing-support-lambda
Aneurysm9 Oct 25, 2021
8dd0fe8
Update detectors/aws/lambda/detector.go
Aneurysm9 Oct 25, 2021
fa51016
Merge branch 'main' into tracing-support-lambda
Aneurysm9 Oct 25, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ updates:
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/detectors/aws/lambda"
labels:
- dependencies
- go
- "Skip Changelog"
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/detectors/aws/ec2"
Expand Down Expand Up @@ -174,6 +184,36 @@ updates:
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/instrumentation/github.com/aws/aws-lambda-go/otellambda"
labels:
- dependencies
- go
- "Skip Changelog"
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/instrumentation/github.com/aws/aws-lambda-go/otellambda/example"
labels:
- dependencies
- go
- "Skip Changelog"
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/instrumentation/github.com/aws/aws-lambda-go/otellambda/test"
labels:
- dependencies
- go
- "Skip Changelog"
schedule:
interval: "weekly"
day: "sunday"
-
package-ecosystem: "gomod"
directory: "/instrumentation/github.com/bradfitz/gomemcache/memcache/otelmemcache"
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm

### Added

- Add instrumentation for the `github.com/aws/aws-lambda-go` package. (#983)
- Add resource detector for AWS Lambda. (#983)
- Add `WithTracerProvider` option for `otelhttptrace.NewClientTrace`. (#1128)


Expand Down
67 changes: 67 additions & 0 deletions detectors/aws/lambda/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# OpenTelemetry AWS Lambda Resource Detector for Golang

[![Go Reference][goref-image]][goref-url]
[![Apache License][license-image]][license-url]

This module detects resource attributes available in AWS Lambda.

## Installation

```bash
go get -u go.opentelemetry.io/contrib/detectors/aws/lambda
```

## Usage

Create a sample Lambda Go application such as below.

```go
package main

import (
"github.com/aws/aws-lambda-go/lambda"
sdktrace "go.opencensus.io/otel/sdk/trace"
lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda"
)

func main() {
detector := lambdadetector.NewResourceDetector()
res, err := detector.Detect(context.Background())
if err != nil {
fmt.Printf("failed to detect lambda resources: %v\n", err)
}

tp := sdktrace.NewTracerProvider(
sdktrace.WithResource(res),
)
lambda.Start(<some lambda handler>)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the example need either otel.SetTracerProvider(tp) or passing tp explicitly into the Lambda handler? Otherwise the variable is unused.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, made a suggestion

Copy link
Contributor

@willarmiros willarmiros Sep 24, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
lambda.Start(<some lambda handler>)
otel.SetTracerProvider(tp)
lambda.Start(myHandler)

}
```

Now your `TracerProvider` will have the following resource attributes and attach them to new spans:

| Resource Attribute | Example Value |
| --- | --- |
| `cloud.provider` | aws
|`cloud.region` | us-east-1
|`faas.name` | MyLambdaFunction
|`faas.version` | $LATEST

Of note, `faas.id` and `cloud.account.id` are not set by the Lambda resource detector because they are not available outside a Lambda invocation. For this reason, when using the AWS Lambda Instrumentation these attributes are set as additional span attributes.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this be solved through lazy initialization?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not without asking the user to add more code. The faas.id and cloud.account.id attributes are only available inside of the handler, and our solution is meant to be strictly a wrapper of the handler such that we can't actually do anything inside the wrapper. So we could ask the user to lazy-initialize the tracer provider in their handler, but that's a much worse experience.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would the user have to do that lazy-initialization, rather than the framework? E.g., at this point it seems like you'd have access to those invocation-scoped variables. It's true that you'd have to do separately for each possible reflective type of the handler function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the problem is that we will then couple the Lambda resource detector and the Lambda instrumentation, which ought to be two separate components. The Lambda instrumentation does indeed have access to those invocation-scoped attributes, and is able to initialize the tracer provider. But the Lambda resource detector must operate only with what is available in the static environment, so if a user wants to initialize a custom tracer provider outside their handler as seen in the example it will work the same.

I agree that it's unfortunate the lambda resource detector doesn't capture these attributes, but I believe this is a limitation of Lambda itself more than any individual instrumentation, which is why the span attribute is called out in the spec and there's talks of not even marking faas.id as a resource attribute at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for explaining. I was commenting based on "what would an operator find most useful" vs "what is a clean way to factor the code." Given the ambiguity / ongoing discussion around faas.id, I think this code makes a reasonable choice.


## Useful links

- For more on FaaS attribute conventions, visit <https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/faas.md>
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>
- For more about OpenTelemetry Go: <https://github.com/open-telemetry/opentelemetry-go>
- For help or feedback on this project, join us in [GitHub Discussions][discussions-url]

## License

Apache 2.0 - See [LICENSE][license-url] for more information.

[license-url]: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/LICENSE
[license-image]: https://img.shields.io/badge/license-Apache_2.0-green.svg?style=flat
[goref-image]: https://pkg.go.dev/badge/go.opentelemetry.io/contrib/detectors/aws/lambda.svg
[goref-url]: https://pkg.go.dev/go.opentelemetry.io/contrib/detectors/aws/lambda
[discussions-url]: https://github.com/open-telemetry/opentelemetry-go/discussions
68 changes: 68 additions & 0 deletions detectors/aws/lambda/detector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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 lambda

import (
"context"
"errors"
"os"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

const (
Aneurysm9 marked this conversation as resolved.
Show resolved Hide resolved
lambdaFunctionNameEnvVar = "AWS_LAMBDA_FUNCTION_NAME"
Aneurysm9 marked this conversation as resolved.
Show resolved Hide resolved
awsRegionEnvVar = "AWS_REGION"
lambdaFunctionVersionEnvVar = "AWS_LAMBDA_FUNCTION_VERSION"
)

var (
empty = resource.Empty()
errNotOnLambda = errors.New("process is not on Lambda, cannot detect environment variables from Lambda")
)

// resource detector collects resource information from Lambda environment
type resourceDetector struct{}

// compile time assertion that resource detector implements the resource.Detector interface.
var _ resource.Detector = (*resourceDetector)(nil)

// NewResourceDetector returns a resource detector that will detect AWS Lambda resources.
func NewResourceDetector() resource.Detector {
return &resourceDetector{}
}

// Detect collects resource attributes available when running on lambda
func (detector *resourceDetector) Detect(context.Context) (*resource.Resource, error) {

// Lambda resources come from ENV
lambdaName := os.Getenv(lambdaFunctionNameEnvVar)
if len(lambdaName) == 0 {
return empty, errNotOnLambda
}
awsRegion := os.Getenv(awsRegionEnvVar)
functionVersion := os.Getenv(lambdaFunctionVersionEnvVar)

attrs := []attribute.KeyValue{
semconv.CloudProviderAWS,
semconv.CloudRegionKey.String(awsRegion),
semconv.FaaSNameKey.String(lambdaName),
semconv.FaaSVersionKey.String(functionVersion),
}

return resource.NewWithAttributes(semconv.SchemaURL, attrs...), nil
}
58 changes: 58 additions & 0 deletions detectors/aws/lambda/detector_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// 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 lambda

import (
"context"
"os"
"testing"

"github.com/stretchr/testify/assert"

"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/resource"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)

// successfully return resource when process is running on Amazon Lambda environment
func TestDetectSuccess(t *testing.T) {
os.Clearenv()
_ = os.Setenv(lambdaFunctionNameEnvVar, "testFunction")
_ = os.Setenv(awsRegionEnvVar, "us-texas-1")
_ = os.Setenv(lambdaFunctionVersionEnvVar, "$LATEST")

attributes := []attribute.KeyValue{
semconv.CloudProviderAWS,
semconv.CloudRegionKey.String("us-texas-1"),
semconv.FaaSNameKey.String("testFunction"),
semconv.FaaSVersionKey.String("$LATEST"),
}
expectedResource := resource.NewWithAttributes(semconv.SchemaURL, attributes...)
detector := resourceDetector{}
res, err := detector.Detect(context.Background())

assert.Nil(t, err, "Detector unexpectedly returned error")
assert.Equal(t, expectedResource, res, "Resource returned is incorrect")
}

// return empty resource when not running on lambda
func TestReturnsIfNoEnvVars(t *testing.T) {
os.Clearenv()
detector := resourceDetector{}
res, err := detector.Detect(context.Background())

assert.Equal(t, errNotOnLambda, err)
assert.Equal(t, 0, len(res.Attributes()))
}
11 changes: 11 additions & 0 deletions detectors/aws/lambda/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module go.opentelemetry.io/contrib/detectors/aws/lambda

go 1.15

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/stretchr/testify v1.7.0
go.opentelemetry.io/otel v1.0.1
go.opentelemetry.io/otel/sdk v1.0.1
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect
)
25 changes: 25 additions & 0 deletions detectors/aws/lambda/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc=
go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU=
go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA=
go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI=
go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw=
go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Loading