From dcc01deec2b6f27a5af3e5e3ecbb7f93f5fb0f8a Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Thu, 4 Feb 2021 16:21:40 -0800 Subject: [PATCH 01/43] added failure scenario when getting container fails --- detectors/aws/ecs/ecs.go | 7 ++++++- detectors/aws/ecs/ecs_test.go | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index dcc11955b91..82eb201f142 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -37,6 +37,7 @@ const ( var ( empty = resource.Empty() errCannotReadContainerID = errors.New("failed to read container ID from cGroupFile") + errCannotReadContainerName = errors.New("failed to read hostname") errCannotReadCGroupFile = errors.New("ECS resource detector failed to read cGroupFile") errNotOnECS = errors.New("process is not on ECS, cannot detect environment variables from ECS") ) @@ -102,5 +103,9 @@ func (ecsUtils ecsDetectorUtils) getContainerID() (string, error) { // returns host name reported by the kernel func (ecsUtils ecsDetectorUtils) getContainerName() (string, error) { - return os.Hostname() + hostName, err := os.Hostname() + if err != nil { + return "", errCannotReadContainerName + } + return hostName, nil } diff --git a/detectors/aws/ecs/ecs_test.go b/detectors/aws/ecs/ecs_test.go index 85cbb131288..7d667c35f3b 100644 --- a/detectors/aws/ecs/ecs_test.go +++ b/detectors/aws/ecs/ecs_test.go @@ -81,6 +81,23 @@ func TestDetectCannotReadContainerID(t *testing.T) { assert.Equal(t, 0, len(resource.Attributes())) } +//returns empty resource when detector cannot read container Name +func TestDetectCannotReadContainerName(t *testing.T) { + os.Clearenv() + os.Setenv(metadataV3EnvVar, "3") + os.Setenv(metadataV4EnvVar, "4") + detectorUtils := new(MockDetectorUtils) + + detectorUtils.On("getContainerName").Return("", errCannotReadContainerName) + detectorUtils.On("getContainerID").Return("0123456789A", nil) + + detector := ResourceDetector{detectorUtils} + resource, err := detector.Detect(context.Background()) + + assert.Equal(t, errCannotReadContainerName, err) + assert.Equal(t, 0, len(resource.Attributes())) +} + //returns empty resource when process is not running ECS func TestReturnsIfNoEnvVars(t *testing.T) { os.Clearenv() From 1dd54d977a8dce0027f0ff4a79afa1aa9c49eaaf Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Thu, 4 Feb 2021 16:57:07 -0800 Subject: [PATCH 02/43] fix test case failure --- detectors/aws/ecs/ecs.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index 82eb201f142..1bf477345d1 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -35,11 +35,11 @@ const ( ) var ( - empty = resource.Empty() - errCannotReadContainerID = errors.New("failed to read container ID from cGroupFile") - errCannotReadContainerName = errors.New("failed to read hostname") - errCannotReadCGroupFile = errors.New("ECS resource detector failed to read cGroupFile") - errNotOnECS = errors.New("process is not on ECS, cannot detect environment variables from ECS") + empty = resource.Empty() + errCannotReadContainerID = errors.New("failed to read container ID from cGroupFile") + errCannotReadContainerName = errors.New("failed to read hostname") + errCannotReadCGroupFile = errors.New("ECS resource detector failed to read cGroupFile") + errNotOnECS = errors.New("process is not on ECS, cannot detect environment variables from ECS") ) // Create interface for methods needing to be mocked From 03f6fb4f99601c371279378a4c005dc4bf78867e Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Fri, 5 Feb 2021 10:45:07 -0800 Subject: [PATCH 03/43] add changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91b685de7d9..39bba122bb9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Fixed + +- Added failure message for AWS ECS resource detector for better debugging (#568) + ## [0.16.0] - 2021-01-13 ### Fixed From e1ff7d0404815b18be13c39521405cc7d731bfe1 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Sat, 6 Feb 2021 17:04:11 -0800 Subject: [PATCH 04/43] fix ecs resource detector bug --- detectors/aws/ecs/ecs.go | 18 ++++++------------ detectors/aws/ecs/ecs_test.go | 28 ++++++++++++++-------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index 1bf477345d1..02c2718d78a 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -49,19 +49,13 @@ type detectorUtils interface { } // struct implements detectorUtils interface -type ecsDetectorUtils struct{} +type EcsDetectorUtils struct{} // resource detector collects resource information from Elastic Container Service environment type ResourceDetector struct { - utils detectorUtils + Utils detectorUtils } -// compile time assertion that ecsDetectorUtils implements detectorUtils interface -var _ detectorUtils = (*ecsDetectorUtils)(nil) - -// compile time assertion that resource detector implements the resource.Detector interface. -var _ resource.Detector = (*ResourceDetector)(nil) - // Detect finds associated resources when running on ECS environment. func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { metadataURIV3 := os.Getenv(metadataV3EnvVar) @@ -70,11 +64,11 @@ func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resourc if len(metadataURIV3) == 0 && len(metadataURIV4) == 0 { return empty, errNotOnECS } - hostName, err := detector.utils.getContainerName() + hostName, err := detector.Utils.getContainerName() if err != nil { return empty, err } - containerID, err := detector.utils.getContainerID() + containerID, err := detector.Utils.getContainerID() if err != nil { return empty, err } @@ -87,7 +81,7 @@ func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resourc } // returns docker container ID from default c group path -func (ecsUtils ecsDetectorUtils) getContainerID() (string, error) { +func (ecsUtils EcsDetectorUtils) getContainerID() (string, error) { fileData, err := ioutil.ReadFile(defaultCgroupPath) if err != nil { return "", errCannotReadCGroupFile @@ -102,7 +96,7 @@ func (ecsUtils ecsDetectorUtils) getContainerID() (string, error) { } // returns host name reported by the kernel -func (ecsUtils ecsDetectorUtils) getContainerName() (string, error) { +func (ecsUtils EcsDetectorUtils) getContainerName() (string, error) { hostName, err := os.Hostname() if err != nil { return "", errCannotReadContainerName diff --git a/detectors/aws/ecs/ecs_test.go b/detectors/aws/ecs/ecs_test.go index 7d667c35f3b..045648ea035 100644 --- a/detectors/aws/ecs/ecs_test.go +++ b/detectors/aws/ecs/ecs_test.go @@ -45,8 +45,8 @@ func (detectorUtils *MockDetectorUtils) getContainerName() (string, error) { //succesfully return resource when process is running on Amazon ECS environment func TestDetect(t *testing.T) { os.Clearenv() - os.Setenv(metadataV3EnvVar, "3") - os.Setenv(metadataV4EnvVar, "4") + _ = os.Setenv(metadataV3EnvVar, "3") + _ = os.Setenv(metadataV4EnvVar, "4") detectorUtils := new(MockDetectorUtils) @@ -59,51 +59,51 @@ func TestDetect(t *testing.T) { } expectedResource := resource.NewWithAttributes(labels...) detector := ResourceDetector{detectorUtils} - resource, _ := detector.Detect(context.Background()) + res, _ := detector.Detect(context.Background()) - assert.Equal(t, resource, expectedResource, "Resource returned is incorrect") + assert.Equal(t, res, expectedResource, "Resource returned is incorrect") } //returns empty resource when detector cannot read container ID func TestDetectCannotReadContainerID(t *testing.T) { os.Clearenv() - os.Setenv(metadataV3EnvVar, "3") - os.Setenv(metadataV4EnvVar, "4") + _ = os.Setenv(metadataV3EnvVar, "3") + _ = os.Setenv(metadataV4EnvVar, "4") detectorUtils := new(MockDetectorUtils) detectorUtils.On("getContainerName").Return("container-Name", nil) detectorUtils.On("getContainerID").Return("", errCannotReadContainerID) detector := ResourceDetector{detectorUtils} - resource, err := detector.Detect(context.Background()) + res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerID, err) - assert.Equal(t, 0, len(resource.Attributes())) + assert.Equal(t, 0, len(res.Attributes())) } //returns empty resource when detector cannot read container Name func TestDetectCannotReadContainerName(t *testing.T) { os.Clearenv() - os.Setenv(metadataV3EnvVar, "3") - os.Setenv(metadataV4EnvVar, "4") + _ = os.Setenv(metadataV3EnvVar, "3") + _ = os.Setenv(metadataV4EnvVar, "4") detectorUtils := new(MockDetectorUtils) detectorUtils.On("getContainerName").Return("", errCannotReadContainerName) detectorUtils.On("getContainerID").Return("0123456789A", nil) detector := ResourceDetector{detectorUtils} - resource, err := detector.Detect(context.Background()) + res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerName, err) - assert.Equal(t, 0, len(resource.Attributes())) + assert.Equal(t, 0, len(res.Attributes())) } //returns empty resource when process is not running ECS func TestReturnsIfNoEnvVars(t *testing.T) { os.Clearenv() detector := ResourceDetector{} - resource, err := detector.Detect(context.Background()) + res, err := detector.Detect(context.Background()) assert.Equal(t, errNotOnECS, err) - assert.Equal(t, 0, len(resource.Attributes())) + assert.Equal(t, 0, len(res.Attributes())) } From e12a4b185593413d0d459ffcd5507b20362c4819 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Sat, 6 Feb 2021 17:17:55 -0800 Subject: [PATCH 05/43] fix struct name as per golint suggestion --- detectors/aws/ecs/ecs.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index 02c2718d78a..a319454e72b 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -43,17 +43,17 @@ var ( ) // Create interface for methods needing to be mocked -type detectorUtils interface { +type detectorUtilsResources interface { getContainerName() (string, error) getContainerID() (string, error) } // struct implements detectorUtils interface -type EcsDetectorUtils struct{} +type DetectorUtils struct{} // resource detector collects resource information from Elastic Container Service environment type ResourceDetector struct { - Utils detectorUtils + Utils detectorUtilsResources } // Detect finds associated resources when running on ECS environment. @@ -81,7 +81,7 @@ func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resourc } // returns docker container ID from default c group path -func (ecsUtils EcsDetectorUtils) getContainerID() (string, error) { +func (ecsUtils DetectorUtils) getContainerID() (string, error) { fileData, err := ioutil.ReadFile(defaultCgroupPath) if err != nil { return "", errCannotReadCGroupFile @@ -96,7 +96,7 @@ func (ecsUtils EcsDetectorUtils) getContainerID() (string, error) { } // returns host name reported by the kernel -func (ecsUtils EcsDetectorUtils) getContainerName() (string, error) { +func (ecsUtils DetectorUtils) getContainerName() (string, error) { hostName, err := os.Hostname() if err != nil { return "", errCannotReadContainerName From 86c04d1b71f1fcb56703afac36148503098553ec Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Sat, 6 Feb 2021 17:22:49 -0800 Subject: [PATCH 06/43] minor changes --- detectors/aws/ecs/ecs.go | 2 +- detectors/aws/ecs/ecs_test.go | 17 ----------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index a319454e72b..f6237a19f14 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -48,7 +48,7 @@ type detectorUtilsResources interface { getContainerID() (string, error) } -// struct implements detectorUtils interface +// struct implements detectorUtilsResources interface type DetectorUtils struct{} // resource detector collects resource information from Elastic Container Service environment diff --git a/detectors/aws/ecs/ecs_test.go b/detectors/aws/ecs/ecs_test.go index 86239f61a81..045648ea035 100644 --- a/detectors/aws/ecs/ecs_test.go +++ b/detectors/aws/ecs/ecs_test.go @@ -98,23 +98,6 @@ func TestDetectCannotReadContainerName(t *testing.T) { assert.Equal(t, 0, len(res.Attributes())) } -//returns empty resource when detector cannot read container Name -func TestDetectCannotReadContainerName(t *testing.T) { - os.Clearenv() - os.Setenv(metadataV3EnvVar, "3") - os.Setenv(metadataV4EnvVar, "4") - detectorUtils := new(MockDetectorUtils) - - detectorUtils.On("getContainerName").Return("", errCannotReadContainerName) - detectorUtils.On("getContainerID").Return("0123456789A", nil) - - detector := ResourceDetector{detectorUtils} - resource, err := detector.Detect(context.Background()) - - assert.Equal(t, errCannotReadContainerName, err) - assert.Equal(t, 0, len(resource.Attributes())) -} - //returns empty resource when process is not running ECS func TestReturnsIfNoEnvVars(t *testing.T) { os.Clearenv() From 047f5d0c663a283163d8d9154cff2c292bd76b0f Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Tue, 9 Feb 2021 09:58:45 -0800 Subject: [PATCH 07/43] added NewResourceDetector func and interface assertions --- detectors/aws/ecs/ecs.go | 21 ++++++++++++++++----- detectors/aws/ecs/ecs_test.go | 8 ++++---- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index f6237a19f14..5978b1476f7 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -52,23 +52,34 @@ type detectorUtilsResources interface { type DetectorUtils struct{} // resource detector collects resource information from Elastic Container Service environment -type ResourceDetector struct { - Utils detectorUtilsResources +type resourceDetector struct { + utils detectorUtilsResources +} + +// compile time assertion that ecsDetectorUtils implements detectorUtilsResources interface +var _ detectorUtilsResources = (*DetectorUtils)(nil) + +// compile time assertion that resource detector implements the resource.Detector interface. +var _ resource.Detector = (*resourceDetector)(nil) + +// returns resource detector struct +func NewResourceDetector(detectorUtils detectorUtilsResources) resourceDetector{ + return resourceDetector{utils: detectorUtils} } // Detect finds associated resources when running on ECS environment. -func (detector *ResourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { +func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resource, error) { metadataURIV3 := os.Getenv(metadataV3EnvVar) metadataURIV4 := os.Getenv(metadataV4EnvVar) if len(metadataURIV3) == 0 && len(metadataURIV4) == 0 { return empty, errNotOnECS } - hostName, err := detector.Utils.getContainerName() + hostName, err := detector.utils.getContainerName() if err != nil { return empty, err } - containerID, err := detector.Utils.getContainerID() + containerID, err := detector.utils.getContainerID() if err != nil { return empty, err } diff --git a/detectors/aws/ecs/ecs_test.go b/detectors/aws/ecs/ecs_test.go index 045648ea035..fda1d4ba210 100644 --- a/detectors/aws/ecs/ecs_test.go +++ b/detectors/aws/ecs/ecs_test.go @@ -58,7 +58,7 @@ func TestDetect(t *testing.T) { semconv.ContainerIDKey.String("0123456789A"), } expectedResource := resource.NewWithAttributes(labels...) - detector := ResourceDetector{detectorUtils} + detector := NewResourceDetector(detectorUtils) res, _ := detector.Detect(context.Background()) assert.Equal(t, res, expectedResource, "Resource returned is incorrect") @@ -74,7 +74,7 @@ func TestDetectCannotReadContainerID(t *testing.T) { detectorUtils.On("getContainerName").Return("container-Name", nil) detectorUtils.On("getContainerID").Return("", errCannotReadContainerID) - detector := ResourceDetector{detectorUtils} + detector := NewResourceDetector(detectorUtils) res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerID, err) @@ -91,7 +91,7 @@ func TestDetectCannotReadContainerName(t *testing.T) { detectorUtils.On("getContainerName").Return("", errCannotReadContainerName) detectorUtils.On("getContainerID").Return("0123456789A", nil) - detector := ResourceDetector{detectorUtils} + detector := NewResourceDetector(detectorUtils) res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerName, err) @@ -101,7 +101,7 @@ func TestDetectCannotReadContainerName(t *testing.T) { //returns empty resource when process is not running ECS func TestReturnsIfNoEnvVars(t *testing.T) { os.Clearenv() - detector := ResourceDetector{} + detector := NewResourceDetector(nil) res, err := detector.Detect(context.Background()) assert.Equal(t, errNotOnECS, err) From 21db8fabc829a60110299e36658c1f9039b704b7 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Tue, 9 Feb 2021 14:42:29 -0800 Subject: [PATCH 08/43] fix golint failure --- detectors/aws/ecs/ecs.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index 5978b1476f7..57376e876e9 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -63,8 +63,8 @@ var _ detectorUtilsResources = (*DetectorUtils)(nil) var _ resource.Detector = (*resourceDetector)(nil) // returns resource detector struct -func NewResourceDetector(detectorUtils detectorUtilsResources) resourceDetector{ - return resourceDetector{utils: detectorUtils} +func NewResourceDetector(detectorUtils detectorUtilsResources) resource.Detector { + return &resourceDetector{utils: detectorUtils} } // Detect finds associated resources when running on ECS environment. From 5204d27fd5ab645060c5f07d746404b6b8ca54df Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Tue, 9 Feb 2021 17:24:15 -0800 Subject: [PATCH 09/43] minor changes to address review comments --- detectors/aws/ecs/ecs.go | 22 +++++++++++----------- detectors/aws/ecs/ecs_test.go | 8 ++++---- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/detectors/aws/ecs/ecs.go b/detectors/aws/ecs/ecs.go index 57376e876e9..2e21bb080b0 100644 --- a/detectors/aws/ecs/ecs.go +++ b/detectors/aws/ecs/ecs.go @@ -43,28 +43,28 @@ var ( ) // Create interface for methods needing to be mocked -type detectorUtilsResources interface { +type detectorUtils interface { getContainerName() (string, error) getContainerID() (string, error) } -// struct implements detectorUtilsResources interface -type DetectorUtils struct{} +// struct implements detectorUtils interface +type ecsDetectorUtils struct{} // resource detector collects resource information from Elastic Container Service environment type resourceDetector struct { - utils detectorUtilsResources + utils detectorUtils } -// compile time assertion that ecsDetectorUtils implements detectorUtilsResources interface -var _ detectorUtilsResources = (*DetectorUtils)(nil) +// compile time assertion that ecsDetectorUtils implements detectorUtils interface +var _ detectorUtils = (*ecsDetectorUtils)(nil) // compile time assertion that resource detector implements the resource.Detector interface. var _ resource.Detector = (*resourceDetector)(nil) -// returns resource detector struct -func NewResourceDetector(detectorUtils detectorUtilsResources) resource.Detector { - return &resourceDetector{utils: detectorUtils} +// NewResourceDetector returns a resource detector that will detect AWS ECS resources. +func NewResourceDetector() resource.Detector { + return &resourceDetector{utils: ecsDetectorUtils{}} } // Detect finds associated resources when running on ECS environment. @@ -92,7 +92,7 @@ func (detector *resourceDetector) Detect(ctx context.Context) (*resource.Resourc } // returns docker container ID from default c group path -func (ecsUtils DetectorUtils) getContainerID() (string, error) { +func (ecsUtils ecsDetectorUtils) getContainerID() (string, error) { fileData, err := ioutil.ReadFile(defaultCgroupPath) if err != nil { return "", errCannotReadCGroupFile @@ -107,7 +107,7 @@ func (ecsUtils DetectorUtils) getContainerID() (string, error) { } // returns host name reported by the kernel -func (ecsUtils DetectorUtils) getContainerName() (string, error) { +func (ecsUtils ecsDetectorUtils) getContainerName() (string, error) { hostName, err := os.Hostname() if err != nil { return "", errCannotReadContainerName diff --git a/detectors/aws/ecs/ecs_test.go b/detectors/aws/ecs/ecs_test.go index fda1d4ba210..c7719102818 100644 --- a/detectors/aws/ecs/ecs_test.go +++ b/detectors/aws/ecs/ecs_test.go @@ -58,7 +58,7 @@ func TestDetect(t *testing.T) { semconv.ContainerIDKey.String("0123456789A"), } expectedResource := resource.NewWithAttributes(labels...) - detector := NewResourceDetector(detectorUtils) + detector := &resourceDetector{utils: detectorUtils} res, _ := detector.Detect(context.Background()) assert.Equal(t, res, expectedResource, "Resource returned is incorrect") @@ -74,7 +74,7 @@ func TestDetectCannotReadContainerID(t *testing.T) { detectorUtils.On("getContainerName").Return("container-Name", nil) detectorUtils.On("getContainerID").Return("", errCannotReadContainerID) - detector := NewResourceDetector(detectorUtils) + detector := &resourceDetector{utils: detectorUtils} res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerID, err) @@ -91,7 +91,7 @@ func TestDetectCannotReadContainerName(t *testing.T) { detectorUtils.On("getContainerName").Return("", errCannotReadContainerName) detectorUtils.On("getContainerID").Return("0123456789A", nil) - detector := NewResourceDetector(detectorUtils) + detector := &resourceDetector{utils: detectorUtils} res, err := detector.Detect(context.Background()) assert.Equal(t, errCannotReadContainerName, err) @@ -101,7 +101,7 @@ func TestDetectCannotReadContainerName(t *testing.T) { //returns empty resource when process is not running ECS func TestReturnsIfNoEnvVars(t *testing.T) { os.Clearenv() - detector := NewResourceDetector(nil) + detector := &resourceDetector{utils: nil} res, err := detector.Detect(context.Background()) assert.Equal(t, errNotOnECS, err) From 76a52a17d54c899a25e29a485c6bfb6180c548e3 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:26:30 -0700 Subject: [PATCH 10/43] Implement Lambda instrumentation --- detectors/aws/lambda/detector.go | 68 +++ detectors/aws/lambda/detector_test.go | 44 ++ detectors/aws/lambda/go.mod | 11 + detectors/aws/lambda/go.sum | 24 + .../github.com/aws/otellambda/go.mod | 19 + .../github.com/aws/otellambda/go.sum | 145 ++++++ .../github.com/aws/otellambda/lambda.go | 351 ++++++++++++++ .../github.com/aws/otellambda/lambda_test.go | 436 ++++++++++++++++++ 8 files changed, 1098 insertions(+) create mode 100644 detectors/aws/lambda/detector.go create mode 100644 detectors/aws/lambda/detector_test.go create mode 100644 detectors/aws/lambda/go.mod create mode 100644 detectors/aws/lambda/go.sum create mode 100644 instrumentation/github.com/aws/otellambda/go.mod create mode 100644 instrumentation/github.com/aws/otellambda/go.sum create mode 100644 instrumentation/github.com/aws/otellambda/lambda.go create mode 100644 instrumentation/github.com/aws/otellambda/lambda_test.go diff --git a/detectors/aws/lambda/detector.go b/detectors/aws/lambda/detector.go new file mode 100644 index 00000000000..4ede2576c04 --- /dev/null +++ b/detectors/aws/lambda/detector.go @@ -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 ( + lambdaFunctionNameEnvVar = "AWS_LAMBDA_FUNCTION_NAME" + 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 resources 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 +} diff --git a/detectors/aws/lambda/detector_test.go b/detectors/aws/lambda/detector_test.go new file mode 100644 index 00000000000..05048f15b59 --- /dev/null +++ b/detectors/aws/lambda/detector_test.go @@ -0,0 +1,44 @@ +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())) +} \ No newline at end of file diff --git a/detectors/aws/lambda/go.mod b/detectors/aws/lambda/go.mod new file mode 100644 index 00000000000..a1ba019067c --- /dev/null +++ b/detectors/aws/lambda/go.mod @@ -0,0 +1,11 @@ +module go.opentelemetry.io/contrib/detectors/aws/lambda + +go 1.16 + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/sdk v1.0.0-RC1 + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect +) diff --git a/detectors/aws/lambda/go.sum b/detectors/aws/lambda/go.sum new file mode 100644 index 00000000000..1d2f0c1f7c1 --- /dev/null +++ b/detectors/aws/lambda/go.sum @@ -0,0 +1,24 @@ +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.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +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= diff --git a/instrumentation/github.com/aws/otellambda/go.mod b/instrumentation/github.com/aws/otellambda/go.mod new file mode 100644 index 00000000000..34180b7a8d9 --- /dev/null +++ b/instrumentation/github.com/aws/otellambda/go.mod @@ -0,0 +1,19 @@ +module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda + +go 1.16 + +replace ( + go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../detectors/aws/lambda + go.opentelemetry.io/contrib/propagators/aws => ../../../../../propagators/aws +) + +require ( + github.com/aws/aws-lambda-go v1.24.0 + github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 + go.opentelemetry.io/contrib/propagators/aws v0.21.0 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1 + go.opentelemetry.io/otel/sdk v1.0.0-RC1 + go.opentelemetry.io/otel/trace v1.0.0-RC1 +) diff --git a/instrumentation/github.com/aws/otellambda/go.sum b/instrumentation/github.com/aws/otellambda/go.sum new file mode 100644 index 00000000000..10c48f9d998 --- /dev/null +++ b/instrumentation/github.com/aws/otellambda/go.sum @@ -0,0 +1,145 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/aws/aws-lambda-go v1.24.0 h1:bOMerM175hLqHLdF1Nonfv1NA20nTIatuC0HK8eMoYg= +github.com/aws/aws-lambda-go v1.24.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= +github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1 h1:GHKxjc4EDldz8ScMDpiNwX4BAub6wGFUUo5Axm2BimU= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1/go.mod h1:FliQjImlo7emZVjixV8nbDMAa4iAkcWTE9zzSEOiEPw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1 h1:ZOQXuxKJ9evGspu3LvbZxx3KOOQvKAPBJVMOfGf1cOM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1/go.mod h1:cDwRc2Jrh5Gku1peGK8p9rRuX/Uq2OtVmLicjlw2WYU= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= +go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/instrumentation/github.com/aws/otellambda/lambda.go b/instrumentation/github.com/aws/otellambda/lambda.go new file mode 100644 index 00000000000..1ef0271ebb0 --- /dev/null +++ b/instrumentation/github.com/aws/otellambda/lambda.go @@ -0,0 +1,351 @@ +package otellambda + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "reflect" + "runtime" + "strings" + + "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-lambda-go/lambdacontext" + + lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" + "go.opentelemetry.io/contrib/propagators/aws/xray" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" + "go.opentelemetry.io/otel/propagation" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "go.opentelemetry.io/otel/trace" +) + +const ( + tracerName = "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" +) + +var tp *sdktrace.TracerProvider +var errorLogger = log.New(log.Writer(), "OTel Lambda Error: ", 0) + +func init() { + otel.SetTextMapPropagator(xray.Propagator{}) +} + +func initTracerProvider() { + ctx := context.Background() + + exp, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure()) + if err != nil { + errorLogger.Printf("failed to initialize exporter: %v\n", err) + return + } + + detector := lambdadetector.NewResourceDetector() + res, err := detector.Detect(ctx) + if err != nil { + errorLogger.Printf("failed to detect lambda resources: %v\n", err) + return + } + + tp = sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exp), + sdktrace.WithIDGenerator(xray.NewIDGenerator()), + sdktrace.WithResource(res), + ) + + // Set the traceprovider + otel.SetTracerProvider(tp) +} + +func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { + return func(context.Context, interface{}) (interface{}, error) { + return nil, e + } +} + +// Ensure handler takes 0-2 values, with context +// as its first value if two arguments exist +func validateArguments(handler reflect.Type) (bool, error) { + handlerTakesContext := false + if handler.NumIn() > 2 { + return false, fmt.Errorf("handlers may not take more than two arguments, but handler takes %d", handler.NumIn()) + } else if handler.NumIn() > 0 { + contextType := reflect.TypeOf((*context.Context)(nil)).Elem() + argumentType := handler.In(0) + handlerTakesContext = argumentType.Implements(contextType) + if handler.NumIn() > 1 && !handlerTakesContext { + return false, fmt.Errorf("handler takes two arguments, but the first is not Context. got %s", argumentType.Kind()) + } + } + + return handlerTakesContext, nil +} + +// Ensure handler returns 0-2 values, with an error +// as its first value if any exist +func validateReturns(handler reflect.Type) error { + errorType := reflect.TypeOf((*error)(nil)).Elem() + + switch n := handler.NumOut(); { + case n > 2: + return fmt.Errorf("handler may not return more than two values") + case n > 1: + if !handler.Out(1).Implements(errorType) { + return fmt.Errorf("handler returns two values, but the second does not implement error") + } + case n == 1: + if !handler.Out(0).Implements(errorType) { + return fmt.Errorf("handler returns a single value, but it does not implement error") + } + } + + return nil +} + +// Wraps and calls customer lambda handler then unpacks response as necessary +func wrapperInternals(handlerFunc interface{}, event reflect.Value, ctx context.Context, takesContext bool) (interface{}, error) { + wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) + + argsWrapped := []reflect.Value{reflect.ValueOf(ctx), event, reflect.ValueOf(takesContext)} + response := wrappedLambdaHandler.Call(argsWrapped)[0].Interface().([]reflect.Value) + + // convert return values into (interface{}, error) + var err error + if len(response) > 0 { + if errVal, ok := response[len(response)-1].Interface().(error); ok { + err = errVal + } + } + var val interface{} + if len(response) > 1 { + val = response[0].Interface() + } + + return val, err +} + +// converts the given payload to the correct event type +func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, error) { + event := reflect.New(eventType) + + // lambda SDK normally unmarshalls to customer event type, however + // with the wrapper the SDK unmarshalls to map[string]interface{} + // due to our use of reflection. Therefore we must convert this map + // to customer's desired event, we do so by simply re-marshalling then + // unmarshalling to the desired event type + remarshalledPayload, err := json.Marshal(payload) + if err != nil { + return reflect.Value{}, err + } + + if err := json.Unmarshal(remarshalledPayload, event.Interface()); err != nil { + return reflect.Value{}, err + } + return event, nil +} + +// LambdaHandlerWrapper Provides a lambda handler which wraps customer lambda handler with OTel Tracing +func LambdaHandlerWrapper(handlerFunc interface{}) interface{} { + if handlerFunc == nil { + return errorHandler(fmt.Errorf("handler is nil")) + } + handlerType := reflect.TypeOf(handlerFunc) + if handlerType.Kind() != reflect.Func { + return errorHandler(fmt.Errorf("handler kind %s is not %s", handlerType.Kind(), reflect.Func)) + } + + takesContext, err := validateArguments(handlerType) + if err != nil { + return errorHandler(err) + } + + if err := validateReturns(handlerType); err != nil { + return errorHandler(err) + } + + // note we will always take context to capture lambda context, + // regardless of whether customer takes context + if handlerType.NumIn() == 0 || handlerType.NumIn() == 1 && takesContext { + return func(ctx context.Context) (interface{}, error) { + var temp *interface{} + event := reflect.ValueOf(temp) + return wrapperInternals(handlerFunc, event, ctx, takesContext) + } + } else { // customer either takes both context and payload or just payload + return func(ctx context.Context, payload interface{}) (interface{}, error) { + event, err := payloadToEvent(handlerType.In(handlerType.NumIn()-1), payload) + if err != nil { + return nil, err + } + return wrapperInternals(handlerFunc, event.Elem(), ctx, takesContext) + } + } +} + +// basic implementation of TextMapCarrier +// which wraps the default map type +type mapCarrier map[string]string + +// Compile time check our mapCarrier implements propagation.TextMapCarrier +var _ propagation.TextMapCarrier = mapCarrier{} + +// Get returns the value associated with the passed key. +func (mc mapCarrier) Get(key string) string { + return mc[key] +} + +// Set stores the key-value pair. +func (mc mapCarrier) Set(key string, value string) { + mc[key] = value +} + +// Keys lists the keys stored in this carrier. +func (mc mapCarrier) Keys() []string { + keys := make([]string, len(mc)) + i := 0 + for k := range mc { + keys[i] = k + i++ + } + return keys +} + +// Adds OTel span surrounding customer handler call +func wrapper(handlerFunc interface{}) func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { + return func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { + + ctx, span := tracingBegin(ctx) + defer tracingEnd(ctx, span) + + handler := reflect.ValueOf(handlerFunc) + var args []reflect.Value + if takesContext { + args = append(args, reflect.ValueOf(ctx)) + } + if eventExists(event) { + args = append(args, reflect.ValueOf(event)) + } + + response := handler.Call(args) + + return response + } +} + +// Determine if an interface{} is nil or the +// if the reflect.Value of the event is nil +func eventExists(event interface{}) bool { + if event == nil { + return false + } + + // reflect.Value.isNil() can only be called on + // Values of certain Kinds. Unsupported Kinds + // will panic rather than return false + switch reflect.TypeOf(event).Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: + return !reflect.ValueOf(event).IsNil() + } + return true +} + +type wrappedHandler struct { + handler lambda.Handler +} + +// Compile time check our Handler implements lambda.Handler +var _ lambda.Handler = wrappedHandler{} + +// Invoke adds OTel span surrounding customer Handler invocation +func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) { + + ctx, span := tracingBegin(ctx) + defer tracingEnd(ctx, span) + + response, err := h.handler.Invoke(ctx, payload) + if err != nil { + return nil, err + } + + return response, nil +} + +// HandlerWrapper Provides a Handler which wraps customer Handler with OTel Tracing +func HandlerWrapper(handler lambda.Handler) lambda.Handler { + return wrappedHandler{handler: handler} +} + +// Logic to start OTel Tracing +func tracingBegin(ctx context.Context) (context.Context, trace.Span) { + // Add trace id to context + xrayTraceId := os.Getenv("_X_AMZN_TRACE_ID") + mc := mapCarrier{} + mc.Set("X-Amzn-Trace-Id", xrayTraceId) + propagator := xray.Propagator{} + ctx = propagator.Extract(ctx, mc) + + // If tracer provider initialization failed we + // will attempt to initialize once per invocation + if tp == nil { + initTracerProvider() + } + + // if tracer provider successfully initializes then + // we add tracing, otherwise do customer business + // logic with no tracing + if tp != nil { + // Get a named tracer with package path as its name. + tracer := tp.Tracer(tracerName) + + var span trace.Span + spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") + + var attributes []attribute.KeyValue + lc, ok := lambdacontext.FromContext(ctx) + if !ok { + errorLogger.Println("failed to load lambda context from context, ensure tracing enabled in Lambda") + } + if lc != nil { + ctxRequestID := lc.AwsRequestID + attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSExecutionKey, Value: attribute.StringValue(ctxRequestID)}) + + // Resource attrs added as span attr due to static tp + // being created without meaningful context + ctxFunctionArn := lc.InvokedFunctionArn + attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSIDKey, Value: attribute.StringValue(ctxFunctionArn)}) + arnParts := strings.Split(ctxFunctionArn, ":") + if len(arnParts) >= 5 { + attributes = append(attributes, attribute.KeyValue{Key: semconv.CloudAccountIDKey, Value: attribute.StringValue(arnParts[4])}) + } + } + + ctx, span = tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) + + return ctx, span + } + return ctx, nil +} + +// Logic to wrap up OTel Tracing +func tracingEnd(ctx context.Context, span trace.Span) { + if tp != nil { + // span will be valid if tp is not nil + span.End() + + // yield processor to attempt to attempt to ensure + // all spans have been consumed and are ready to be + // flushed - see https://github.com/open-telemetry/opentelemetry-go/issues/2080 + // to be removed upon resolution of above issue + runtime.Gosched() + + // force flush any tracing data since lambda may freeze + err := tp.ForceFlush(ctx) + if err != nil { + errorLogger.Println("failed to force a flush, lambda may freeze before instrumentation exported: ", err) + } + } +} diff --git a/instrumentation/github.com/aws/otellambda/lambda_test.go b/instrumentation/github.com/aws/otellambda/lambda_test.go new file mode 100644 index 00000000000..a1ac6939b19 --- /dev/null +++ b/instrumentation/github.com/aws/otellambda/lambda_test.go @@ -0,0 +1,436 @@ +package otellambda + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "os" + "reflect" + "sync" + "testing" + "time" + + "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-lambda-go/lambda/messages" + "github.com/aws/aws-lambda-go/lambdacontext" + "github.com/stretchr/testify/assert" + + lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" + "go.opentelemetry.io/contrib/propagators/aws/xray" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "go.opentelemetry.io/otel/trace" +) + +var ( + mockLambdaContext = lambdacontext.LambdaContext{ + AwsRequestID: "123", + InvokedFunctionArn: "arn:partition:service:region:account-id:resource-type:resource-id", + Identity: lambdacontext.CognitoIdentity{ + CognitoIdentityID: "someId", + CognitoIdentityPoolID: "somePoolId", + }, + ClientContext: lambdacontext.ClientContext{}, + } + mockContext = xray.Propagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), + mapCarrier{ + "X-Amzn-Trace-Id": "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1", + }) +) + +type mockIdGenerator struct { + sync.Mutex + traceCount int + spanCount int +} + +func (m *mockIdGenerator) NewIDs(_ context.Context) (trace.TraceID, trace.SpanID) { + m.Lock() + defer m.Unlock() + m.traceCount += 1 + m.spanCount += 1 + return [16]byte{byte(m.traceCount)}, [8]byte{byte(m.spanCount)} +} + +func (m *mockIdGenerator) NewSpanID(_ context.Context, _ trace.TraceID) trace.SpanID { + m.Lock() + defer m.Unlock() + m.spanCount += 1 + return [8]byte{byte(m.spanCount)} +} + +var _ sdktrace.IDGenerator = &mockIdGenerator{} + +type emptyHandler struct{} + +func (h emptyHandler) Invoke(_ context.Context, _ []byte) ([]byte, error) { + return nil, nil +} + +var _ lambda.Handler = emptyHandler{} + +func initMockTracerProvider() *tracetest.InMemoryExporter { + ctx := context.Background() + + exp := tracetest.NewInMemoryExporter() + + detector := lambdadetector.NewResourceDetector() + res, err := detector.Detect(ctx) + if err != nil { + errorLogger.Printf("failed to detect lambda resources: %v\n", err) + return nil + } + + tp = sdktrace.NewTracerProvider( + sdktrace.WithSyncer(exp), + sdktrace.WithIDGenerator(&mockIdGenerator{}), + sdktrace.WithResource(res), + ) + + // Set the traceprovider + otel.SetTracerProvider(tp) + + return exp +} + +func setEnvVars() { + _ = os.Setenv("AWS_LAMBDA_FUNCTION_NAME", "testFunction") + _ = os.Setenv("AWS_REGION", "us-texas-1") + _ = os.Setenv("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST") + _ = os.Setenv("_X_AMZN_TRACE_ID", "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") +} + +func TestLambdaHandlerSignatures(t *testing.T) { + setEnvVars() + + // for these tests we do not care about the tracing and + // so we will ignore it the in memory span exporter + _ = initMockTracerProvider() + + emptyPayload := "" + testCases := []struct { + name string + handler interface{} + expected error + args []reflect.Value + }{ + { + name: "nil handler", + expected: errors.New("handler is nil"), + handler: nil, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "handler is not a function", + expected: errors.New("handler kind struct is not func"), + handler: struct{}{}, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "handler declares too many arguments", + expected: errors.New("handlers may not take more than two arguments, but handler takes 3"), + handler: func(n context.Context, x string, y string) error { + return nil + }, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "two argument handler does not have context as first argument", + expected: errors.New("handler takes two arguments, but the first is not Context. got string"), + handler: func(a string, x context.Context) error { + return nil + }, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "handler returns too many values", + expected: errors.New("handler may not return more than two values"), + handler: func() (error, error, error) { + return nil, nil, nil + }, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "handler returning two values does not declare error as the second return value", + expected: errors.New("handler returns two values, but the second does not implement error"), + handler: func() (error, string) { + return nil, "hello" + }, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "handler returning a single value does not implement error", + expected: errors.New("handler returns a single value, but it does not implement error"), + handler: func() string { + return "hello" + }, + args: []reflect.Value{reflect.ValueOf(mockContext), reflect.ValueOf(emptyPayload)}, + }, + { + name: "no args or return value should not result in error", + expected: nil, + handler: func() { + }, + args: []reflect.Value{reflect.ValueOf(mockContext)}, // reminder - customer takes no args but wrapped handler always takes context from lambda + }, + } + for i, testCase := range testCases { + testCase := testCase + t.Run(fmt.Sprintf("testCase[%d] %s", i, testCase.name), func(t *testing.T) { + lambdaHandler := LambdaHandlerWrapper(testCase.handler) + handler := reflect.ValueOf(lambdaHandler) + resp := handler.Call(testCase.args) + assert.Equal(t, 2, len(resp)) + assert.Equal(t, testCase.expected, resp[1].Interface()) + }) + } +} + +type expected struct { + val interface{} + err error +} + +func TestHandlerInvokes(t *testing.T) { + setEnvVars() + + // for these tests we do not care about the tracing and + // so we will ignore it the in memory span exporter + _ = initMockTracerProvider() + + hello := func(s string) string { + return fmt.Sprintf("Hello %s!", s) + } + + testCases := []struct { + name string + input interface{} + expected expected + handler interface{} + }{ + { + name: "string input and return without context", + input: "Lambda", + expected: expected{`"Hello Lambda!"`, nil}, + handler: func(name string) (string, error) { + return hello(name), nil + }, + }, + { + name: "string input and return with context", + input: "Lambda", + expected: expected{`"Hello Lambda!"`, nil}, + handler: func(ctx context.Context, name string) (string, error) { + return hello(name), nil + }, + }, + { + name: "no input with response event and simple error", + input: nil, + expected: expected{"", errors.New("bad stuff")}, + handler: func() (interface{}, error) { + return nil, errors.New("bad stuff") + }, + }, + { + name: "input with response event and simple error", + input: "Lambda", + expected: expected{"", errors.New("bad stuff")}, + handler: func(e interface{}) (interface{}, error) { + return nil, errors.New("bad stuff") + }, + }, + { + name: "input and context with response event and simple error", + input: "Lambda", + expected: expected{"", errors.New("bad stuff")}, + handler: func(ctx context.Context, e interface{}) (interface{}, error) { + return nil, errors.New("bad stuff") + }, + }, + { + name: "input with response event and complex error", + input: "Lambda", + expected: expected{"", messages.InvokeResponse_Error{Message: "message", Type: "type"}}, + handler: func(e interface{}) (interface{}, error) { + return nil, messages.InvokeResponse_Error{Message: "message", Type: "type"} + }, + }, + { + name: "basic input struct serialization", + input: struct{ Custom int }{9001}, + expected: expected{`9001`, nil}, + handler: func(event struct{ Custom int }) (int, error) { + return event.Custom, nil + }, + }, + { + name: "basic output struct serialization", + input: 9001, + expected: expected{`{"Number":9001}`, nil}, + handler: func(event int) (struct{ Number int }, error) { + return struct{ Number int }{event}, nil + }, + }, + } + + // test invocation via a lambda handler + for i, testCase := range testCases { + testCase := testCase + t.Run(fmt.Sprintf("lambdaHandlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { + lambdaHandler := LambdaHandlerWrapper(testCase.handler) + handler := reflect.ValueOf(lambdaHandler) + handlerType := handler.Type() + + var args []reflect.Value + args = append(args, reflect.ValueOf(mockContext)) + if handlerType.NumIn() > 1 { + args = append(args, reflect.ValueOf(testCase.input)) + } + response := handler.Call(args) + assert.Equal(t, 2, len(response)) + if testCase.expected.err != nil { + assert.Equal(t, testCase.expected.err, response[handlerType.NumOut()-1].Interface()) + } else { + assert.Nil(t, response[handlerType.NumOut()-1].Interface()) + responseValMarshalled, _ := json.Marshal(response[0].Interface()) + assert.Equal(t, testCase.expected.val, string(responseValMarshalled)) + } + }) + } + + // test invocation via a Handler + for i, testCase := range testCases { + testCase := testCase + t.Run(fmt.Sprintf("handlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { + handler := HandlerWrapper(lambda.NewHandler(testCase.handler)) + inputPayload, _ := json.Marshal(testCase.input) + response, err := handler.Invoke(mockContext, inputPayload) + if testCase.expected.err != nil { + assert.Equal(t, testCase.expected.err, err) + } else { + assert.NoError(t, err) + assert.Equal(t, testCase.expected.val, string(response)) + } + }) + } +} + +var expectedTraceID, _ = trace.TraceIDFromHex("5759e988bd862e3fe1be46a994272793") +var expectedSpanStub = tracetest.SpanStub{ + Name: "testFunction", + SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: expectedTraceID, + SpanID: trace.SpanID{1}, + TraceFlags: 1, + TraceState: trace.TraceState{}, + Remote: false, + }), + Parent: trace.SpanContextFromContext(mockContext), + SpanKind: trace.SpanKindServer, + StartTime: time.Time{}, + EndTime: time.Time{}, + Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), + attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), + attribute.String("cloud.account.id", "account-id")}, + Events: nil, + Links: nil, + Status: sdktrace.Status{}, + DroppedAttributes: 0, + DroppedEvents: 0, + DroppedLinks: 0, + ChildSpanCount: 0, + Resource: resource.NewWithAttributes(semconv.SchemaURL, + attribute.String("cloud.provider", "aws"), + attribute.String("cloud.region", "us-texas-1"), + attribute.String("faas.name", "testFunction"), + attribute.String("faas.version", "$LATEST")), + InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda"}, +} + +func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actual tracetest.SpanStub) { + assert.Equal(t, expected.Name, actual.Name) + assert.Equal(t, expected.SpanContext, actual.SpanContext) + assert.Equal(t, expected.Parent, actual.Parent) + assert.Equal(t, expected.SpanKind, actual.SpanKind) + assert.Equal(t, expected.Attributes, actual.Attributes) + assert.Equal(t, expected.Events, actual.Events) + assert.Equal(t, expected.Links, actual.Links) + assert.Equal(t, expected.Status, actual.Status) + assert.Equal(t, expected.DroppedAttributes, actual.DroppedAttributes) + assert.Equal(t, expected.DroppedEvents, actual.DroppedEvents) + assert.Equal(t, expected.DroppedLinks, actual.DroppedLinks) + assert.Equal(t, expected.ChildSpanCount, actual.ChildSpanCount) + assert.Equal(t, expected.Resource, actual.Resource) + assert.Equal(t, expected.InstrumentationLibrary, actual.InstrumentationLibrary) +} + +func TestLambdaHandlerWrapperTracing(t *testing.T) { + setEnvVars() + memExporter := initMockTracerProvider() + + customerHandler := func() (string, error) { + return "hello world", nil + } + + wrapped := LambdaHandlerWrapper(customerHandler) + wrappedCallable := reflect.ValueOf(wrapped) + resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) + assert.Len(t, resp, 2) + assert.Equal(t, "hello world", resp[0].Interface()) + assert.Nil(t, resp[1].Interface()) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) +} + +func TestHandlerWrapperTracing(t *testing.T) { + setEnvVars() + memExporter := initMockTracerProvider() + + wrapped := HandlerWrapper(emptyHandler{}) + _, err := wrapped.Invoke(mockContext, nil) + assert.NoError(t, err) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) +} + +func BenchmarkLambdaHandlerWrapper(b *testing.B) { + setEnvVars() + initMockTracerProvider() + + customerHandler := func(ctx context.Context, payload int) error { + return nil + } + wrapped := LambdaHandlerWrapper(customerHandler) + wrappedCallable := reflect.ValueOf(wrapped) + ctx := reflect.ValueOf(mockContext) + payload := reflect.ValueOf(0) + args := []reflect.Value{ctx, payload} + + b.ResetTimer() + for i := 0; i < b.N; i++ { + wrappedCallable.Call(args) + } +} + +func BenchmarkHandlerWrapper(b *testing.B) { + setEnvVars() + initMockTracerProvider() + + wrapped := HandlerWrapper(emptyHandler{}) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + _, _ = wrapped.Invoke(mockContext, []byte{0}) + } +} From f048e4bb3d80e36e79f3bc25c35345d252afe138 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:34:13 -0700 Subject: [PATCH 11/43] Fix filepath --- .../aws/{ => aws-lambda-go/otellambda}/otellambda/go.mod | 0 .../aws/{ => aws-lambda-go/otellambda}/otellambda/go.sum | 0 .../aws/{ => aws-lambda-go/otellambda}/otellambda/lambda.go | 0 .../aws/{ => aws-lambda-go/otellambda}/otellambda/lambda_test.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename instrumentation/github.com/aws/{ => aws-lambda-go/otellambda}/otellambda/go.mod (100%) rename instrumentation/github.com/aws/{ => aws-lambda-go/otellambda}/otellambda/go.sum (100%) rename instrumentation/github.com/aws/{ => aws-lambda-go/otellambda}/otellambda/lambda.go (100%) rename instrumentation/github.com/aws/{ => aws-lambda-go/otellambda}/otellambda/lambda_test.go (100%) diff --git a/instrumentation/github.com/aws/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.mod similarity index 100% rename from instrumentation/github.com/aws/otellambda/go.mod rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.mod diff --git a/instrumentation/github.com/aws/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.sum similarity index 100% rename from instrumentation/github.com/aws/otellambda/go.sum rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.sum diff --git a/instrumentation/github.com/aws/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda.go similarity index 100% rename from instrumentation/github.com/aws/otellambda/lambda.go rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda.go diff --git a/instrumentation/github.com/aws/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda_test.go similarity index 100% rename from instrumentation/github.com/aws/otellambda/lambda_test.go rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda_test.go From 23638fb056f8a9fdb008236887840f655de5c901 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Thu, 22 Jul 2021 15:34:43 -0700 Subject: [PATCH 12/43] Add Lambda Dependabot checks --- .github/dependabot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3b5f38be555..76fc3c82a4f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -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" @@ -155,6 +165,16 @@ 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/bradfitz/gomemcache/memcache/otelmemcache" From 439023e8640ddf3f3a2c05e0424c5d961c17f315 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Thu, 22 Jul 2021 16:24:18 -0700 Subject: [PATCH 13/43] Fix filepath from copy --- .../aws/aws-lambda-go/otellambda/{otellambda => }/go.mod | 0 .../aws/aws-lambda-go/otellambda/{otellambda => }/go.sum | 0 .../aws/aws-lambda-go/otellambda/{otellambda => }/lambda.go | 0 .../aws/aws-lambda-go/otellambda/{otellambda => }/lambda_test.go | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename instrumentation/github.com/aws/aws-lambda-go/otellambda/{otellambda => }/go.mod (100%) rename instrumentation/github.com/aws/aws-lambda-go/otellambda/{otellambda => }/go.sum (100%) rename instrumentation/github.com/aws/aws-lambda-go/otellambda/{otellambda => }/lambda.go (100%) rename instrumentation/github.com/aws/aws-lambda-go/otellambda/{otellambda => }/lambda_test.go (100%) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod similarity index 100% rename from instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.mod rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum similarity index 100% rename from instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/go.sum rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go similarity index 100% rename from instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda.go rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go similarity index 100% rename from instrumentation/github.com/aws/aws-lambda-go/otellambda/otellambda/lambda_test.go rename to instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go From f7ac5db340aa4e5b5ef8404bd3d2cad433315904 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Fri, 23 Jul 2021 14:55:09 -0700 Subject: [PATCH 14/43] Decouple SDK from instrumentation --- .../aws/aws-lambda-go/otellambda/go.mod | 8 - .../aws/aws-lambda-go/otellambda/go.sum | 113 +-------- .../aws/aws-lambda-go/otellambda/lambda.go | 162 ++++++------- .../aws-lambda-go/otellambda/lambda_test.go | 156 +------------ .../aws/aws-lambda-go/otellambda/test/doc.go | 21 ++ .../aws/aws-lambda-go/otellambda/test/go.mod | 19 ++ .../aws/aws-lambda-go/otellambda/test/go.sum | 37 +++ .../otellambda/test/lambda_test.go | 215 ++++++++++++++++++ 8 files changed, 378 insertions(+), 353 deletions(-) create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index 34180b7a8d9..23ec3cfeae6 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -2,18 +2,10 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/ go 1.16 -replace ( - go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../detectors/aws/lambda - go.opentelemetry.io/contrib/propagators/aws => ../../../../../propagators/aws -) - require ( github.com/aws/aws-lambda-go v1.24.0 github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 go.opentelemetry.io/contrib/propagators/aws v0.21.0 go.opentelemetry.io/otel v1.0.0-RC1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1 - go.opentelemetry.io/otel/sdk v1.0.0-RC1 go.opentelemetry.io/otel/trace v1.0.0-RC1 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index 10c48f9d998..b43415cf660 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -1,145 +1,36 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aws/aws-lambda-go v1.24.0 h1:bOMerM175hLqHLdF1Nonfv1NA20nTIatuC0HK8eMoYg= github.com/aws/aws-lambda-go v1.24.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= +go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1 h1:GHKxjc4EDldz8ScMDpiNwX4BAub6wGFUUo5Axm2BimU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.0-RC1/go.mod h1:FliQjImlo7emZVjixV8nbDMAa4iAkcWTE9zzSEOiEPw= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1 h1:ZOQXuxKJ9evGspu3LvbZxx3KOOQvKAPBJVMOfGf1cOM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.0-RC1/go.mod h1:cDwRc2Jrh5Gku1peGK8p9rRuX/Uq2OtVmLicjlw2WYU= go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= -go.opentelemetry.io/proto/otlp v0.9.0 h1:C0g6TWmQYvjKRnljRULLWUVJGy8Uvu0NEL/5frY2/t4= -go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 1ef0271ebb0..913d8cef393 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -7,19 +7,15 @@ import ( "log" "os" "reflect" - "runtime" "strings" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-lambda-go/lambdacontext" - lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" "go.opentelemetry.io/contrib/propagators/aws/xray" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/propagation" - sdktrace "go.opentelemetry.io/otel/sdk/trace" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "go.opentelemetry.io/otel/trace" ) @@ -28,39 +24,38 @@ const ( tracerName = "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" ) -var tp *sdktrace.TracerProvider var errorLogger = log.New(log.Writer(), "OTel Lambda Error: ", 0) -func init() { - otel.SetTextMapPropagator(xray.Propagator{}) +type Flusher interface { + ForceFlush(context.Context) error } -func initTracerProvider() { - ctx := context.Background() +type noopFlusher struct{} - exp, err := otlptracegrpc.New(ctx, otlptracegrpc.WithInsecure()) - if err != nil { - errorLogger.Printf("failed to initialize exporter: %v\n", err) - return - } +func (*noopFlusher) ForceFlush(context.Context) error{return nil} - detector := lambdadetector.NewResourceDetector() - res, err := detector.Detect(ctx) - if err != nil { - errorLogger.Printf("failed to detect lambda resources: %v\n", err) - return - } +// Compile time check our noopFlusher implements FLusher +var _ Flusher = &noopFlusher{} - tp = sdktrace.NewTracerProvider( - sdktrace.WithBatcher(exp), - sdktrace.WithIDGenerator(xray.NewIDGenerator()), - sdktrace.WithResource(res), - ) +type InstrumentationOption func(o *InstrumentationOptions) - // Set the traceprovider - otel.SetTracerProvider(tp) +type InstrumentationOptions struct { + // TracerProvider is the TracerProvider which will be used + // to create instrumentation spans + // The default value of TracerProvider the global otel TracerProvider + // returned by otel.GetTracerProvider() + TracerProvider trace.TracerProvider + + // Flusher is the mechanism used to flush any unexported spans + // each Lambda Invocation to avoid spans being unexported for long + // when periods of time if Lambda freezes the execution environment + // The default value of Flusher is a noop Flusher, using this + // default can result in long data delays in asynchronous settings + Flusher Flusher } +var configuration InstrumentationOptions + func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { return func(context.Context, interface{}) (interface{}, error) { return nil, e @@ -149,7 +144,16 @@ func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, } // LambdaHandlerWrapper Provides a lambda handler which wraps customer lambda handler with OTel Tracing -func LambdaHandlerWrapper(handlerFunc interface{}) interface{} { +func LambdaHandlerWrapper(handlerFunc interface{}, options ...InstrumentationOption) interface{} { + o := InstrumentationOptions{ + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + } + for _, opt := range options { + opt(&o) + } + configuration = o + if handlerFunc == nil { return errorHandler(fmt.Errorf("handler is nil")) } @@ -275,7 +279,16 @@ func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, err } // HandlerWrapper Provides a Handler which wraps customer Handler with OTel Tracing -func HandlerWrapper(handler lambda.Handler) lambda.Handler { +func HandlerWrapper(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { + o := InstrumentationOptions{ + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + } + for _, opt := range options { + opt(&o) + } + configuration = o + return wrappedHandler{handler: handler} } @@ -288,64 +301,55 @@ func tracingBegin(ctx context.Context) (context.Context, trace.Span) { propagator := xray.Propagator{} ctx = propagator.Extract(ctx, mc) - // If tracer provider initialization failed we - // will attempt to initialize once per invocation - if tp == nil { - initTracerProvider() - } - - // if tracer provider successfully initializes then - // we add tracing, otherwise do customer business - // logic with no tracing - if tp != nil { - // Get a named tracer with package path as its name. - tracer := tp.Tracer(tracerName) + // Get a named tracer with package path as its name. + tracer := configuration.TracerProvider.Tracer(tracerName) - var span trace.Span - spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") + var span trace.Span + spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") - var attributes []attribute.KeyValue - lc, ok := lambdacontext.FromContext(ctx) - if !ok { - errorLogger.Println("failed to load lambda context from context, ensure tracing enabled in Lambda") - } - if lc != nil { - ctxRequestID := lc.AwsRequestID - attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSExecutionKey, Value: attribute.StringValue(ctxRequestID)}) - - // Resource attrs added as span attr due to static tp - // being created without meaningful context - ctxFunctionArn := lc.InvokedFunctionArn - attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSIDKey, Value: attribute.StringValue(ctxFunctionArn)}) - arnParts := strings.Split(ctxFunctionArn, ":") - if len(arnParts) >= 5 { - attributes = append(attributes, attribute.KeyValue{Key: semconv.CloudAccountIDKey, Value: attribute.StringValue(arnParts[4])}) - } + var attributes []attribute.KeyValue + lc, ok := lambdacontext.FromContext(ctx) + if !ok { + errorLogger.Println("failed to load lambda context from context, ensure tracing enabled in Lambda") + } + if lc != nil { + ctxRequestID := lc.AwsRequestID + attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSExecutionKey, Value: attribute.StringValue(ctxRequestID)}) + + // Resource attrs added as span attr due to static tp + // being created without meaningful context + ctxFunctionArn := lc.InvokedFunctionArn + attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSIDKey, Value: attribute.StringValue(ctxFunctionArn)}) + arnParts := strings.Split(ctxFunctionArn, ":") + if len(arnParts) >= 5 { + attributes = append(attributes, attribute.KeyValue{Key: semconv.CloudAccountIDKey, Value: attribute.StringValue(arnParts[4])}) } + } - ctx, span = tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) + ctx, span = tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) - return ctx, span - } - return ctx, nil + return ctx, span } // Logic to wrap up OTel Tracing func tracingEnd(ctx context.Context, span trace.Span) { - if tp != nil { - // span will be valid if tp is not nil - span.End() - - // yield processor to attempt to attempt to ensure - // all spans have been consumed and are ready to be - // flushed - see https://github.com/open-telemetry/opentelemetry-go/issues/2080 - // to be removed upon resolution of above issue - runtime.Gosched() - - // force flush any tracing data since lambda may freeze - err := tp.ForceFlush(ctx) - if err != nil { - errorLogger.Println("failed to force a flush, lambda may freeze before instrumentation exported: ", err) - } + span.End() + + // force flush any tracing data since lambda may freeze + err := configuration.Flusher.ForceFlush(ctx) + if err != nil { + errorLogger.Println("failed to force a flush, lambda may freeze before instrumentation exported: ", err) + } +} + +func WithTracerProvider(tracerProvider trace.TracerProvider) InstrumentationOption { + return func(o *InstrumentationOptions) { + o.TracerProvider = tracerProvider } } + +func WithFlusher(flusher Flusher) InstrumentationOption { + return func(o *InstrumentationOptions) { + o.Flusher = flusher + } +} \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index a1ac6939b19..257538a10e5 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -7,25 +7,12 @@ import ( "fmt" "os" "reflect" - "sync" "testing" - "time" "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-lambda-go/lambda/messages" "github.com/aws/aws-lambda-go/lambdacontext" "github.com/stretchr/testify/assert" - - lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" - "go.opentelemetry.io/contrib/propagators/aws/xray" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/sdk/instrumentation" - "go.opentelemetry.io/otel/sdk/resource" - sdktrace "go.opentelemetry.io/otel/sdk/trace" - "go.opentelemetry.io/otel/sdk/trace/tracetest" - semconv "go.opentelemetry.io/otel/semconv/v1.4.0" - "go.opentelemetry.io/otel/trace" ) var ( @@ -38,34 +25,9 @@ var ( }, ClientContext: lambdacontext.ClientContext{}, } - mockContext = xray.Propagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), - mapCarrier{ - "X-Amzn-Trace-Id": "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1", - }) + mockContext = lambdacontext.NewContext(context.TODO(), &mockLambdaContext) ) -type mockIdGenerator struct { - sync.Mutex - traceCount int - spanCount int -} - -func (m *mockIdGenerator) NewIDs(_ context.Context) (trace.TraceID, trace.SpanID) { - m.Lock() - defer m.Unlock() - m.traceCount += 1 - m.spanCount += 1 - return [16]byte{byte(m.traceCount)}, [8]byte{byte(m.spanCount)} -} - -func (m *mockIdGenerator) NewSpanID(_ context.Context, _ trace.TraceID) trace.SpanID { - m.Lock() - defer m.Unlock() - m.spanCount += 1 - return [8]byte{byte(m.spanCount)} -} - -var _ sdktrace.IDGenerator = &mockIdGenerator{} type emptyHandler struct{} @@ -75,30 +37,6 @@ func (h emptyHandler) Invoke(_ context.Context, _ []byte) ([]byte, error) { var _ lambda.Handler = emptyHandler{} -func initMockTracerProvider() *tracetest.InMemoryExporter { - ctx := context.Background() - - exp := tracetest.NewInMemoryExporter() - - detector := lambdadetector.NewResourceDetector() - res, err := detector.Detect(ctx) - if err != nil { - errorLogger.Printf("failed to detect lambda resources: %v\n", err) - return nil - } - - tp = sdktrace.NewTracerProvider( - sdktrace.WithSyncer(exp), - sdktrace.WithIDGenerator(&mockIdGenerator{}), - sdktrace.WithResource(res), - ) - - // Set the traceprovider - otel.SetTracerProvider(tp) - - return exp -} - func setEnvVars() { _ = os.Setenv("AWS_LAMBDA_FUNCTION_NAME", "testFunction") _ = os.Setenv("AWS_REGION", "us-texas-1") @@ -109,10 +47,6 @@ func setEnvVars() { func TestLambdaHandlerSignatures(t *testing.T) { setEnvVars() - // for these tests we do not care about the tracing and - // so we will ignore it the in memory span exporter - _ = initMockTracerProvider() - emptyPayload := "" testCases := []struct { name string @@ -200,10 +134,6 @@ type expected struct { func TestHandlerInvokes(t *testing.T) { setEnvVars() - // for these tests we do not care about the tracing and - // so we will ignore it the in memory span exporter - _ = initMockTracerProvider() - hello := func(s string) string { return fmt.Sprintf("Hello %s!", s) } @@ -322,91 +252,8 @@ func TestHandlerInvokes(t *testing.T) { } } -var expectedTraceID, _ = trace.TraceIDFromHex("5759e988bd862e3fe1be46a994272793") -var expectedSpanStub = tracetest.SpanStub{ - Name: "testFunction", - SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: expectedTraceID, - SpanID: trace.SpanID{1}, - TraceFlags: 1, - TraceState: trace.TraceState{}, - Remote: false, - }), - Parent: trace.SpanContextFromContext(mockContext), - SpanKind: trace.SpanKindServer, - StartTime: time.Time{}, - EndTime: time.Time{}, - Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), - attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), - attribute.String("cloud.account.id", "account-id")}, - Events: nil, - Links: nil, - Status: sdktrace.Status{}, - DroppedAttributes: 0, - DroppedEvents: 0, - DroppedLinks: 0, - ChildSpanCount: 0, - Resource: resource.NewWithAttributes(semconv.SchemaURL, - attribute.String("cloud.provider", "aws"), - attribute.String("cloud.region", "us-texas-1"), - attribute.String("faas.name", "testFunction"), - attribute.String("faas.version", "$LATEST")), - InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda"}, -} - -func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actual tracetest.SpanStub) { - assert.Equal(t, expected.Name, actual.Name) - assert.Equal(t, expected.SpanContext, actual.SpanContext) - assert.Equal(t, expected.Parent, actual.Parent) - assert.Equal(t, expected.SpanKind, actual.SpanKind) - assert.Equal(t, expected.Attributes, actual.Attributes) - assert.Equal(t, expected.Events, actual.Events) - assert.Equal(t, expected.Links, actual.Links) - assert.Equal(t, expected.Status, actual.Status) - assert.Equal(t, expected.DroppedAttributes, actual.DroppedAttributes) - assert.Equal(t, expected.DroppedEvents, actual.DroppedEvents) - assert.Equal(t, expected.DroppedLinks, actual.DroppedLinks) - assert.Equal(t, expected.ChildSpanCount, actual.ChildSpanCount) - assert.Equal(t, expected.Resource, actual.Resource) - assert.Equal(t, expected.InstrumentationLibrary, actual.InstrumentationLibrary) -} - -func TestLambdaHandlerWrapperTracing(t *testing.T) { - setEnvVars() - memExporter := initMockTracerProvider() - - customerHandler := func() (string, error) { - return "hello world", nil - } - - wrapped := LambdaHandlerWrapper(customerHandler) - wrappedCallable := reflect.ValueOf(wrapped) - resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) - assert.Len(t, resp, 2) - assert.Equal(t, "hello world", resp[0].Interface()) - assert.Nil(t, resp[1].Interface()) - - assert.Len(t, memExporter.GetSpans(), 1) - stub := memExporter.GetSpans()[0] - assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) -} - -func TestHandlerWrapperTracing(t *testing.T) { - setEnvVars() - memExporter := initMockTracerProvider() - - wrapped := HandlerWrapper(emptyHandler{}) - _, err := wrapped.Invoke(mockContext, nil) - assert.NoError(t, err) - - assert.Len(t, memExporter.GetSpans(), 1) - stub := memExporter.GetSpans()[0] - assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) -} - func BenchmarkLambdaHandlerWrapper(b *testing.B) { setEnvVars() - initMockTracerProvider() customerHandler := func(ctx context.Context, payload int) error { return nil @@ -425,7 +272,6 @@ func BenchmarkLambdaHandlerWrapper(b *testing.B) { func BenchmarkHandlerWrapper(b *testing.B) { setEnvVars() - initMockTracerProvider() wrapped := HandlerWrapper(emptyHandler{}) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go new file mode 100644 index 00000000000..457d9968139 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go @@ -0,0 +1,21 @@ +// 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 test validates AWS Lambda instrumentation with the default SDK. +This package is in a separate module from the instrumentation it tests to +isolate the dependency of the default SDK and not impose this as a transitive +dependency for users. +*/ +package test \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod new file mode 100644 index 00000000000..5a16e15473b --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod @@ -0,0 +1,19 @@ +module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda/test + +go 1.16 + +replace ( + go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../../detectors/aws/lambda + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda => ../ +) + +require ( + github.com/aws/aws-lambda-go v1.25.0 + github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.21.0 + go.opentelemetry.io/contrib/propagators/aws v0.21.0 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/sdk v1.0.0-RC1 + go.opentelemetry.io/otel/trace v1.0.0-RC1 +) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum new file mode 100644 index 00000000000..73ee0993bcf --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -0,0 +1,37 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/aws/aws-lambda-go v1.24.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= +github.com/aws/aws-lambda-go v1.25.0 h1:hv0Av6ooQhnqMS2jqeaph0izIwwaV2N6gsT5ad17Ihw= +github.com/aws/aws-lambda-go v1.25.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= +go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go new file mode 100644 index 00000000000..c276eeb0f0e --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -0,0 +1,215 @@ +package test + +import ( + "context" + "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" + "go.opentelemetry.io/otel/propagation" + "log" + "os" + "reflect" + "sync" + "testing" + "time" + + "github.com/aws/aws-lambda-go/lambda" + "github.com/aws/aws-lambda-go/lambdacontext" + "github.com/stretchr/testify/assert" + + lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" + "go.opentelemetry.io/contrib/propagators/aws/xray" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/sdk/instrumentation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + semconv "go.opentelemetry.io/otel/semconv/v1.4.0" + "go.opentelemetry.io/otel/trace" +) + +var ( + mockLambdaContext = lambdacontext.LambdaContext{ + AwsRequestID: "123", + InvokedFunctionArn: "arn:partition:service:region:account-id:resource-type:resource-id", + Identity: lambdacontext.CognitoIdentity{ + CognitoIdentityID: "someId", + CognitoIdentityPoolID: "somePoolId", + }, + ClientContext: lambdacontext.ClientContext{}, + } + mockContext = xray.Propagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), + mapCarrier{ + "X-Amzn-Trace-Id": "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1", + }) +) + +var errorLogger = log.New(log.Writer(), "OTel Lambda Test Error: ", 0) + +// basic implementation of TextMapCarrier +// which wraps the default map type +type mapCarrier map[string]string + +// Compile time check our mapCarrier implements propagation.TextMapCarrier +var _ propagation.TextMapCarrier = mapCarrier{} + +// Get returns the value associated with the passed key. +func (mc mapCarrier) Get(key string) string { + return mc[key] +} + +// Set stores the key-value pair. +func (mc mapCarrier) Set(key string, value string) { + mc[key] = value +} + +// Keys lists the keys stored in this carrier. +func (mc mapCarrier) Keys() []string { + keys := make([]string, len(mc)) + i := 0 + for k := range mc { + keys[i] = k + i++ + } + return keys +} + + +type mockIdGenerator struct { + sync.Mutex + traceCount int + spanCount int +} + +func (m *mockIdGenerator) NewIDs(_ context.Context) (trace.TraceID, trace.SpanID) { + m.Lock() + defer m.Unlock() + m.traceCount += 1 + m.spanCount += 1 + return [16]byte{byte(m.traceCount)}, [8]byte{byte(m.spanCount)} +} + +func (m *mockIdGenerator) NewSpanID(_ context.Context, _ trace.TraceID) trace.SpanID { + m.Lock() + defer m.Unlock() + m.spanCount += 1 + return [8]byte{byte(m.spanCount)} +} + +var _ sdktrace.IDGenerator = &mockIdGenerator{} + +type emptyHandler struct{} + +func (h emptyHandler) Invoke(_ context.Context, _ []byte) ([]byte, error) { + return nil, nil +} + +var _ lambda.Handler = emptyHandler{} + +func initMockTracerProvider() (trace.TracerProvider, *tracetest.InMemoryExporter) { + ctx := context.Background() + + exp := tracetest.NewInMemoryExporter() + + detector := lambdadetector.NewResourceDetector() + res, err := detector.Detect(ctx) + if err != nil { + errorLogger.Printf("failed to detect lambda resources: %v\n", err) + return nil, nil + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithSyncer(exp), + sdktrace.WithIDGenerator(&mockIdGenerator{}), + sdktrace.WithResource(res), + ) + + return tp, exp +} + +func setEnvVars() { + _ = os.Setenv("AWS_LAMBDA_FUNCTION_NAME", "testFunction") + _ = os.Setenv("AWS_REGION", "us-texas-1") + _ = os.Setenv("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST") + _ = os.Setenv("_X_AMZN_TRACE_ID", "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") +} + +var expectedTraceID, _ = trace.TraceIDFromHex("5759e988bd862e3fe1be46a994272793") +var expectedSpanStub = tracetest.SpanStub{ + Name: "testFunction", + SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: expectedTraceID, + SpanID: trace.SpanID{1}, + TraceFlags: 1, + TraceState: trace.TraceState{}, + Remote: false, + }), + Parent: trace.SpanContextFromContext(mockContext), + SpanKind: trace.SpanKindServer, + StartTime: time.Time{}, + EndTime: time.Time{}, + Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), + attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), + attribute.String("cloud.account.id", "account-id")}, + Events: nil, + Links: nil, + Status: sdktrace.Status{}, + DroppedAttributes: 0, + DroppedEvents: 0, + DroppedLinks: 0, + ChildSpanCount: 0, + Resource: resource.NewWithAttributes(semconv.SchemaURL, + attribute.String("cloud.provider", "aws"), + attribute.String("cloud.region", "us-texas-1"), + attribute.String("faas.name", "testFunction"), + attribute.String("faas.version", "$LATEST")), + InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda"}, +} + +func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actual tracetest.SpanStub) { + assert.Equal(t, expected.Name, actual.Name) + assert.Equal(t, expected.SpanContext, actual.SpanContext) + assert.Equal(t, expected.Parent, actual.Parent) + assert.Equal(t, expected.SpanKind, actual.SpanKind) + assert.Equal(t, expected.Attributes, actual.Attributes) + assert.Equal(t, expected.Events, actual.Events) + assert.Equal(t, expected.Links, actual.Links) + assert.Equal(t, expected.Status, actual.Status) + assert.Equal(t, expected.DroppedAttributes, actual.DroppedAttributes) + assert.Equal(t, expected.DroppedEvents, actual.DroppedEvents) + assert.Equal(t, expected.DroppedLinks, actual.DroppedLinks) + assert.Equal(t, expected.ChildSpanCount, actual.ChildSpanCount) + assert.Equal(t, expected.Resource, actual.Resource) + assert.Equal(t, expected.InstrumentationLibrary, actual.InstrumentationLibrary) +} + +func TestLambdaHandlerWrapperTracing(t *testing.T) { + setEnvVars() + tp, memExporter := initMockTracerProvider() + + customerHandler := func() (string, error) { + return "hello world", nil + } + + wrapped := otellambda.LambdaHandlerWrapper(customerHandler, otellambda.WithTracerProvider(tp)) + wrappedCallable := reflect.ValueOf(wrapped) + resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) + assert.Len(t, resp, 2) + assert.Equal(t, "hello world", resp[0].Interface()) + assert.Nil(t, resp[1].Interface()) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) +} + +func TestHandlerWrapperTracing(t *testing.T) { + setEnvVars() + tp, memExporter := initMockTracerProvider() + + wrapped := otellambda.HandlerWrapper(emptyHandler{}, otellambda.WithTracerProvider(tp)) + _, err := wrapped.Invoke(mockContext, nil) + assert.NoError(t, err) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) +} From e932685d9026e09b83ba902dd4cabf3d04eadcaf Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:08:13 -0700 Subject: [PATCH 15/43] Improve usage of make --- .../github.com/aws/aws-lambda-go/otellambda/lambda.go | 6 ++---- .../aws/aws-lambda-go/otellambda/test/lambda_test.go | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 913d8cef393..7d26562f2f3 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -209,11 +209,9 @@ func (mc mapCarrier) Set(key string, value string) { // Keys lists the keys stored in this carrier. func (mc mapCarrier) Keys() []string { - keys := make([]string, len(mc)) - i := 0 + keys := make([]string, 0, len(mc)) for k := range mc { - keys[i] = k - i++ + keys = append(keys, k) } return keys } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index c276eeb0f0e..5a3d2822975 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -63,11 +63,9 @@ func (mc mapCarrier) Set(key string, value string) { // Keys lists the keys stored in this carrier. func (mc mapCarrier) Keys() []string { - keys := make([]string, len(mc)) - i := 0 + keys := make([]string, 0, len(mc)) for k := range mc { - keys[i] = k - i++ + keys = append(keys, k) } return keys } From 8c86bb4964b9456445f6fa63ecf8a8b5fcae239f Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:10:06 -0700 Subject: [PATCH 16/43] Improve comment clarity --- detectors/aws/lambda/detector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/aws/lambda/detector.go b/detectors/aws/lambda/detector.go index 4ede2576c04..44501f5d5cb 100644 --- a/detectors/aws/lambda/detector.go +++ b/detectors/aws/lambda/detector.go @@ -46,7 +46,7 @@ func NewResourceDetector() resource.Detector { return &resourceDetector{} } -// Detect collects resources available when running on lambda +// Detect collects resource attributes available when running on lambda func (detector *resourceDetector) Detect(context.Context) (*resource.Resource, error) { // Lambda resources come from ENV From debba6cfae12a71da880e8655c76c5145671f6d2 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Fri, 23 Jul 2021 15:39:40 -0700 Subject: [PATCH 17/43] Minor refactoring --- .../aws/aws-lambda-go/otellambda/lambda.go | 22 +++++++++---------- .../otellambda/test/lambda_test.go | 7 +++--- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 7d26562f2f3..c0a52ca37d2 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -32,7 +32,7 @@ type Flusher interface { type noopFlusher struct{} -func (*noopFlusher) ForceFlush(context.Context) error{return nil} +func (*noopFlusher) ForceFlush(context.Context) error { return nil } // Compile time check our noopFlusher implements FLusher var _ Flusher = &noopFlusher{} @@ -88,7 +88,7 @@ func validateReturns(handler reflect.Type) error { switch n := handler.NumOut(); { case n > 2: return fmt.Errorf("handler may not return more than two values") - case n > 1: + case n == 2: if !handler.Out(1).Implements(errorType) { return fmt.Errorf("handler returns two values, but the second does not implement error") } @@ -102,7 +102,7 @@ func validateReturns(handler reflect.Type) error { } // Wraps and calls customer lambda handler then unpacks response as necessary -func wrapperInternals(handlerFunc interface{}, event reflect.Value, ctx context.Context, takesContext bool) (interface{}, error) { +func wrapperInternals(ctx context.Context, handlerFunc interface{}, event reflect.Value, takesContext bool) (interface{}, error) { wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) argsWrapped := []reflect.Value{reflect.ValueOf(ctx), event, reflect.ValueOf(takesContext)} @@ -147,7 +147,7 @@ func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, func LambdaHandlerWrapper(handlerFunc interface{}, options ...InstrumentationOption) interface{} { o := InstrumentationOptions{ TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, + Flusher: &noopFlusher{}, } for _, opt := range options { opt(&o) @@ -177,7 +177,7 @@ func LambdaHandlerWrapper(handlerFunc interface{}, options ...InstrumentationOpt return func(ctx context.Context) (interface{}, error) { var temp *interface{} event := reflect.ValueOf(temp) - return wrapperInternals(handlerFunc, event, ctx, takesContext) + return wrapperInternals(ctx, handlerFunc, event, takesContext) } } else { // customer either takes both context and payload or just payload return func(ctx context.Context, payload interface{}) (interface{}, error) { @@ -185,7 +185,7 @@ func LambdaHandlerWrapper(handlerFunc interface{}, options ...InstrumentationOpt if err != nil { return nil, err } - return wrapperInternals(handlerFunc, event.Elem(), ctx, takesContext) + return wrapperInternals(ctx, handlerFunc, event.Elem(), takesContext) } } } @@ -280,7 +280,7 @@ func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, err func HandlerWrapper(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { o := InstrumentationOptions{ TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, + Flusher: &noopFlusher{}, } for _, opt := range options { opt(&o) @@ -312,15 +312,15 @@ func tracingBegin(ctx context.Context) (context.Context, trace.Span) { } if lc != nil { ctxRequestID := lc.AwsRequestID - attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSExecutionKey, Value: attribute.StringValue(ctxRequestID)}) + attributes = append(attributes, semconv.FaaSExecutionKey.String(ctxRequestID)) // Resource attrs added as span attr due to static tp // being created without meaningful context ctxFunctionArn := lc.InvokedFunctionArn - attributes = append(attributes, attribute.KeyValue{Key: semconv.FaaSIDKey, Value: attribute.StringValue(ctxFunctionArn)}) + attributes = append(attributes, semconv.FaaSIDKey.String(ctxFunctionArn)) arnParts := strings.Split(ctxFunctionArn, ":") if len(arnParts) >= 5 { - attributes = append(attributes, attribute.KeyValue{Key: semconv.CloudAccountIDKey, Value: attribute.StringValue(arnParts[4])}) + attributes = append(attributes, semconv.CloudAccountIDKey.String(arnParts[4])) } } @@ -350,4 +350,4 @@ func WithFlusher(flusher Flusher) InstrumentationOption { return func(o *InstrumentationOptions) { o.Flusher = flusher } -} \ No newline at end of file +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 5a3d2822975..711833aaf61 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -70,7 +70,6 @@ func (mc mapCarrier) Keys() []string { return keys } - type mockIdGenerator struct { sync.Mutex traceCount int @@ -102,7 +101,7 @@ func (h emptyHandler) Invoke(_ context.Context, _ []byte) ([]byte, error) { var _ lambda.Handler = emptyHandler{} -func initMockTracerProvider() (trace.TracerProvider, *tracetest.InMemoryExporter) { +func initMockTracerProvider() (*sdktrace.TracerProvider, *tracetest.InMemoryExporter) { ctx := context.Background() exp := tracetest.NewInMemoryExporter() @@ -187,7 +186,7 @@ func TestLambdaHandlerWrapperTracing(t *testing.T) { return "hello world", nil } - wrapped := otellambda.LambdaHandlerWrapper(customerHandler, otellambda.WithTracerProvider(tp)) + wrapped := otellambda.LambdaHandlerWrapper(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) assert.Len(t, resp, 2) @@ -203,7 +202,7 @@ func TestHandlerWrapperTracing(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() - wrapped := otellambda.HandlerWrapper(emptyHandler{}, otellambda.WithTracerProvider(tp)) + wrapped := otellambda.HandlerWrapper(emptyHandler{}, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp)) _, err := wrapped.Invoke(mockContext, nil) assert.NoError(t, err) From d481dcb5b0ceca555c3a3550d325ef33f1709fae Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:37:16 -0700 Subject: [PATCH 18/43] Add example --- .../otellambda/example/Dockerfile | 28 +++++ .../otellambda/example/README.md | 34 ++++++ .../example/assumeRolePolicyDocument.json | 10 ++ .../aws-lambda-go/otellambda/example/build.sh | 82 +++++++++++++ .../otellambda/example/docker-compose.yml | 31 +++++ .../aws-lambda-go/otellambda/example/go.mod | 22 ++++ .../aws-lambda-go/otellambda/example/go.sum | 85 +++++++++++++ .../aws-lambda-go/otellambda/example/main.go | 114 ++++++++++++++++++ .../otellambda/example/manualAWSCleanup.sh | 34 ++++++ .../example/policyForRoleDocument.json | 20 +++ 10 files changed, 460 insertions(+) create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/Dockerfile create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/README.md create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/assumeRolePolicyDocument.json create mode 100755 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/docker-compose.yml create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go create mode 100755 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/example/policyForRoleDocument.json diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/Dockerfile b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/Dockerfile new file mode 100644 index 00000000000..3815ad97a35 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/Dockerfile @@ -0,0 +1,28 @@ +# 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. +FROM golang:1.16 AS base +COPY . /src/ +WORKDIR /src/instrumentation/github.com/aws/aws-lambda-go/otellambda/example +RUN apt-get update + +FROM base AS aws-lambda + +# install other package(s) in base +RUN apt-get install zip unzip +RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" \ + && unzip awscliv2.zip \ + && ./aws/install +RUN apt-get -y install jq + +CMD ["./build.sh"] \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/README.md b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/README.md new file mode 100644 index 00000000000..24fa6355bb0 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/README.md @@ -0,0 +1,34 @@ +# aws/aws-lambda-go instrumentation example + +A simple example to demonstrate the AWS Lambda for Go instrumentation. In this example, container `aws-lambda-client` initializes an S3 client and an HTTP client and runs 2 basic operations: `listS3Buckets` and `GET`. + + +These instructions assume you have +[docker-compose](https://docs.docker.com/compose/) installed and setup, and [AWS credential](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) configured. + +1. From within the `example` directory, bring up the project by running: + + ```sh + docker-compose up --detach + ``` + +2. The instrumentation works with a `stdout` exporter. The example pulls this output from AWS and outputs back to stdout. + To inspect the output (following build output), you can run: + + ```sh + docker-compose logs + ``` +3. After inspecting the client logs, the example can be cleaned up by running: + + ```sh + docker-compose down + ``` + +Note: Because the example runs on AWS Lambda, a handful of resources are created in AWS by the + example. The example will automatically destroy any resources it makes; however, if you + terminate the container before it completes you may have leftover resources in AWS. Should + you terminate the container early, run the below command to ensure all AWS resources are cleaned up: + +```sh +./manualAWSCleanup.sh +``` \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/assumeRolePolicyDocument.json b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/assumeRolePolicyDocument.json new file mode 100644 index 00000000000..b8572eb8ab8 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/assumeRolePolicyDocument.json @@ -0,0 +1,10 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { "Service": "lambda.amazonaws.com" }, + "Action": "sts:AssumeRole" + } + ] +} \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh new file mode 100755 index 00000000000..58bbce37b4a --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh @@ -0,0 +1,82 @@ +#!/bin/sh + +# constants +LAMBDA_FUNCTION_NAME=SampleLambdaGo +ROLE_NAME="$LAMBDA_FUNCTION_NAME"Role +POLICY_NAME="$LAMBDA_FUNCTION_NAME"Policy +LOG_GROUP_NAME=/aws/lambda/"$LAMBDA_FUNCTION_NAME" +AWS_ACCT_ID=$(aws sts get-caller-identity | jq '.Account | tonumber') +MAX_CREATE_TRIES=5 +MAX_GET_LOG_STREAM_TRIES=10 + +# build go executable +echo "1/6 Building go executable" +GOOS=linux GOARCH=amd64 go build -o ./build/bootstrap . > /dev/null +cd build || exit +zip bootstrap.zip bootstrap > /dev/null + +# create AWS resources +echo "2/6 Creating necessary resources in AWS" +aws iam create-role --role-name "$ROLE_NAME" --assume-role-policy-document file://../assumeRolePolicyDocument.json > /dev/null +aws iam create-policy --policy-name "$POLICY_NAME" --policy-document file://../policyForRoleDocument.json > /dev/null +aws iam attach-role-policy --role-name "$ROLE_NAME" --policy-arn arn:aws:iam::"$AWS_ACCT_ID":policy/"$POLICY_NAME" > /dev/null +aws logs create-log-group --log-group-name "$LOG_GROUP_NAME" > /dev/null + +# race condition exists such that a role can be created and validated +# via IAM, yet still cannot be assumed by Lambda, we will retry up to +# MAX_CREATE_TRIES times to create the function +TIMEOUT="$MAX_CREATE_TRIES" +CREATE_FUNCTION_SUCCESS=$(aws lambda create-function --function-name "$LAMBDA_FUNCTION_NAME" --runtime provided.al2 --handler bootstrap --zip-file fileb://bootstrap.zip --role arn:aws:iam::"$AWS_ACCT_ID":role/"$ROLE_NAME" --timeout 5 --tracing-config Mode=Active > /dev/null || echo "false") +while [ "$CREATE_FUNCTION_SUCCESS" = "false" ] && [ "$TIMEOUT" -ne 1 ] ; do + echo " Retrying create-function, role likely not ready for use..." + sleep 1 + TIMEOUT=$((TIMEOUT - 1)) + CREATE_FUNCTION_SUCCESS=$(aws lambda create-function --function-name "$LAMBDA_FUNCTION_NAME" --runtime provided.al2 --handler bootstrap --zip-file fileb://bootstrap.zip --role arn:aws:iam::"$AWS_ACCT_ID":role/"$ROLE_NAME" --timeout 5 --tracing-config Mode=Active > /dev/null || echo "false") +done +if [ "$TIMEOUT" -eq 1 ] ; then + echo "Error: max retries reached when attempting to create Lambda Function" +fi + +# invoke lambda +echo "3/6 Invoking lambda" +aws lambda invoke --function-name "$LAMBDA_FUNCTION_NAME" --payload "" resp.json + +# get logs from lambda (via cloudwatch) +# logs sent from lambda to Cloudwatch and retrieved +# from there because example logs are too long to +# return directly from lambda invocation +echo "4/6 Storing logs from AWS" + +# significant (3+ second) delay can occur between invoking Lambda and +# the related log stream existing in Cloudwatch. We will retry to +# retrieve the log stream up to MAX_GET_LOG_STREAM_TRIES +TIMEOUT="$MAX_GET_LOG_STREAM_TRIES" +LOG_STREAM_NAME=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --order-by LastEventTime --descending | jq --raw-output '.logStreams[0].logStreamName') +while [ "$LOG_STREAM_NAME" = "null" ] && [ "$TIMEOUT" -ne 1 ] ; do + echo " Waiting for log stream to be created..." + sleep 1 + TIMEOUT=$((TIMEOUT - 1)) + LOG_STREAM_NAME=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --order-by LastEventTime --descending | jq --raw-output '.logStreams[0].logStreamName') +done +if [ "$TIMEOUT" -eq 1 ] ; then + echo "Timed out waiting for log stream to be created" +fi + +# minor (<1 second) delay can exist when adding logs to the +# log stream such that only partial logs will be returned. +# Will wait small amount of time to let logs fully populate +sleep 2 +aws logs get-log-events --log-group-name "$LOG_GROUP_NAME" --log-stream-name "$LOG_STREAM_NAME" | jq --join-output '.events[] | select(has("message")) | .message' | jq -R -r '. as $line | try fromjson catch $line' > lambdaLogs + +# destroy lambda resources +echo "5/6 Destroying AWS resources" +aws logs delete-log-stream --log-group-name "$LOG_GROUP_NAME" --log-stream-name "$LOG_STREAM_NAME" +aws logs delete-log-group --log-group-name "$LOG_GROUP_NAME" +aws lambda delete-function --function-name $LAMBDA_FUNCTION_NAME +aws iam detach-role-policy --role-name "$ROLE_NAME" --policy-arn arn:aws:iam::"$AWS_ACCT_ID":policy/"$POLICY_NAME" +aws iam delete-policy --policy-arn arn:aws:iam::"$AWS_ACCT_ID":policy/"$POLICY_NAME" +aws iam delete-role --role-name "$ROLE_NAME" + +# display logs +printf "6/6 Displaying logs from AWS:\n\n\n" +cat lambdaLogs diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/docker-compose.yml b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/docker-compose.yml new file mode 100644 index 00000000000..6f18fbd29ac --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/docker-compose.yml @@ -0,0 +1,31 @@ +# 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. +version: "3.7" +services: + aws-lambda-client: + build: + dockerfile: $PWD/Dockerfile + context: ../../../../../.. + ports: + - "8080:80" + command: + - "/bin/sh" + - "-c" + - "./build.sh" + volumes: + - ~/.aws:/root/.aws + networks: + - example +networks: + example: diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod new file mode 100644 index 00000000000..fa7e0bc680b --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod @@ -0,0 +1,22 @@ +module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-g/otellambda/example + +go 1.16 + +replace ( + go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../../detectors/aws/lambda + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda => ../ +) + +require ( + github.com/aws/aws-lambda-go v1.25.0 + github.com/aws/aws-sdk-go-v2/config v1.5.0 + github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.21.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0 + go.opentelemetry.io/otel v1.0.0-RC1 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 + go.opentelemetry.io/otel/sdk v1.0.0-RC1 + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum new file mode 100644 index 00000000000..c32e6eb6216 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -0,0 +1,85 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/aws/aws-lambda-go v1.24.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= +github.com/aws/aws-lambda-go v1.25.0 h1:hv0Av6ooQhnqMS2jqeaph0izIwwaV2N6gsT5ad17Ihw= +github.com/aws/aws-lambda-go v1.25.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= +github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= +github.com/aws/aws-sdk-go-v2 v1.7.1 h1:TswSc7KNqZ/K1Ijt3IkpXk/2+62vi3Q82Yrr5wSbRBQ= +github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250= +github.com/aws/aws-sdk-go-v2/config v1.5.0 h1:tRQcWXVmO7wC+ApwYc2LiYKfIBoIrdzcJ+7HIh6AlR0= +github.com/aws/aws-sdk-go-v2/config v1.5.0/go.mod h1:RWlPOAW3E3tbtNAqTwvSW54Of/yP3oiZXMI0xfUdjyA= +github.com/aws/aws-sdk-go-v2/credentials v1.3.1 h1:fFeqL5+9kwFKsCb2oci5yAIDsWYqn/Nga8oQ5bIasI8= +github.com/aws/aws-sdk-go-v2/credentials v1.3.1/go.mod h1:r0n73xwsIVagq8RsxmZbGSRQFj9As3je72C2WzUIToc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.3.0 h1:s4vtv3Mv1CisI3qm2HGHi1Ls9ZtbCOEqeQn6oz7fTyU= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.3.0/go.mod h1:2LAuqPx1I6jNfaGDucWfA2zqQCYCOMCDHiCOciALyNw= +github.com/aws/aws-sdk-go-v2/internal/ini v1.1.1 h1:SDLwr1NKyowP7uqxuLNdvFZhjnoVWxNv456zAp+ZFjU= +github.com/aws/aws-sdk-go-v2/internal/ini v1.1.1/go.mod h1:Zy8smImhTdOETZqfyn01iNOe0CNggVbPjCajyaz6Gvg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.1 h1:s/uV8UyMB4UcO0ERHxG9BJhYJAD9MiY0QeYvJmlC7PE= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.2.1/go.mod h1:v33JQ57i2nekYTA70Mb+O18KeH4KqhdqxTJZNK1zdRE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1 h1:VJe/XEhrfyfBLupcGg1BfUSK2VMZNdbDcZQ49jnp+h0= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1/go.mod h1:zceowr5Z1Nh2WVP8bf/3ikB41IZW59E4yIYbg+pC6mw= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.1 h1:1ds3HkMQEBx9XvOkqsPuqBmNFn0w8XEDuB4LOi6KepU= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.1/go.mod h1:6EQZIwNNvHpq/2/QSJnp4+ECvqIy55w95Ofs0ze+nGQ= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU= +github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= +github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1 h1:HiXhafnqG0AkVJIZA/BHhFvuc/8xFdUO1uaeqF2Artc= +github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1/go.mod h1:XLAGFrEjbvMCLvAtWLLP32yTv8GpBquCApZEycDLunI= +github.com/aws/aws-sdk-go-v2/service/sso v1.3.1 h1:H2ZLWHUbbeYtghuqCY5s/7tbBM99PAwCioRJF8QvV/U= +github.com/aws/aws-sdk-go-v2/service/sso v1.3.1/go.mod h1:J3A3RGUvuCZjvSuZEcOpHDnzZP/sKbhDWV2T1EOzFIM= +github.com/aws/aws-sdk-go-v2/service/sts v1.6.0 h1:Y9r6mrzOyAYz4qKaluSH19zqH1236il/nGbsPKOUT0s= +github.com/aws/aws-sdk-go-v2/service/sts v1.6.0/go.mod h1:q7o0j7d7HrJk/vr9uUt3BVRASvcU7gYZB9PUgPiByXg= +github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= +github.com/aws/smithy-go v1.6.0 h1:T6puApfBcYiTIsaI+SYWqanjMt5pc3aoyyDrI+0YH54= +github.com/aws/smithy-go v1.6.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +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/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= +github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= +github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +go.opentelemetry.io/contrib v0.21.0 h1:RMJ6GlUVzLYp/zmItxTTdAmr1gnpO/HHMFmvjAhvJQM= +go.opentelemetry.io/contrib v0.21.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0 h1:7jzIZ2lh5T4t/9+UjeDPvIKmqUadZB4JUta1gs2OaUI= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0/go.mod h1:O+blok0+ZMWjdDhkO+h8wOklvj5H58+yeLezJ+l6YeY= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0 h1:G1vNyNfKknFvrKVC8ga8EYIECy0s5D/QPW4QPRSMhwc= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= +go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= +go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= +go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 h1:SEfJImgKQ5TP2aTJwN08qhS8oFlYWr/neECGsyuxKWg= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1/go.mod h1:TAM/UYjVd1UdaifWkof3qj9cCW9oINemHfj0K6yodSo= +go.opentelemetry.io/otel/internal/metric v0.21.0 h1:gZlIBo5O51hZOOZz8vEcuRx/l5dnADadKfpT70AELoo= +go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= +go.opentelemetry.io/otel/metric v0.21.0 h1:ZtcJlHqVE4l8Su0WOLOd9fEPheJuYEiQ0wr9wv2p25I= +go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= +go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= +go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go new file mode 100644 index 00000000000..3dc7c4774ca --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -0,0 +1,114 @@ +// 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 main + +import ( + "context" + "encoding/json" + "fmt" + "github.com/aws/aws-lambda-go/lambda" + awsConfig "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/s3" + lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" + "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" + "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "io" + "net/http" +) + +func lambda_handler(ctx context.Context) error { + // init aws config + cfg, err := awsConfig.LoadDefaultConfig(ctx) + if err != nil { + panic("configuration error, " + err.Error()) + } + + // instrument all aws clients + otelaws.AppendMiddlewares(&cfg.APIOptions) + + // S3 + s3Client := s3.NewFromConfig(cfg) + input := &s3.ListBucketsInput{} + result, err := s3Client.ListBuckets(ctx, input) + if err != nil { + fmt.Printf("Got an error retrieving buckets, %v", err) + } + + fmt.Println("Buckets:") + for _, bucket := range result.Buckets { + fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) + } + + + // HTTP + orig := otelhttp.DefaultClient + otelhttp.DefaultClient = &http.Client{ + Transport: otelhttp.NewTransport( + http.DefaultTransport, + otelhttp.WithTracerProvider(otel.GetTracerProvider()), + ), + } + defer func() { otelhttp.DefaultClient = orig }() + res, err := otelhttp.Get(ctx, "https://api.github.com/repos/open-telemetry/opentelemetry-go/releases/latest") + if err != nil { + fmt.Printf("failed to make http request, %v\n", err) + } + + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + fmt.Printf("failed to close http response body, %v\n", err) + } + }(res.Body) + + var data map[string]interface{} + err = json.NewDecoder(res.Body).Decode(&data) + if err != nil { + fmt.Printf("failed to read http response body, %v\n", err) + } + fmt.Printf("Latest OTel Go Release is '%s'\n", data["name"]) + + return nil +} + +func main() { + ctx := context.Background() + + exp, err := stdouttrace.New() + if err != nil { + fmt.Printf("failed to initialize stdout exporter %v\n", err) + return + } + + detector := lambdadetector.NewResourceDetector() + res, err := detector.Detect(ctx) + if err != nil { + fmt.Printf("failed to detect lambda resources: %v\n", err) + } + + tp := sdktrace.NewTracerProvider( + sdktrace.WithSyncer(exp), + sdktrace.WithResource(res), + ) + + // Downstream spans use global tracer provider + otel.SetTracerProvider(tp) + + lambda.Start(otellambda.LambdaHandlerWrapper(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) +} \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh new file mode 100755 index 00000000000..e4af1bba897 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh @@ -0,0 +1,34 @@ +#!/bin/sh + +# constants +LAMBDA_FUNCTION_NAME=SampleLambdaGo +ROLE_NAME="$LAMBDA_FUNCTION_NAME"Role +POLICY_NAME="$LAMBDA_FUNCTION_NAME"Policy +LOG_GROUP_NAME=/aws/lambda/"$LAMBDA_FUNCTION_NAME" +AWS_ACCT_ID=$(aws sts get-caller-identity | jq '.Account | tonumber') +ERROR_LOG_FILE=manualAWSCleanupErrors.log + +# Clear log +rm $ERROR_LOG_FILE 2> /dev/null + +# clear log group of all streams +if aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" > /dev/null 2>> $ERROR_LOG_FILE ; then + LOG_STREAM_NAME=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --order-by LastEventTime --descending | jq --raw-output '.logStreams[0].logStreamName') + while [ "$LOG_STREAM_NAME" != "null" ] ; do + aws logs delete-log-stream --log-group-name "$LOG_GROUP_NAME" --log-stream-name "$LOG_STREAM_NAME" 2>> $ERROR_LOG_FILE && echo "Deleted log stream $LOG_STREAM_NAME" + LOG_STREAM_NAME=$(aws logs describe-log-streams --log-group-name "$LOG_GROUP_NAME" --order-by LastEventTime --descending | jq --raw-output '.logStreams[0].logStreamName') + done + aws logs delete-log-group --log-group-name "$LOG_GROUP_NAME" && echo "Deleted log group $LOG_GROUP_NAME" +else + echo "Did not delete log group, likely already deleted" +fi + +# destroy remaining lambda resources if they exist +aws lambda delete-function --function-name "$LAMBDA_FUNCTION_NAME" 2>> $ERROR_LOG_FILE && echo "Deleted Lambda Function $LAMBDA_FUNCTION_NAME" || echo "Did not delete function, likely already deleted" +aws iam detach-role-policy --role-name "$ROLE_NAME" --policy-arn arn:aws:iam::"$AWS_ACCT_ID":policy/"$POLICY_NAME" 2>> $ERROR_LOG_FILE && echo "Detached $POLICY_NAME from $ROLE_NAME" || echo "Did not detach policy from role, likely already detached" +aws iam delete-policy --policy-arn arn:aws:iam::"$AWS_ACCT_ID":policy/"$POLICY_NAME" 2>> $ERROR_LOG_FILE && echo "Deleted IAM Policy POLICY_NAME" || echo "Did not delete IAM Policy, likely already deleted" +aws iam delete-role --role-name "$ROLE_NAME" 2>> $ERROR_LOG_FILE && echo "Deleted IAM Role $ROLE_NAME" || echo "Did not delete IAM Role, likely already deleted" + +if [ -s $ERROR_LOG_FILE ] ; then + echo 'Some resources failed to delete. Can ensure these errors were due to the resources existing by checking "'$ERROR_LOG_FILE'"' +fi \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/policyForRoleDocument.json b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/policyForRoleDocument.json new file mode 100644 index 00000000000..3932198732c --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/policyForRoleDocument.json @@ -0,0 +1,20 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": "s3:ListAllMyBuckets", + "Resource": "*" + }, + { + "Sid": "", + "Effect": "Allow", + "Action": [ + "logs:PutLogEvents", + "logs:CreateLogStream", + "logs:CreateLogGroup" + ], + "Resource": "*" + } + ] +} \ No newline at end of file From fedb803c7a60dea82aa8551311a612f4eedeb5b5 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:44:36 -0700 Subject: [PATCH 19/43] Add license --- detectors/aws/lambda/detector_test.go | 14 ++++++++++++++ .../aws/aws-lambda-go/otellambda/example/build.sh | 14 ++++++++++++++ .../otellambda/example/manualAWSCleanup.sh | 14 ++++++++++++++ .../aws/aws-lambda-go/otellambda/lambda.go | 14 ++++++++++++++ .../aws/aws-lambda-go/otellambda/lambda_test.go | 14 ++++++++++++++ .../aws-lambda-go/otellambda/test/lambda_test.go | 14 ++++++++++++++ 6 files changed, 84 insertions(+) diff --git a/detectors/aws/lambda/detector_test.go b/detectors/aws/lambda/detector_test.go index 05048f15b59..968ad967bd3 100644 --- a/detectors/aws/lambda/detector_test.go +++ b/detectors/aws/lambda/detector_test.go @@ -1,3 +1,17 @@ +// 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 ( diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh index 58bbce37b4a..c8bba60a005 100755 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/build.sh @@ -1,5 +1,19 @@ #!/bin/sh +# 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. + # constants LAMBDA_FUNCTION_NAME=SampleLambdaGo ROLE_NAME="$LAMBDA_FUNCTION_NAME"Role diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh index e4af1bba897..2cbdbe249ea 100755 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/manualAWSCleanup.sh @@ -1,5 +1,19 @@ #!/bin/sh +# 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. + # constants LAMBDA_FUNCTION_NAME=SampleLambdaGo ROLE_NAME="$LAMBDA_FUNCTION_NAME"Role diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index c0a52ca37d2..33e2ae3cfdf 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -1,3 +1,17 @@ +// 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 otellambda import ( diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index 257538a10e5..9df623cc61c 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -1,3 +1,17 @@ +// 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 otellambda import ( diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 711833aaf61..09dfe61ccf8 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -1,3 +1,17 @@ +// 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 test import ( From 38a9e9107b5f8a72f8174ba7230f38dad65ef8c3 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 12:48:13 -0700 Subject: [PATCH 20/43] Add gomod checks for otellambda /example and /test modules --- .github/dependabot.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 76fc3c82a4f..f4c6a18be52 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -175,6 +175,26 @@ updates: 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" From 6cc43b2596123d5fdf16888324e46aaddd473e9b Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:37:19 -0700 Subject: [PATCH 21/43] Refactor entrypoints into seperate files and update entrypoint names --- .../aws-lambda-go/otellambda/example/main.go | 2 +- .../aws/aws-lambda-go/otellambda/lambda.go | 217 +----------------- .../aws-lambda-go/otellambda/lambda_test.go | 10 +- .../otellambda/test/lambda_test.go | 6 +- .../aws-lambda-go/otellambda/wrapHandler.go | 44 ++++ .../otellambda/wrapLambdaHandler.go | 185 +++++++++++++++ 6 files changed, 241 insertions(+), 223 deletions(-) create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index 3dc7c4774ca..81e503dc211 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -110,5 +110,5 @@ func main() { // Downstream spans use global tracer provider otel.SetTracerProvider(tp) - lambda.Start(otellambda.LambdaHandlerWrapper(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) + lambda.Start(otellambda.WrapLambdaHandler(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) } \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 33e2ae3cfdf..54ac311bce5 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -16,18 +16,13 @@ package otellambda import ( "context" - "encoding/json" - "fmt" "log" "os" - "reflect" "strings" - "github.com/aws/aws-lambda-go/lambda" "github.com/aws/aws-lambda-go/lambdacontext" "go.opentelemetry.io/contrib/propagators/aws/xray" - "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" @@ -70,147 +65,10 @@ type InstrumentationOptions struct { var configuration InstrumentationOptions -func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { - return func(context.Context, interface{}) (interface{}, error) { - return nil, e - } -} - -// Ensure handler takes 0-2 values, with context -// as its first value if two arguments exist -func validateArguments(handler reflect.Type) (bool, error) { - handlerTakesContext := false - if handler.NumIn() > 2 { - return false, fmt.Errorf("handlers may not take more than two arguments, but handler takes %d", handler.NumIn()) - } else if handler.NumIn() > 0 { - contextType := reflect.TypeOf((*context.Context)(nil)).Elem() - argumentType := handler.In(0) - handlerTakesContext = argumentType.Implements(contextType) - if handler.NumIn() > 1 && !handlerTakesContext { - return false, fmt.Errorf("handler takes two arguments, but the first is not Context. got %s", argumentType.Kind()) - } - } - - return handlerTakesContext, nil -} - -// Ensure handler returns 0-2 values, with an error -// as its first value if any exist -func validateReturns(handler reflect.Type) error { - errorType := reflect.TypeOf((*error)(nil)).Elem() - - switch n := handler.NumOut(); { - case n > 2: - return fmt.Errorf("handler may not return more than two values") - case n == 2: - if !handler.Out(1).Implements(errorType) { - return fmt.Errorf("handler returns two values, but the second does not implement error") - } - case n == 1: - if !handler.Out(0).Implements(errorType) { - return fmt.Errorf("handler returns a single value, but it does not implement error") - } - } - - return nil -} - -// Wraps and calls customer lambda handler then unpacks response as necessary -func wrapperInternals(ctx context.Context, handlerFunc interface{}, event reflect.Value, takesContext bool) (interface{}, error) { - wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) - - argsWrapped := []reflect.Value{reflect.ValueOf(ctx), event, reflect.ValueOf(takesContext)} - response := wrappedLambdaHandler.Call(argsWrapped)[0].Interface().([]reflect.Value) - - // convert return values into (interface{}, error) - var err error - if len(response) > 0 { - if errVal, ok := response[len(response)-1].Interface().(error); ok { - err = errVal - } - } - var val interface{} - if len(response) > 1 { - val = response[0].Interface() - } - - return val, err -} - -// converts the given payload to the correct event type -func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, error) { - event := reflect.New(eventType) - - // lambda SDK normally unmarshalls to customer event type, however - // with the wrapper the SDK unmarshalls to map[string]interface{} - // due to our use of reflection. Therefore we must convert this map - // to customer's desired event, we do so by simply re-marshalling then - // unmarshalling to the desired event type - remarshalledPayload, err := json.Marshal(payload) - if err != nil { - return reflect.Value{}, err - } - - if err := json.Unmarshal(remarshalledPayload, event.Interface()); err != nil { - return reflect.Value{}, err - } - return event, nil -} - -// LambdaHandlerWrapper Provides a lambda handler which wraps customer lambda handler with OTel Tracing -func LambdaHandlerWrapper(handlerFunc interface{}, options ...InstrumentationOption) interface{} { - o := InstrumentationOptions{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, - } - for _, opt := range options { - opt(&o) - } - configuration = o - - if handlerFunc == nil { - return errorHandler(fmt.Errorf("handler is nil")) - } - handlerType := reflect.TypeOf(handlerFunc) - if handlerType.Kind() != reflect.Func { - return errorHandler(fmt.Errorf("handler kind %s is not %s", handlerType.Kind(), reflect.Func)) - } - - takesContext, err := validateArguments(handlerType) - if err != nil { - return errorHandler(err) - } - - if err := validateReturns(handlerType); err != nil { - return errorHandler(err) - } - - // note we will always take context to capture lambda context, - // regardless of whether customer takes context - if handlerType.NumIn() == 0 || handlerType.NumIn() == 1 && takesContext { - return func(ctx context.Context) (interface{}, error) { - var temp *interface{} - event := reflect.ValueOf(temp) - return wrapperInternals(ctx, handlerFunc, event, takesContext) - } - } else { // customer either takes both context and payload or just payload - return func(ctx context.Context, payload interface{}) (interface{}, error) { - event, err := payloadToEvent(handlerType.In(handlerType.NumIn()-1), payload) - if err != nil { - return nil, err - } - return wrapperInternals(ctx, handlerFunc, event.Elem(), takesContext) - } - } -} - // basic implementation of TextMapCarrier // which wraps the default map type type mapCarrier map[string]string -// Compile time check our mapCarrier implements propagation.TextMapCarrier -var _ propagation.TextMapCarrier = mapCarrier{} - // Get returns the value associated with the passed key. func (mc mapCarrier) Get(key string) string { return mc[key] @@ -230,79 +88,8 @@ func (mc mapCarrier) Keys() []string { return keys } -// Adds OTel span surrounding customer handler call -func wrapper(handlerFunc interface{}) func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { - return func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { - - ctx, span := tracingBegin(ctx) - defer tracingEnd(ctx, span) - - handler := reflect.ValueOf(handlerFunc) - var args []reflect.Value - if takesContext { - args = append(args, reflect.ValueOf(ctx)) - } - if eventExists(event) { - args = append(args, reflect.ValueOf(event)) - } - - response := handler.Call(args) - - return response - } -} - -// Determine if an interface{} is nil or the -// if the reflect.Value of the event is nil -func eventExists(event interface{}) bool { - if event == nil { - return false - } - - // reflect.Value.isNil() can only be called on - // Values of certain Kinds. Unsupported Kinds - // will panic rather than return false - switch reflect.TypeOf(event).Kind() { - case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: - return !reflect.ValueOf(event).IsNil() - } - return true -} - -type wrappedHandler struct { - handler lambda.Handler -} - -// Compile time check our Handler implements lambda.Handler -var _ lambda.Handler = wrappedHandler{} - -// Invoke adds OTel span surrounding customer Handler invocation -func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) { - - ctx, span := tracingBegin(ctx) - defer tracingEnd(ctx, span) - - response, err := h.handler.Invoke(ctx, payload) - if err != nil { - return nil, err - } - - return response, nil -} - -// HandlerWrapper Provides a Handler which wraps customer Handler with OTel Tracing -func HandlerWrapper(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { - o := InstrumentationOptions{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, - } - for _, opt := range options { - opt(&o) - } - configuration = o - - return wrappedHandler{handler: handler} -} +// Compile time check our mapCarrier implements propagation.TextMapCarrier +var _ propagation.TextMapCarrier = mapCarrier{} // Logic to start OTel Tracing func tracingBegin(ctx context.Context) (context.Context, trace.Span) { diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index 9df623cc61c..b6f038e559b 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -131,7 +131,7 @@ func TestLambdaHandlerSignatures(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("testCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := LambdaHandlerWrapper(testCase.handler) + lambdaHandler := WrapLambdaHandler(testCase.handler) handler := reflect.ValueOf(lambdaHandler) resp := handler.Call(testCase.args) assert.Equal(t, 2, len(resp)) @@ -228,7 +228,7 @@ func TestHandlerInvokes(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("lambdaHandlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := LambdaHandlerWrapper(testCase.handler) + lambdaHandler := WrapLambdaHandler(testCase.handler) handler := reflect.ValueOf(lambdaHandler) handlerType := handler.Type() @@ -253,7 +253,7 @@ func TestHandlerInvokes(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("handlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { - handler := HandlerWrapper(lambda.NewHandler(testCase.handler)) + handler := WrapHandler(lambda.NewHandler(testCase.handler)) inputPayload, _ := json.Marshal(testCase.input) response, err := handler.Invoke(mockContext, inputPayload) if testCase.expected.err != nil { @@ -272,7 +272,7 @@ func BenchmarkLambdaHandlerWrapper(b *testing.B) { customerHandler := func(ctx context.Context, payload int) error { return nil } - wrapped := LambdaHandlerWrapper(customerHandler) + wrapped := WrapLambdaHandler(customerHandler) wrappedCallable := reflect.ValueOf(wrapped) ctx := reflect.ValueOf(mockContext) payload := reflect.ValueOf(0) @@ -287,7 +287,7 @@ func BenchmarkLambdaHandlerWrapper(b *testing.B) { func BenchmarkHandlerWrapper(b *testing.B) { setEnvVars() - wrapped := HandlerWrapper(emptyHandler{}) + wrapped := WrapHandler(emptyHandler{}) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 09dfe61ccf8..401dbeaf742 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -200,7 +200,8 @@ func TestLambdaHandlerWrapperTracing(t *testing.T) { return "hello world", nil } - wrapped := otellambda.LambdaHandlerWrapper(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp)) + // No flusher needed as SimpleSpanProcessor is synchronous + wrapped := otellambda.WrapLambdaHandler(customerHandler, otellambda.WithTracerProvider(tp)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) assert.Len(t, resp, 2) @@ -216,7 +217,8 @@ func TestHandlerWrapperTracing(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() - wrapped := otellambda.HandlerWrapper(emptyHandler{}, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp)) + // No flusher needed as SimpleSpanProcessor is synchronous + wrapped := otellambda.WrapHandler(emptyHandler{}, otellambda.WithTracerProvider(tp)) _, err := wrapped.Invoke(mockContext, nil) assert.NoError(t, err) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go new file mode 100644 index 00000000000..2678b6ec203 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go @@ -0,0 +1,44 @@ +package otellambda + +import ( + "context" + + "github.com/aws/aws-lambda-go/lambda" + + "go.opentelemetry.io/otel" +) + +type wrappedHandler struct { + handler lambda.Handler +} + +// Compile time check our Handler implements lambda.Handler +var _ lambda.Handler = wrappedHandler{} + +// Invoke adds OTel span surrounding customer Handler invocation +func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) { + + ctx, span := tracingBegin(ctx) + defer tracingEnd(ctx, span) + + response, err := h.handler.Invoke(ctx, payload) + if err != nil { + return nil, err + } + + return response, nil +} + +// WrapHandler Provides a Handler which wraps customer Handler with OTel Tracing +func WrapHandler(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { + o := InstrumentationOptions{ + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + } + for _, opt := range options { + opt(&o) + } + configuration = o + + return wrappedHandler{handler: handler} +} \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go new file mode 100644 index 00000000000..1d8008dfa7c --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -0,0 +1,185 @@ +package otellambda + +import ( + "context" + "encoding/json" + "fmt" + "reflect" + + "go.opentelemetry.io/otel" +) + + +func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { + return func(context.Context, interface{}) (interface{}, error) { + return nil, e + } +} + +// Ensure handler takes 0-2 values, with context +// as its first value if two arguments exist +func validateArguments(handler reflect.Type) (bool, error) { + handlerTakesContext := false + if handler.NumIn() > 2 { + return false, fmt.Errorf("handlers may not take more than two arguments, but handler takes %d", handler.NumIn()) + } else if handler.NumIn() > 0 { + contextType := reflect.TypeOf((*context.Context)(nil)).Elem() + argumentType := handler.In(0) + handlerTakesContext = argumentType.Implements(contextType) + if handler.NumIn() > 1 && !handlerTakesContext { + return false, fmt.Errorf("handler takes two arguments, but the first is not Context. got %s", argumentType.Kind()) + } + } + + return handlerTakesContext, nil +} + +// Ensure handler returns 0-2 values, with an error +// as its first value if any exist +func validateReturns(handler reflect.Type) error { + errorType := reflect.TypeOf((*error)(nil)).Elem() + + switch n := handler.NumOut(); { + case n > 2: + return fmt.Errorf("handler may not return more than two values") + case n == 2: + if !handler.Out(1).Implements(errorType) { + return fmt.Errorf("handler returns two values, but the second does not implement error") + } + case n == 1: + if !handler.Out(0).Implements(errorType) { + return fmt.Errorf("handler returns a single value, but it does not implement error") + } + } + + return nil +} + +// Wraps and calls customer lambda handler then unpacks response as necessary +func wrapperInternals(ctx context.Context, handlerFunc interface{}, event reflect.Value, takesContext bool) (interface{}, error) { + wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) + + argsWrapped := []reflect.Value{reflect.ValueOf(ctx), event, reflect.ValueOf(takesContext)} + response := wrappedLambdaHandler.Call(argsWrapped)[0].Interface().([]reflect.Value) + + // convert return values into (interface{}, error) + var err error + if len(response) > 0 { + if errVal, ok := response[len(response)-1].Interface().(error); ok { + err = errVal + } + } + var val interface{} + if len(response) > 1 { + val = response[0].Interface() + } + + return val, err +} + +// converts the given payload to the correct event type +func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, error) { + event := reflect.New(eventType) + + // lambda SDK normally unmarshalls to customer event type, however + // with the wrapper the SDK unmarshalls to map[string]interface{} + // due to our use of reflection. Therefore we must convert this map + // to customer's desired event, we do so by simply re-marshalling then + // unmarshalling to the desired event type + remarshalledPayload, err := json.Marshal(payload) + if err != nil { + return reflect.Value{}, err + } + + if err := json.Unmarshal(remarshalledPayload, event.Interface()); err != nil { + return reflect.Value{}, err + } + return event, nil +} + +// WrapLambdaHandler Provides a lambda handler which wraps customer lambda handler with OTel Tracing +func WrapLambdaHandler(handlerFunc interface{}, options ...InstrumentationOption) interface{} { + o := InstrumentationOptions{ + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + } + for _, opt := range options { + opt(&o) + } + configuration = o + + if handlerFunc == nil { + return errorHandler(fmt.Errorf("handler is nil")) + } + handlerType := reflect.TypeOf(handlerFunc) + if handlerType.Kind() != reflect.Func { + return errorHandler(fmt.Errorf("handler kind %s is not %s", handlerType.Kind(), reflect.Func)) + } + + takesContext, err := validateArguments(handlerType) + if err != nil { + return errorHandler(err) + } + + if err := validateReturns(handlerType); err != nil { + return errorHandler(err) + } + + // note we will always take context to capture lambda context, + // regardless of whether customer takes context + if handlerType.NumIn() == 0 || handlerType.NumIn() == 1 && takesContext { + return func(ctx context.Context) (interface{}, error) { + var temp *interface{} + event := reflect.ValueOf(temp) + return wrapperInternals(ctx, handlerFunc, event, takesContext) + } + } else { // customer either takes both context and payload or just payload + return func(ctx context.Context, payload interface{}) (interface{}, error) { + event, err := payloadToEvent(handlerType.In(handlerType.NumIn()-1), payload) + if err != nil { + return nil, err + } + return wrapperInternals(ctx, handlerFunc, event.Elem(), takesContext) + } + } +} + +// Adds OTel span surrounding customer handler call +func wrapper(handlerFunc interface{}) func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { + return func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { + + ctx, span := tracingBegin(ctx) + defer tracingEnd(ctx, span) + + handler := reflect.ValueOf(handlerFunc) + var args []reflect.Value + if takesContext { + args = append(args, reflect.ValueOf(ctx)) + } + if eventExists(event) { + args = append(args, reflect.ValueOf(event)) + } + + response := handler.Call(args) + + return response + } +} + +// Determine if an interface{} is nil or the +// if the reflect.Value of the event is nil +func eventExists(event interface{}) bool { + if event == nil { + return false + } + + // reflect.Value.isNil() can only be called on + // Values of certain Kinds. Unsupported Kinds + // will panic rather than return false + switch reflect.TypeOf(event).Kind() { + case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: + return !reflect.ValueOf(event).IsNil() + } + return true +} + From f0b4a7fd3118ffb3297f03c0248c0c33b360f66c Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 13:47:56 -0700 Subject: [PATCH 22/43] Remove redundant computations of lambda resources --- .../aws/aws-lambda-go/otellambda/lambda.go | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 54ac311bce5..8a1524e4dca 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -64,6 +64,7 @@ type InstrumentationOptions struct { } var configuration InstrumentationOptions +var resourceAttributesToAddAsSpanAttributes []attribute.KeyValue // basic implementation of TextMapCarrier // which wraps the default map type @@ -115,14 +116,19 @@ func tracingBegin(ctx context.Context) (context.Context, trace.Span) { ctxRequestID := lc.AwsRequestID attributes = append(attributes, semconv.FaaSExecutionKey.String(ctxRequestID)) - // Resource attrs added as span attr due to static tp - // being created without meaningful context - ctxFunctionArn := lc.InvokedFunctionArn - attributes = append(attributes, semconv.FaaSIDKey.String(ctxFunctionArn)) - arnParts := strings.Split(ctxFunctionArn, ":") - if len(arnParts) >= 5 { - attributes = append(attributes, semconv.CloudAccountIDKey.String(arnParts[4])) + // Some resource attrs added as span attrs because lambda + // resource detectors are created before a lambda + // invocation and therefore lack lambdacontext. + // Create these attrs upon first invocation + if resourceAttributesToAddAsSpanAttributes == nil { + ctxFunctionArn := lc.InvokedFunctionArn + attributes = append(attributes, semconv.FaaSIDKey.String(ctxFunctionArn)) + arnParts := strings.Split(ctxFunctionArn, ":") + if len(arnParts) >= 5 { + attributes = append(attributes, semconv.CloudAccountIDKey.String(arnParts[4])) + } } + attributes = append(attributes, resourceAttributesToAddAsSpanAttributes...) } ctx, span = tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) From 6df424c59bdf558d62fef8eef0044e3586f35ee3 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Mon, 26 Jul 2021 14:19:43 -0700 Subject: [PATCH 23/43] Create and store tracer upon entry --- .../github.com/aws/aws-lambda-go/otellambda/go.mod | 6 ++++++ .../github.com/aws/aws-lambda-go/otellambda/go.sum | 2 -- .../github.com/aws/aws-lambda-go/otellambda/lambda.go | 4 +--- .../github.com/aws/aws-lambda-go/otellambda/test/go.mod | 3 +++ .../github.com/aws/aws-lambda-go/otellambda/test/go.sum | 2 -- .../aws/aws-lambda-go/otellambda/test/lambda_test.go | 7 ++++--- .../github.com/aws/aws-lambda-go/otellambda/wrapHandler.go | 4 ++++ .../aws/aws-lambda-go/otellambda/wrapLambdaHandler.go | 4 ++++ 8 files changed, 22 insertions(+), 10 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index 23ec3cfeae6..13eb3dcef8e 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -2,9 +2,15 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/ go 1.16 +replace ( + go.opentelemetry.io/contrib => ../../../../.. + go.opentelemetry.io/contrib/propagators/aws => ../../../../../propagators/aws +) + require ( github.com/aws/aws-lambda-go v1.24.0 github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/contrib v0.21.0 go.opentelemetry.io/contrib/propagators/aws v0.21.0 go.opentelemetry.io/otel v1.0.0-RC1 go.opentelemetry.io/otel/trace v1.0.0-RC1 diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index b43415cf660..5ca286fbceb 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -17,8 +17,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= -go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 8a1524e4dca..184c9ce5099 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -65,6 +65,7 @@ type InstrumentationOptions struct { var configuration InstrumentationOptions var resourceAttributesToAddAsSpanAttributes []attribute.KeyValue +var tracer trace.Tracer // basic implementation of TextMapCarrier // which wraps the default map type @@ -101,9 +102,6 @@ func tracingBegin(ctx context.Context) (context.Context, trace.Span) { propagator := xray.Propagator{} ctx = propagator.Extract(ctx, mc) - // Get a named tracer with package path as its name. - tracer := configuration.TracerProvider.Tracer(tracerName) - var span trace.Span spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod index 5a16e15473b..df8306b89f3 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod @@ -3,13 +3,16 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/ go 1.16 replace ( + go.opentelemetry.io/contrib => ../../../../../.. go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../../detectors/aws/lambda go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda => ../ + go.opentelemetry.io/contrib/propagators/aws => ../../../../../../propagators/aws ) require ( github.com/aws/aws-lambda-go v1.25.0 github.com/stretchr/testify v1.7.0 + go.opentelemetry.io/contrib v0.21.0 go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.21.0 go.opentelemetry.io/contrib/propagators/aws v0.21.0 diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index 73ee0993bcf..22ca04ecdbf 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -18,8 +18,6 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= -go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 401dbeaf742..26ab514ec84 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -16,8 +16,6 @@ package test import ( "context" - "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" - "go.opentelemetry.io/otel/propagation" "log" "os" "reflect" @@ -29,9 +27,12 @@ import ( "github.com/aws/aws-lambda-go/lambdacontext" "github.com/stretchr/testify/assert" + "go.opentelemetry.io/contrib" lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" + "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" "go.opentelemetry.io/contrib/propagators/aws/xray" "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/instrumentation" "go.opentelemetry.io/otel/sdk/resource" sdktrace "go.opentelemetry.io/otel/sdk/trace" @@ -172,7 +173,7 @@ var expectedSpanStub = tracetest.SpanStub{ attribute.String("cloud.region", "us-texas-1"), attribute.String("faas.name", "testFunction"), attribute.String("faas.version", "$LATEST")), - InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda"}, + InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda", Version: contrib.SemVersion()}, } func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actual tracetest.SpanStub) { diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go index 2678b6ec203..261350a11b9 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go @@ -5,7 +5,9 @@ import ( "github.com/aws/aws-lambda-go/lambda" + "go.opentelemetry.io/contrib" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" ) type wrappedHandler struct { @@ -39,6 +41,8 @@ func WrapHandler(handler lambda.Handler, options ...InstrumentationOption) lambd opt(&o) } configuration = o + // Get a named tracer with package path as its name. + tracer = configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) return wrappedHandler{handler: handler} } \ No newline at end of file diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index 1d8008dfa7c..930a900c4fc 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -6,7 +6,9 @@ import ( "fmt" "reflect" + "go.opentelemetry.io/contrib" "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/trace" ) @@ -107,6 +109,8 @@ func WrapLambdaHandler(handlerFunc interface{}, options ...InstrumentationOption opt(&o) } configuration = o + // Get a named tracer with package path as its name. + tracer = configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) if handlerFunc == nil { return errorHandler(fmt.Errorf("handler is nil")) From 5b70dfef00dc714620f37a3eaa97f188b2ca246b Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Tue, 27 Jul 2021 10:03:13 -0700 Subject: [PATCH 24/43] Rename handler function wrapper to WrapHandlerFunction --- .../github.com/aws/aws-lambda-go/otellambda/lambda_test.go | 6 +++--- .../aws/aws-lambda-go/otellambda/test/lambda_test.go | 2 +- .../aws/aws-lambda-go/otellambda/wrapLambdaHandler.go | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index b6f038e559b..36c42871b09 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -131,7 +131,7 @@ func TestLambdaHandlerSignatures(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("testCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := WrapLambdaHandler(testCase.handler) + lambdaHandler := WrapHandlerFunction(testCase.handler) handler := reflect.ValueOf(lambdaHandler) resp := handler.Call(testCase.args) assert.Equal(t, 2, len(resp)) @@ -228,7 +228,7 @@ func TestHandlerInvokes(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("lambdaHandlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := WrapLambdaHandler(testCase.handler) + lambdaHandler := WrapHandlerFunction(testCase.handler) handler := reflect.ValueOf(lambdaHandler) handlerType := handler.Type() @@ -272,7 +272,7 @@ func BenchmarkLambdaHandlerWrapper(b *testing.B) { customerHandler := func(ctx context.Context, payload int) error { return nil } - wrapped := WrapLambdaHandler(customerHandler) + wrapped := WrapHandlerFunction(customerHandler) wrappedCallable := reflect.ValueOf(wrapped) ctx := reflect.ValueOf(mockContext) payload := reflect.ValueOf(0) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 26ab514ec84..95860cab036 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -202,7 +202,7 @@ func TestLambdaHandlerWrapperTracing(t *testing.T) { } // No flusher needed as SimpleSpanProcessor is synchronous - wrapped := otellambda.WrapLambdaHandler(customerHandler, otellambda.WithTracerProvider(tp)) + wrapped := otellambda.WrapHandlerFunction(customerHandler, otellambda.WithTracerProvider(tp)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) assert.Len(t, resp, 2) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index 930a900c4fc..0037c9a2f11 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -99,8 +99,8 @@ func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, return event, nil } -// WrapLambdaHandler Provides a lambda handler which wraps customer lambda handler with OTel Tracing -func WrapLambdaHandler(handlerFunc interface{}, options ...InstrumentationOption) interface{} { +// WrapHandlerFunction Provides a lambda handler which wraps customer lambda handler with OTel Tracing +func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOption) interface{} { o := InstrumentationOptions{ TracerProvider: otel.GetTracerProvider(), Flusher: &noopFlusher{}, From 9de0d34364e0e571ea25053b1a3185ba7b3abcf0 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Tue, 27 Jul 2021 10:33:32 -0700 Subject: [PATCH 25/43] Add go doc --- .../aws/aws-lambda-go/otellambda/doc.go | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go new file mode 100644 index 00000000000..100fce7001d --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go @@ -0,0 +1,22 @@ +// 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 otellambda instruments the github.com/aws/aws-lambda-go package. +// +// Two wrappers are provided which can be used to instrument Lambda, +// one for each Lambda entrypoint. Their usages are shown below. +// +// lambda.Start() entrypoint: lambda.Start(otellambda.WrapHandlerFunction()) +// lambda.StartHandler() entrypoint: lambda.StartHandler(otellambda.WrapHandler()) +package otellambda // import "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" From 51144f51843e73fe0a82f29975f7a232b5164e6c Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Tue, 27 Jul 2021 14:30:32 -0700 Subject: [PATCH 26/43] Correct for wrapper name changes --- .../aws/aws-lambda-go/otellambda/example/main.go | 7 +++---- .../github.com/aws/aws-lambda-go/otellambda/lambda_test.go | 5 ++--- .../aws/aws-lambda-go/otellambda/test/lambda_test.go | 4 ++-- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index 81e503dc211..fbc9a5243a0 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -32,7 +32,7 @@ import ( "net/http" ) -func lambda_handler(ctx context.Context) error { +func lambda_handler(ctx context.Context) error { // init aws config cfg, err := awsConfig.LoadDefaultConfig(ctx) if err != nil { @@ -55,7 +55,6 @@ func lambda_handler(ctx context.Context) error { fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) } - // HTTP orig := otelhttp.DefaultClient otelhttp.DefaultClient = &http.Client{ @@ -110,5 +109,5 @@ func main() { // Downstream spans use global tracer provider otel.SetTracerProvider(tp) - lambda.Start(otellambda.WrapLambdaHandler(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) -} \ No newline at end of file + lambda.Start(otellambda.WrapHandlerFunction(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index 36c42871b09..6febd43c47f 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -42,7 +42,6 @@ var ( mockContext = lambdacontext.NewContext(context.TODO(), &mockLambdaContext) ) - type emptyHandler struct{} func (h emptyHandler) Invoke(_ context.Context, _ []byte) ([]byte, error) { @@ -266,7 +265,7 @@ func TestHandlerInvokes(t *testing.T) { } } -func BenchmarkLambdaHandlerWrapper(b *testing.B) { +func BenchmarkWrapHandlerFunction(b *testing.B) { setEnvVars() customerHandler := func(ctx context.Context, payload int) error { @@ -284,7 +283,7 @@ func BenchmarkLambdaHandlerWrapper(b *testing.B) { } } -func BenchmarkHandlerWrapper(b *testing.B) { +func BenchmarkWrapHandler(b *testing.B) { setEnvVars() wrapped := WrapHandler(emptyHandler{}) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 95860cab036..1692319c14a 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -193,7 +193,7 @@ func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actua assert.Equal(t, expected.InstrumentationLibrary, actual.InstrumentationLibrary) } -func TestLambdaHandlerWrapperTracing(t *testing.T) { +func TestWrapHandlerFunctionTracing(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() @@ -214,7 +214,7 @@ func TestLambdaHandlerWrapperTracing(t *testing.T) { assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) } -func TestHandlerWrapperTracing(t *testing.T) { +func TestWrapHandlerTracing(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() From 8f8e491f39f224649353cda2a03a61be2293f5de Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 05:36:55 -0700 Subject: [PATCH 27/43] Further decouple instrumentation from SDK by supporting custom propagator. --- .../aws-lambda-go/otellambda/example/go.sum | 2 - .../aws-lambda-go/otellambda/example/main.go | 10 +- .../aws/aws-lambda-go/otellambda/go.mod | 2 - .../aws/aws-lambda-go/otellambda/go.sum | 2 - .../aws/aws-lambda-go/otellambda/lambda.go | 67 ++-- .../aws/aws-lambda-go/otellambda/test/doc.go | 2 +- .../otellambda/test/lambda_test.go | 333 +++++++++++++----- .../aws-lambda-go/otellambda/wrapHandler.go | 25 +- .../otellambda/wrapLambdaHandler.go | 82 +++-- 9 files changed, 357 insertions(+), 168 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum index c32e6eb6216..fc2f8b4bbf7 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -58,8 +58,6 @@ go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0/go.mod h1:O+blok0+ZMWjdDhkO+h8wOklvj5H58+yeLezJ+l6YeY= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0 h1:G1vNyNfKknFvrKVC8ga8EYIECy0s5D/QPW4QPRSMhwc= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= -go.opentelemetry.io/contrib/propagators/aws v0.21.0 h1:UwLcaHxOxKQjoxbnaIs1CMyHOx0a+s+X6Op48pJD758= -go.opentelemetry.io/contrib/propagators/aws v0.21.0/go.mod h1:f57X7xnBA3tv9ci/zq3KqkEAWBdXoSthcRRgGlpCxSI= go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 h1:SEfJImgKQ5TP2aTJwN08qhS8oFlYWr/neECGsyuxKWg= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index fbc9a5243a0..f1469330129 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -18,9 +18,13 @@ import ( "context" "encoding/json" "fmt" + "io" + "net/http" + "github.com/aws/aws-lambda-go/lambda" awsConfig "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/s3" + lambdadetector "go.opentelemetry.io/contrib/detectors/aws/lambda" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws" @@ -28,11 +32,9 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" sdktrace "go.opentelemetry.io/otel/sdk/trace" - "io" - "net/http" ) -func lambda_handler(ctx context.Context) error { +func lambdaHandler(ctx context.Context) error { // init aws config cfg, err := awsConfig.LoadDefaultConfig(ctx) if err != nil { @@ -109,5 +111,5 @@ func main() { // Downstream spans use global tracer provider otel.SetTracerProvider(tp) - lambda.Start(otellambda.WrapHandlerFunction(lambda_handler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp))) + lambda.Start(otellambda.WrapHandlerFunction(lambdaHandler, otellambda.WithTracerProvider(tp))) } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index 13eb3dcef8e..7c23a9dcf67 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -4,14 +4,12 @@ go 1.16 replace ( go.opentelemetry.io/contrib => ../../../../.. - go.opentelemetry.io/contrib/propagators/aws => ../../../../../propagators/aws ) require ( github.com/aws/aws-lambda-go v1.24.0 github.com/stretchr/testify v1.7.0 go.opentelemetry.io/contrib v0.21.0 - go.opentelemetry.io/contrib/propagators/aws v0.21.0 go.opentelemetry.io/otel v1.0.0-RC1 go.opentelemetry.io/otel/trace v1.0.0-RC1 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index 5ca286fbceb..be918d5fc3e 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -21,8 +21,6 @@ go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcd go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= -go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 184c9ce5099..75990a99652 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -22,7 +22,6 @@ import ( "github.com/aws/aws-lambda-go/lambdacontext" - "go.opentelemetry.io/contrib/propagators/aws/xray" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" @@ -46,6 +45,12 @@ func (*noopFlusher) ForceFlush(context.Context) error { return nil } // Compile time check our noopFlusher implements FLusher var _ Flusher = &noopFlusher{} +type EventToTextMapCarrierConverter func([]byte) propagation.TextMapCarrier + +func noopEventToTextMapCarrierConverter([]byte) propagation.TextMapCarrier { + return propagation.HeaderCarrier{} +} + type InstrumentationOption func(o *InstrumentationOptions) type InstrumentationOptions struct { @@ -61,46 +66,30 @@ type InstrumentationOptions struct { // The default value of Flusher is a noop Flusher, using this // default can result in long data delays in asynchronous settings Flusher Flusher + + // eventToTextMapCarrierConverter is the mechanism used to retrieve the TraceID + // from the event or environment and generate a TextMapCarrier which + // can then be used by a Propagator to extract the TraceID into our context + // The default value of eventToTextMapCarrierConverter returns an empty + // HeaderCarrier, using this default will cause all spans to be not be traced + EventToTextMapCarrierConverter EventToTextMapCarrierConverter + + // Propagator is the Propagator which will be used + // to extrract Trace info into the context + // The default value of Propagator the global otel Propagator + // returned by otel.GetTextMapPropagator() + Propagator propagation.TextMapPropagator } var configuration InstrumentationOptions var resourceAttributesToAddAsSpanAttributes []attribute.KeyValue var tracer trace.Tracer -// basic implementation of TextMapCarrier -// which wraps the default map type -type mapCarrier map[string]string - -// Get returns the value associated with the passed key. -func (mc mapCarrier) Get(key string) string { - return mc[key] -} - -// Set stores the key-value pair. -func (mc mapCarrier) Set(key string, value string) { - mc[key] = value -} - -// Keys lists the keys stored in this carrier. -func (mc mapCarrier) Keys() []string { - keys := make([]string, 0, len(mc)) - for k := range mc { - keys = append(keys, k) - } - return keys -} - -// Compile time check our mapCarrier implements propagation.TextMapCarrier -var _ propagation.TextMapCarrier = mapCarrier{} - // Logic to start OTel Tracing -func tracingBegin(ctx context.Context) (context.Context, trace.Span) { +func tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace.Span) { // Add trace id to context - xrayTraceId := os.Getenv("_X_AMZN_TRACE_ID") - mc := mapCarrier{} - mc.Set("X-Amzn-Trace-Id", xrayTraceId) - propagator := xray.Propagator{} - ctx = propagator.Extract(ctx, mc) + mc := configuration.EventToTextMapCarrierConverter(eventJSON) + ctx = configuration.Propagator.Extract(ctx, mc) var span trace.Span spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") @@ -156,3 +145,15 @@ func WithFlusher(flusher Flusher) InstrumentationOption { o.Flusher = flusher } } + +func WithEventToTextMapCarrierConverter(eventToTextMapCarrierConverter EventToTextMapCarrierConverter) InstrumentationOption { + return func(o *InstrumentationOptions) { + o.EventToTextMapCarrierConverter = eventToTextMapCarrierConverter + } +} + +func WithPropagator(propagator propagation.TextMapPropagator) InstrumentationOption { + return func(o *InstrumentationOptions) { + o.Propagator = propagator + } +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go index 457d9968139..38688f5d9db 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/doc.go @@ -18,4 +18,4 @@ This package is in a separate module from the instrumentation it tests to isolate the dependency of the default SDK and not impose this as a transitive dependency for users. */ -package test \ No newline at end of file +package test diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 1692319c14a..effed697235 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -16,9 +16,13 @@ package test import ( "context" + "encoding/json" + "fmt" "log" "os" "reflect" + "strconv" + "strings" "sync" "testing" "time" @@ -41,72 +45,30 @@ import ( "go.opentelemetry.io/otel/trace" ) -var ( - mockLambdaContext = lambdacontext.LambdaContext{ - AwsRequestID: "123", - InvokedFunctionArn: "arn:partition:service:region:account-id:resource-type:resource-id", - Identity: lambdacontext.CognitoIdentity{ - CognitoIdentityID: "someId", - CognitoIdentityPoolID: "somePoolId", - }, - ClientContext: lambdacontext.ClientContext{}, - } - mockContext = xray.Propagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), - mapCarrier{ - "X-Amzn-Trace-Id": "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1", - }) -) - var errorLogger = log.New(log.Writer(), "OTel Lambda Test Error: ", 0) -// basic implementation of TextMapCarrier -// which wraps the default map type -type mapCarrier map[string]string - -// Compile time check our mapCarrier implements propagation.TextMapCarrier -var _ propagation.TextMapCarrier = mapCarrier{} - -// Get returns the value associated with the passed key. -func (mc mapCarrier) Get(key string) string { - return mc[key] -} - -// Set stores the key-value pair. -func (mc mapCarrier) Set(key string, value string) { - mc[key] = value -} - -// Keys lists the keys stored in this carrier. -func (mc mapCarrier) Keys() []string { - keys := make([]string, 0, len(mc)) - for k := range mc { - keys = append(keys, k) - } - return keys -} - -type mockIdGenerator struct { +type mockIDGenerator struct { sync.Mutex traceCount int spanCount int } -func (m *mockIdGenerator) NewIDs(_ context.Context) (trace.TraceID, trace.SpanID) { +func (m *mockIDGenerator) NewIDs(_ context.Context) (trace.TraceID, trace.SpanID) { m.Lock() defer m.Unlock() - m.traceCount += 1 - m.spanCount += 1 + m.traceCount++ + m.spanCount++ return [16]byte{byte(m.traceCount)}, [8]byte{byte(m.spanCount)} } -func (m *mockIdGenerator) NewSpanID(_ context.Context, _ trace.TraceID) trace.SpanID { +func (m *mockIDGenerator) NewSpanID(_ context.Context, _ trace.TraceID) trace.SpanID { m.Lock() defer m.Unlock() - m.spanCount += 1 + m.spanCount++ return [8]byte{byte(m.spanCount)} } -var _ sdktrace.IDGenerator = &mockIdGenerator{} +var _ sdktrace.IDGenerator = &mockIDGenerator{} type emptyHandler struct{} @@ -130,7 +92,7 @@ func initMockTracerProvider() (*sdktrace.TracerProvider, *tracetest.InMemoryExpo tp := sdktrace.NewTracerProvider( sdktrace.WithSyncer(exp), - sdktrace.WithIDGenerator(&mockIdGenerator{}), + sdktrace.WithIDGenerator(&mockIDGenerator{}), sdktrace.WithResource(res), ) @@ -144,37 +106,53 @@ func setEnvVars() { _ = os.Setenv("_X_AMZN_TRACE_ID", "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1") } -var expectedTraceID, _ = trace.TraceIDFromHex("5759e988bd862e3fe1be46a994272793") -var expectedSpanStub = tracetest.SpanStub{ - Name: "testFunction", - SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ - TraceID: expectedTraceID, - SpanID: trace.SpanID{1}, - TraceFlags: 1, - TraceState: trace.TraceState{}, - Remote: false, - }), - Parent: trace.SpanContextFromContext(mockContext), - SpanKind: trace.SpanKindServer, - StartTime: time.Time{}, - EndTime: time.Time{}, - Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), - attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), - attribute.String("cloud.account.id", "account-id")}, - Events: nil, - Links: nil, - Status: sdktrace.Status{}, - DroppedAttributes: 0, - DroppedEvents: 0, - DroppedLinks: 0, - ChildSpanCount: 0, - Resource: resource.NewWithAttributes(semconv.SchemaURL, - attribute.String("cloud.provider", "aws"), - attribute.String("cloud.region", "us-texas-1"), - attribute.String("faas.name", "testFunction"), - attribute.String("faas.version", "$LATEST")), - InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda", Version: contrib.SemVersion()}, -} +// Vars for Tracing and TracingWithFlusher Tests +var ( + mockLambdaContext = lambdacontext.LambdaContext{ + AwsRequestID: "123", + InvokedFunctionArn: "arn:partition:service:region:account-id:resource-type:resource-id", + Identity: lambdacontext.CognitoIdentity{ + CognitoIdentityID: "someId", + CognitoIdentityPoolID: "somePoolId", + }, + ClientContext: lambdacontext.ClientContext{}, + } + mockContext = xray.Propagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), + propagation.HeaderCarrier{ + "X-Amzn-Trace-Id": []string{"Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"}, + }) + expectedTraceID, _ = trace.TraceIDFromHex("5759e988bd862e3fe1be46a994272793") + expectedSpanStub = tracetest.SpanStub{ + Name: "testFunction", + SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: expectedTraceID, + SpanID: trace.SpanID{1}, + TraceFlags: 1, + TraceState: trace.TraceState{}, + Remote: false, + }), + Parent: trace.SpanContextFromContext(mockContext), + SpanKind: trace.SpanKindServer, + StartTime: time.Time{}, + EndTime: time.Time{}, + Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), + attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), + attribute.String("cloud.account.id", "account-id")}, + Events: nil, + Links: nil, + Status: sdktrace.Status{}, + DroppedAttributes: 0, + DroppedEvents: 0, + DroppedLinks: 0, + ChildSpanCount: 0, + Resource: resource.NewWithAttributes(semconv.SchemaURL, + attribute.String("cloud.provider", "aws"), + attribute.String("cloud.region", "us-texas-1"), + attribute.String("faas.name", "testFunction"), + attribute.String("faas.version", "$LATEST")), + InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda", Version: contrib.SemVersion()}, + } +) func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actual tracetest.SpanStub) { assert.Equal(t, expected.Name, actual.Name) @@ -220,10 +198,201 @@ func TestWrapHandlerTracing(t *testing.T) { // No flusher needed as SimpleSpanProcessor is synchronous wrapped := otellambda.WrapHandler(emptyHandler{}, otellambda.WithTracerProvider(tp)) - _, err := wrapped.Invoke(mockContext, nil) + _, err := wrapped.Invoke(mockContext, []byte{}) assert.NoError(t, err) assert.Len(t, memExporter.GetSpans(), 1) stub := memExporter.GetSpans()[0] assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) } + +type mockFlusher struct { + flushCount int +} + +func (mf *mockFlusher) ForceFlush(context.Context) error { + mf.flushCount++ + return nil +} + +var _ otellambda.Flusher = &mockFlusher{} + +func TestWrapHandlerFunctionTracingWithFlusher(t *testing.T) { + setEnvVars() + tp, memExporter := initMockTracerProvider() + + customerHandler := func() (string, error) { + return "hello world", nil + } + + flusher := mockFlusher{} + wrapped := otellambda.WrapHandlerFunction(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(&flusher)) + wrappedCallable := reflect.ValueOf(wrapped) + resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) + assert.Len(t, resp, 2) + assert.Equal(t, "hello world", resp[0].Interface()) + assert.Nil(t, resp[1].Interface()) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) + + assert.Equal(t, 1, flusher.flushCount) +} + +func TestWrapHandlerTracingWithFlusher(t *testing.T) { + setEnvVars() + tp, memExporter := initMockTracerProvider() + + flusher := mockFlusher{} + wrapped := otellambda.WrapHandler(emptyHandler{}, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(&flusher)) + _, err := wrapped.Invoke(mockContext, []byte{}) + assert.NoError(t, err) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, expectedSpanStub, stub) + + assert.Equal(t, 1, flusher.flushCount) +} + +const mockPropagatorKey = "Mockkey" + +type mockPropagator struct{} + +func (prop mockPropagator) Extract(ctx context.Context, carrier propagation.TextMapCarrier) context.Context { + // extract tracing information + if header := carrier.Get(mockPropagatorKey); header != "" { + scc := trace.SpanContextConfig{} + splitHeaderVal := strings.Split(header, ":") + var err error + scc.TraceID, err = trace.TraceIDFromHex(splitHeaderVal[0]) + if err != nil { + errorLogger.Println("Failed to create trace id from hex: ", err) + } + scc.SpanID, err = trace.SpanIDFromHex(splitHeaderVal[1]) + if err != nil { + errorLogger.Println("Failed to create span id from hex: ", err) + } + isTraced, err := strconv.Atoi(splitHeaderVal[1]) + if err != nil { + errorLogger.Println("Failed to convert trace flag to int: ", err) + } + scc.TraceFlags = scc.TraceFlags.WithSampled(isTraced != 0) + sc := trace.NewSpanContext(scc) + return trace.ContextWithRemoteSpanContext(ctx, sc) + } + return ctx +} + +func (prop mockPropagator) Inject(context.Context, propagation.TextMapCarrier) { + // not needed other than to satisfy interface +} + +func (prop mockPropagator) Fields() []string { + // not needed other than to satisfy interface + return []string{} +} + +type mockRequest struct { + Headers map[string]string +} + +// Vars for mockPropagator Tests +var ( + mockPropagatorTestsTraceIDHex = "12345678901234567890123456789012" + mockPropagatorTestsSpanIDHex = "1234567890123456" + mockPropagatorTestsSampled = "1" + mockPropagatorTestsHeader = mockPropagatorTestsTraceIDHex + ":" + mockPropagatorTestsSpanIDHex + ":" + mockPropagatorTestsSampled + mockPropagatorTestsEvent = mockRequest{Headers: map[string]string{mockPropagatorKey: mockPropagatorTestsHeader}} + + mockPropagatorTestsContext = mockPropagator{}.Extract(lambdacontext.NewContext(context.TODO(), &mockLambdaContext), + propagation.HeaderCarrier{mockPropagatorKey: []string{mockPropagatorTestsHeader}}) + + mockPropagatorTestsExpectedTraceID, _ = trace.TraceIDFromHex(mockPropagatorTestsTraceIDHex) + mockPropagatorTestsExpectedSpanStub = tracetest.SpanStub{ + Name: "testFunction", + SpanContext: trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: mockPropagatorTestsExpectedTraceID, + SpanID: trace.SpanID{1}, + TraceFlags: 1, + TraceState: trace.TraceState{}, + Remote: false, + }), + Parent: trace.SpanContextFromContext(mockPropagatorTestsContext), + SpanKind: trace.SpanKindServer, + StartTime: time.Time{}, + EndTime: time.Time{}, + Attributes: []attribute.KeyValue{attribute.String("faas.execution", "123"), + attribute.String("faas.id", "arn:partition:service:region:account-id:resource-type:resource-id"), + attribute.String("cloud.account.id", "account-id")}, + Events: nil, + Links: nil, + Status: sdktrace.Status{}, + DroppedAttributes: 0, + DroppedEvents: 0, + DroppedLinks: 0, + ChildSpanCount: 0, + Resource: resource.NewWithAttributes(semconv.SchemaURL, + attribute.String("cloud.provider", "aws"), + attribute.String("cloud.region", "us-texas-1"), + attribute.String("faas.name", "testFunction"), + attribute.String("faas.version", "$LATEST")), + InstrumentationLibrary: instrumentation.Library{Name: "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda", Version: contrib.SemVersion()}, + } +) + +func mockRequestToTextMapCarrierConverter(eventJSON []byte) propagation.TextMapCarrier { + var event mockRequest + err := json.Unmarshal(eventJSON, &event) + if err != nil { + fmt.Println("event type: ", reflect.TypeOf(event)) + panic("This TextMapCarrierConverter only supports events of type mockRequest") + } + return propagation.HeaderCarrier{mockPropagatorKey: []string{event.Headers[mockPropagatorKey]}} +} + +func TestWrapHandlerFunctionTracingWithMockPropagator(t *testing.T) { + + setEnvVars() + tp, memExporter := initMockTracerProvider() + + customerHandler := func(event mockRequest) (string, error) { + return "hello world", nil + } + + // No flusher needed as SimpleSpanProcessor is synchronous + wrapped := otellambda.WrapHandlerFunction(customerHandler, + otellambda.WithTracerProvider(tp), + otellambda.WithPropagator(mockPropagator{}), + otellambda.WithEventToTextMapCarrierConverter(mockRequestToTextMapCarrierConverter)) + + wrappedCallable := reflect.ValueOf(wrapped) + resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockPropagatorTestsContext), reflect.ValueOf(mockPropagatorTestsEvent)}) + assert.Len(t, resp, 2) + assert.Equal(t, "hello world", resp[0].Interface()) + assert.Nil(t, resp[1].Interface()) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, mockPropagatorTestsExpectedSpanStub, stub) +} + +func TestWrapHandlerTracingWithMockPropagator(t *testing.T) { + setEnvVars() + tp, memExporter := initMockTracerProvider() + + // No flusher needed as SimpleSpanProcessor is synchronous + wrapped := otellambda.WrapHandler(emptyHandler{}, + otellambda.WithTracerProvider(tp), + otellambda.WithPropagator(mockPropagator{}), + otellambda.WithEventToTextMapCarrierConverter(mockRequestToTextMapCarrierConverter)) + + payload, _ := json.Marshal(mockPropagatorTestsEvent) + _, err := wrapped.Invoke(mockPropagatorTestsContext, payload) + assert.NoError(t, err) + + assert.Len(t, memExporter.GetSpans(), 1) + stub := memExporter.GetSpans()[0] + assertStubEqualsIgnoreTime(t, mockPropagatorTestsExpectedSpanStub, stub) +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go index 261350a11b9..e847d494773 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go @@ -1,3 +1,17 @@ +// 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 otellambda import ( @@ -19,8 +33,7 @@ var _ lambda.Handler = wrappedHandler{} // Invoke adds OTel span surrounding customer Handler invocation func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) { - - ctx, span := tracingBegin(ctx) + ctx, span := tracingBegin(ctx, payload) defer tracingEnd(ctx, span) response, err := h.handler.Invoke(ctx, payload) @@ -34,8 +47,10 @@ func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, err // WrapHandler Provides a Handler which wraps customer Handler with OTel Tracing func WrapHandler(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { o := InstrumentationOptions{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + EventToTextMapCarrierConverter: noopEventToTextMapCarrierConverter, + Propagator: otel.GetTextMapPropagator(), } for _, opt := range options { opt(&o) @@ -45,4 +60,4 @@ func WrapHandler(handler lambda.Handler, options ...InstrumentationOption) lambd tracer = configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) return wrappedHandler{handler: handler} -} \ No newline at end of file +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index 0037c9a2f11..906ee309184 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -1,3 +1,17 @@ +// 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 otellambda import ( @@ -11,7 +25,6 @@ import ( "go.opentelemetry.io/otel/trace" ) - func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { return func(context.Context, interface{}) (interface{}, error) { return nil, e @@ -58,10 +71,10 @@ func validateReturns(handler reflect.Type) error { } // Wraps and calls customer lambda handler then unpacks response as necessary -func wrapperInternals(ctx context.Context, handlerFunc interface{}, event reflect.Value, takesContext bool) (interface{}, error) { +func wrapperInternals(ctx context.Context, handlerFunc interface{}, eventJSON []byte, event reflect.Value, takesContext bool) (interface{}, error) { wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) - argsWrapped := []reflect.Value{reflect.ValueOf(ctx), event, reflect.ValueOf(takesContext)} + argsWrapped := []reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(eventJSON), event, reflect.ValueOf(takesContext)} response := wrappedLambdaHandler.Call(argsWrapped)[0].Interface().([]reflect.Value) // convert return values into (interface{}, error) @@ -79,31 +92,13 @@ func wrapperInternals(ctx context.Context, handlerFunc interface{}, event reflec return val, err } -// converts the given payload to the correct event type -func payloadToEvent(eventType reflect.Type, payload interface{}) (reflect.Value, error) { - event := reflect.New(eventType) - - // lambda SDK normally unmarshalls to customer event type, however - // with the wrapper the SDK unmarshalls to map[string]interface{} - // due to our use of reflection. Therefore we must convert this map - // to customer's desired event, we do so by simply re-marshalling then - // unmarshalling to the desired event type - remarshalledPayload, err := json.Marshal(payload) - if err != nil { - return reflect.Value{}, err - } - - if err := json.Unmarshal(remarshalledPayload, event.Interface()); err != nil { - return reflect.Value{}, err - } - return event, nil -} - // WrapHandlerFunction Provides a lambda handler which wraps customer lambda handler with OTel Tracing func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOption) interface{} { o := InstrumentationOptions{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + EventToTextMapCarrierConverter: noopEventToTextMapCarrierConverter, + Propagator: otel.GetTextMapPropagator(), } for _, opt := range options { opt(&o) @@ -135,24 +130,38 @@ func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOpti return func(ctx context.Context) (interface{}, error) { var temp *interface{} event := reflect.ValueOf(temp) - return wrapperInternals(ctx, handlerFunc, event, takesContext) + return wrapperInternals(ctx, handlerFunc, []byte{}, event, takesContext) + } + } + + // customer either takes both context and payload or just payload + return func(ctx context.Context, payload interface{}) (interface{}, error) { + event := reflect.New(handlerType.In(handlerType.NumIn() - 1)) + + // lambda SDK normally unmarshalls to customer event type, however + // with the wrapper the SDK unmarshalls to map[string]interface{} + // due to our use of reflection. Therefore we must convert this map + // to customer's desired event, we do so by simply re-marshaling then + // unmarshalling to the desired event type. The remarshalledPayload + // will also be used by users using custom propagators + remarshalledPayload, err := json.Marshal(payload) + if err != nil { + return nil, err } - } else { // customer either takes both context and payload or just payload - return func(ctx context.Context, payload interface{}) (interface{}, error) { - event, err := payloadToEvent(handlerType.In(handlerType.NumIn()-1), payload) - if err != nil { - return nil, err - } - return wrapperInternals(ctx, handlerFunc, event.Elem(), takesContext) + + if err := json.Unmarshal(remarshalledPayload, event.Interface()); err != nil { + return nil, err } + + return wrapperInternals(ctx, handlerFunc, remarshalledPayload, event.Elem(), takesContext) } } // Adds OTel span surrounding customer handler call -func wrapper(handlerFunc interface{}) func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { - return func(ctx context.Context, event interface{}, takesContext bool) []reflect.Value { +func wrapper(handlerFunc interface{}) func(ctx context.Context, eventJSON []byte, event interface{}, takesContext bool) []reflect.Value { + return func(ctx context.Context, eventJSON []byte, event interface{}, takesContext bool) []reflect.Value { - ctx, span := tracingBegin(ctx) + ctx, span := tracingBegin(ctx, eventJSON) defer tracingEnd(ctx, span) handler := reflect.ValueOf(handlerFunc) @@ -186,4 +195,3 @@ func eventExists(event interface{}) bool { } return true } - From d3d2c181cfb248cb0e9a797a0e60dfe62aba9be1 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 05:37:23 -0700 Subject: [PATCH 28/43] Go format --- detectors/aws/lambda/detector_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detectors/aws/lambda/detector_test.go b/detectors/aws/lambda/detector_test.go index 968ad967bd3..f733f2f356e 100644 --- a/detectors/aws/lambda/detector_test.go +++ b/detectors/aws/lambda/detector_test.go @@ -55,4 +55,4 @@ func TestReturnsIfNoEnvVars(t *testing.T) { assert.Equal(t, errNotOnLambda, err) assert.Equal(t, 0, len(res.Attributes())) -} \ No newline at end of file +} From e572b7bba86f521062bb8354e39b19f1c466990b Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 05:52:49 -0700 Subject: [PATCH 29/43] Improve HTTP tracing usage --- .../aws/aws-lambda-go/otellambda/example/main.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index f1469330129..28d36df0b2e 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -58,17 +58,22 @@ func lambdaHandler(ctx context.Context) error { } // HTTP - orig := otelhttp.DefaultClient - otelhttp.DefaultClient = &http.Client{ + client := &http.Client{ Transport: otelhttp.NewTransport( http.DefaultTransport, otelhttp.WithTracerProvider(otel.GetTracerProvider()), ), } - defer func() { otelhttp.DefaultClient = orig }() - res, err := otelhttp.Get(ctx, "https://api.github.com/repos/open-telemetry/opentelemetry-go/releases/latest") + req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/repos/open-telemetry/opentelemetry-go/releases/latest", nil) if err != nil { - fmt.Printf("failed to make http request, %v\n", err) + fmt.Printf("failed to create http request, %v\n", err) + return err + } + + res, err := client.Do(req) + if err != nil { + fmt.Printf("failed to do http request, %v\n", err) + return err } defer func(Body io.ReadCloser) { From ac8b307f87b3197b27de8015210d4edcbf116c10 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 05:57:54 -0700 Subject: [PATCH 30/43] Bump dependencies for RC2 --- .../aws-lambda-go/otellambda/example/go.mod | 14 +++---- .../aws-lambda-go/otellambda/example/go.sum | 38 +++++++++++-------- .../aws/aws-lambda-go/otellambda/go.mod | 10 ++--- .../aws/aws-lambda-go/otellambda/go.sum | 10 ++--- .../aws/aws-lambda-go/otellambda/test/go.mod | 14 +++---- .../aws/aws-lambda-go/otellambda/test/go.sum | 12 ++++-- 6 files changed, 52 insertions(+), 46 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod index fa7e0bc680b..94287f406d3 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod @@ -11,12 +11,12 @@ require ( github.com/aws/aws-lambda-go v1.25.0 github.com/aws/aws-sdk-go-v2/config v1.5.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1 - go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.21.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0 - go.opentelemetry.io/otel v1.0.0-RC1 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 - go.opentelemetry.io/otel/sdk v1.0.0-RC1 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.22.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.22.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0 + go.opentelemetry.io/otel v1.0.0-RC2 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2 + go.opentelemetry.io/otel/sdk v1.0.0-RC2 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum index fc2f8b4bbf7..ad1aa9fbd74 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -52,26 +52,32 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/contrib v0.21.0 h1:RMJ6GlUVzLYp/zmItxTTdAmr1gnpO/HHMFmvjAhvJQM= -go.opentelemetry.io/contrib v0.21.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0 h1:7jzIZ2lh5T4t/9+UjeDPvIKmqUadZB4JUta1gs2OaUI= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.21.0/go.mod h1:O+blok0+ZMWjdDhkO+h8wOklvj5H58+yeLezJ+l6YeY= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0 h1:G1vNyNfKknFvrKVC8ga8EYIECy0s5D/QPW4QPRSMhwc= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.21.0/go.mod h1:JQAtechjxLEL81EjmbRwxBq/XEzGaHcsPuDHAx54hg4= -go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= +go.opentelemetry.io/contrib v0.22.0 h1:0F7gDEjgb1WGn4ODIjaCAg75hmqF+UN0LiVgwxsCodc= +go.opentelemetry.io/contrib v0.22.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0 h1:yvHsET05+W6mGbiBmpzeSNfguFl7wdGc7wnZzL6oXZg= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0/go.mod h1:SYNRbn31XulM3soVaBCla9PC47il0lxsiIVPGVDdJLE= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0 h1:WHjZguqT+3UjTgFum33hWZYybDVnx8u9q5/kQDfaGTs= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0/go.mod h1:o3MuU25bYroYnc2TOKe8mTk8f9X1oPFO6C5RCoPKtSU= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1 h1:SEfJImgKQ5TP2aTJwN08qhS8oFlYWr/neECGsyuxKWg= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC1/go.mod h1:TAM/UYjVd1UdaifWkof3qj9cCW9oINemHfj0K6yodSo= -go.opentelemetry.io/otel/internal/metric v0.21.0 h1:gZlIBo5O51hZOOZz8vEcuRx/l5dnADadKfpT70AELoo= -go.opentelemetry.io/otel/internal/metric v0.21.0/go.mod h1:iOfAaY2YycsXfYD4kaRSbLx2LKmfpKObWBEv9QK5zFo= -go.opentelemetry.io/otel/metric v0.21.0 h1:ZtcJlHqVE4l8Su0WOLOd9fEPheJuYEiQ0wr9wv2p25I= -go.opentelemetry.io/otel/metric v0.21.0/go.mod h1:JWCt1bjivC4iCrz/aCrM1GSw+ZcvY44KCbaeeRhzHnc= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= +go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2 h1:crksoFyTPDDywRJDUW36OZma+C3HhcYwQLPUZZMXFO0= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2/go.mod h1:6kVxj1C/f3irP/IeeZNbcEwbg3rwnM6a7bCrcGbIJeI= +go.opentelemetry.io/otel/internal/metric v0.22.0 h1:Q9bS02XRykSRIbggaU4hVF9oWOP9PyILu26zJWoKmk0= +go.opentelemetry.io/otel/internal/metric v0.22.0/go.mod h1:7qVuMihW/ktMonEfOvBXuh6tfMvvEyoIDgeJNRloYbQ= +go.opentelemetry.io/otel/metric v0.22.0 h1:/qv10BzznqEifrXBwsTT370OCN1PRgt+mnjzMwxJKrQ= +go.opentelemetry.io/otel/metric v0.22.0/go.mod h1:KcsUkBiYGW003DJ+ugd2aqIRIfjabD9jeOUXqsAtrq0= go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= +go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk= +go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A= go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= -go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= +go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index 7c23a9dcf67..ba1e87a828a 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -2,14 +2,12 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/ go 1.16 -replace ( - go.opentelemetry.io/contrib => ../../../../.. -) +replace go.opentelemetry.io/contrib => ../../../../.. require ( github.com/aws/aws-lambda-go v1.24.0 github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/contrib v0.21.0 - go.opentelemetry.io/otel v1.0.0-RC1 - go.opentelemetry.io/otel/trace v1.0.0-RC1 + go.opentelemetry.io/contrib v0.22.0 + go.opentelemetry.io/otel v1.0.0-RC2 + go.opentelemetry.io/otel/trace v1.0.0-RC2 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index be918d5fc3e..a7c7b16bf04 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -17,12 +17,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= -go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= -go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= +go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= +go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= 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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod index df8306b89f3..16cfc7d4e23 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod @@ -12,11 +12,11 @@ replace ( require ( github.com/aws/aws-lambda-go v1.25.0 github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/contrib v0.21.0 - go.opentelemetry.io/contrib/detectors/aws/lambda v0.21.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.21.0 - go.opentelemetry.io/contrib/propagators/aws v0.21.0 - go.opentelemetry.io/otel v1.0.0-RC1 - go.opentelemetry.io/otel/sdk v1.0.0-RC1 - go.opentelemetry.io/otel/trace v1.0.0-RC1 + go.opentelemetry.io/contrib v0.22.0 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.22.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.22.0 + go.opentelemetry.io/contrib/propagators/aws v0.22.0 + go.opentelemetry.io/otel v1.0.0-RC2 + go.opentelemetry.io/otel/sdk v1.0.0-RC2 + go.opentelemetry.io/otel/trace v1.0.0-RC2 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index 22ca04ecdbf..6959c3ec852 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -18,14 +18,18 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= +go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= +go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= -go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= +go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= +go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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/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= From 24c91086e7cd745e67584a51560cd46866f839d6 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 06:00:33 -0700 Subject: [PATCH 31/43] Fix typo --- .../github.com/aws/aws-lambda-go/otellambda/lambda.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 75990a99652..bf5d4779027 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -42,7 +42,7 @@ type noopFlusher struct{} func (*noopFlusher) ForceFlush(context.Context) error { return nil } -// Compile time check our noopFlusher implements FLusher +// Compile time check our noopFlusher implements Flusher var _ Flusher = &noopFlusher{} type EventToTextMapCarrierConverter func([]byte) propagation.TextMapCarrier From 7b4a00e144a54e3a505cc57e78c4123751ea30b6 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 08:16:02 -0700 Subject: [PATCH 32/43] Refactor configuration design --- .../aws/aws-lambda-go/otellambda/config.go | 116 ++++++++++++++++++ .../aws/aws-lambda-go/otellambda/lambda.go | 94 ++------------ .../aws-lambda-go/otellambda/wrapHandler.go | 26 ++-- .../otellambda/wrapLambdaHandler.go | 36 ++++-- 4 files changed, 167 insertions(+), 105 deletions(-) create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go new file mode 100644 index 00000000000..1ad34e8d046 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go @@ -0,0 +1,116 @@ +// 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 otellambda + +import ( + "context" + + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" +) + +// A Flusher dictates how the instrumentation will attempt to flush +// unexported spans at the end of each Lambda innovation. This is +// very important in asynchronous settings because the Lambda runtime +// may enter a 'frozen' state any time after the invocation completes. +// Should this freeze happen and spans are left unexported, there can be a +// long delay before those spans are exported. +type Flusher interface { + ForceFlush(context.Context) error +} + +type noopFlusher struct{} + +func (*noopFlusher) ForceFlush(context.Context) error { return nil } + +// Compile time check our noopFlusher implements Flusher +var _ Flusher = &noopFlusher{} + +// An EventToTextMapCarrierConverter defines how the instrumentation should +// prepare a TextMapCarrier for the configured propagator to read from. This +// extra step is necessary because Lambda does not have HTTP headers to read +// from and instead stores the headers it was invoked with (including TraceID, etc.) +// as part of the invocation event. If using the AWS XRay tracing then the +// trace information is instead stored in the Lambda environment. +type EventToTextMapCarrierConverter func(eventJSON []byte) propagation.TextMapCarrier + +func emptyEventToTextMapCarrierConverter([]byte) propagation.TextMapCarrier { + return propagation.HeaderCarrier{} +} + +// Compile time check our emptyEventToTextMapCarrierConverter implements EventToTextMapCarrierConverter +var _ EventToTextMapCarrierConverter = emptyEventToTextMapCarrierConverter + +type Option interface { + apply(*config) +} + +type optionFunc func(*config) + +func (o optionFunc) apply(c *config) { + o(c) +} + +type config struct { + // TracerProvider is the TracerProvider which will be used + // to create instrumentation spans + // The default value of TracerProvider the global otel TracerProvider + // returned by otel.GetTracerProvider() + TracerProvider trace.TracerProvider + + // Flusher is the mechanism used to flush any unexported spans + // each Lambda Invocation to avoid spans being unexported for long + // when periods of time if Lambda freezes the execution environment + // The default value of Flusher is a noop Flusher, using this + // default can result in long data delays in asynchronous settings + Flusher Flusher + + // EventToTextMapCarrierConverter is the mechanism used to retrieve the TraceID + // from the event or environment and generate a TextMapCarrier which + // can then be used by a Propagator to extract the TraceID into our context + // The default value of eventToTextMapCarrierConverter returns an empty + // HeaderCarrier, using this default will cause all spans to be not be traced + EventToTextMapCarrierConverter EventToTextMapCarrierConverter + + // Propagator is the Propagator which will be used + // to extract Trace info into the context + // The default value of Propagator the global otel Propagator + // returned by otel.GetTextMapPropagator() + Propagator propagation.TextMapPropagator +} + +func WithTracerProvider(tracerProvider trace.TracerProvider) Option { + return optionFunc(func(c *config) { + c.TracerProvider = tracerProvider + }) +} + +func WithFlusher(flusher Flusher) Option { + return optionFunc(func(c *config) { + c.Flusher = flusher + }) +} + +func WithEventToTextMapCarrierConverter(eventToTextMapCarrierConverter EventToTextMapCarrierConverter) Option { + return optionFunc(func(c *config) { + c.EventToTextMapCarrierConverter = eventToTextMapCarrierConverter + }) +} + +func WithPropagator(propagator propagation.TextMapPropagator) Option { + return optionFunc(func(c *config) { + c.Propagator = propagator + }) +} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index bf5d4779027..7aac473de1c 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -23,7 +23,6 @@ import ( "github.com/aws/aws-lambda-go/lambdacontext" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/propagation" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "go.opentelemetry.io/otel/trace" ) @@ -34,62 +33,17 @@ const ( var errorLogger = log.New(log.Writer(), "OTel Lambda Error: ", 0) -type Flusher interface { - ForceFlush(context.Context) error +type instrumentor struct { + configuration config + resourceAttributesToAddAsSpanAttributes []attribute.KeyValue + tracer trace.Tracer } -type noopFlusher struct{} - -func (*noopFlusher) ForceFlush(context.Context) error { return nil } - -// Compile time check our noopFlusher implements Flusher -var _ Flusher = &noopFlusher{} - -type EventToTextMapCarrierConverter func([]byte) propagation.TextMapCarrier - -func noopEventToTextMapCarrierConverter([]byte) propagation.TextMapCarrier { - return propagation.HeaderCarrier{} -} - -type InstrumentationOption func(o *InstrumentationOptions) - -type InstrumentationOptions struct { - // TracerProvider is the TracerProvider which will be used - // to create instrumentation spans - // The default value of TracerProvider the global otel TracerProvider - // returned by otel.GetTracerProvider() - TracerProvider trace.TracerProvider - - // Flusher is the mechanism used to flush any unexported spans - // each Lambda Invocation to avoid spans being unexported for long - // when periods of time if Lambda freezes the execution environment - // The default value of Flusher is a noop Flusher, using this - // default can result in long data delays in asynchronous settings - Flusher Flusher - - // eventToTextMapCarrierConverter is the mechanism used to retrieve the TraceID - // from the event or environment and generate a TextMapCarrier which - // can then be used by a Propagator to extract the TraceID into our context - // The default value of eventToTextMapCarrierConverter returns an empty - // HeaderCarrier, using this default will cause all spans to be not be traced - EventToTextMapCarrierConverter EventToTextMapCarrierConverter - - // Propagator is the Propagator which will be used - // to extrract Trace info into the context - // The default value of Propagator the global otel Propagator - // returned by otel.GetTextMapPropagator() - Propagator propagation.TextMapPropagator -} - -var configuration InstrumentationOptions -var resourceAttributesToAddAsSpanAttributes []attribute.KeyValue -var tracer trace.Tracer - // Logic to start OTel Tracing -func tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace.Span) { +func (i *instrumentor) tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace.Span) { // Add trace id to context - mc := configuration.EventToTextMapCarrierConverter(eventJSON) - ctx = configuration.Propagator.Extract(ctx, mc) + mc := i.configuration.EventToTextMapCarrierConverter(eventJSON) + ctx = i.configuration.Propagator.Extract(ctx, mc) var span trace.Span spanName := os.Getenv("AWS_LAMBDA_FUNCTION_NAME") @@ -107,7 +61,7 @@ func tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace // resource detectors are created before a lambda // invocation and therefore lack lambdacontext. // Create these attrs upon first invocation - if resourceAttributesToAddAsSpanAttributes == nil { + if i.resourceAttributesToAddAsSpanAttributes == nil { ctxFunctionArn := lc.InvokedFunctionArn attributes = append(attributes, semconv.FaaSIDKey.String(ctxFunctionArn)) arnParts := strings.Split(ctxFunctionArn, ":") @@ -115,45 +69,21 @@ func tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace attributes = append(attributes, semconv.CloudAccountIDKey.String(arnParts[4])) } } - attributes = append(attributes, resourceAttributesToAddAsSpanAttributes...) + attributes = append(attributes, i.resourceAttributesToAddAsSpanAttributes...) } - ctx, span = tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) + ctx, span = i.tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) return ctx, span } // Logic to wrap up OTel Tracing -func tracingEnd(ctx context.Context, span trace.Span) { +func (i *instrumentor) tracingEnd(ctx context.Context, span trace.Span) { span.End() // force flush any tracing data since lambda may freeze - err := configuration.Flusher.ForceFlush(ctx) + err := i.configuration.Flusher.ForceFlush(ctx) if err != nil { errorLogger.Println("failed to force a flush, lambda may freeze before instrumentation exported: ", err) } } - -func WithTracerProvider(tracerProvider trace.TracerProvider) InstrumentationOption { - return func(o *InstrumentationOptions) { - o.TracerProvider = tracerProvider - } -} - -func WithFlusher(flusher Flusher) InstrumentationOption { - return func(o *InstrumentationOptions) { - o.Flusher = flusher - } -} - -func WithEventToTextMapCarrierConverter(eventToTextMapCarrierConverter EventToTextMapCarrierConverter) InstrumentationOption { - return func(o *InstrumentationOptions) { - o.EventToTextMapCarrierConverter = eventToTextMapCarrierConverter - } -} - -func WithPropagator(propagator propagation.TextMapPropagator) InstrumentationOption { - return func(o *InstrumentationOptions) { - o.Propagator = propagator - } -} diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go index e847d494773..438269b17dd 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go @@ -24,8 +24,12 @@ import ( "go.opentelemetry.io/otel/trace" ) +// wrappedHandler is a struct which holds an instrumentor +// as well as the user's original lambda.Handler and is +// able to instrument invocations of the user's lambda.Handler type wrappedHandler struct { - handler lambda.Handler + instrumentor instrumentor + handler lambda.Handler } // Compile time check our Handler implements lambda.Handler @@ -33,8 +37,8 @@ var _ lambda.Handler = wrappedHandler{} // Invoke adds OTel span surrounding customer Handler invocation func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, error) { - ctx, span := tracingBegin(ctx, payload) - defer tracingEnd(ctx, span) + ctx, span := h.instrumentor.tracingBegin(ctx, payload) + defer h.instrumentor.tracingEnd(ctx, span) response, err := h.handler.Invoke(ctx, payload) if err != nil { @@ -45,19 +49,21 @@ func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, err } // WrapHandler Provides a Handler which wraps customer Handler with OTel Tracing -func WrapHandler(handler lambda.Handler, options ...InstrumentationOption) lambda.Handler { - o := InstrumentationOptions{ +func WrapHandler(handler lambda.Handler, options ...Option) lambda.Handler { + cfg := config{ TracerProvider: otel.GetTracerProvider(), Flusher: &noopFlusher{}, - EventToTextMapCarrierConverter: noopEventToTextMapCarrierConverter, + EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, Propagator: otel.GetTextMapPropagator(), } for _, opt := range options { - opt(&o) + opt.apply(&cfg) } - configuration = o + + i := instrumentor{} + i.configuration = cfg // Get a named tracer with package path as its name. - tracer = configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) + i.tracer = i.configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) - return wrappedHandler{handler: handler} + return wrappedHandler{instrumentor: i, handler: handler} } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index 906ee309184..f2b06e2a7ef 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -25,6 +25,12 @@ import ( "go.opentelemetry.io/otel/trace" ) +// wrappedHandlerFunction is a struct which only holds an instrumentor and is +// able to instrument invocations of the user's lambda handler function +type wrappedHandlerFunction struct { + instrumentor instrumentor +} + func errorHandler(e error) func(context.Context, interface{}) (interface{}, error) { return func(context.Context, interface{}) (interface{}, error) { return nil, e @@ -71,8 +77,8 @@ func validateReturns(handler reflect.Type) error { } // Wraps and calls customer lambda handler then unpacks response as necessary -func wrapperInternals(ctx context.Context, handlerFunc interface{}, eventJSON []byte, event reflect.Value, takesContext bool) (interface{}, error) { - wrappedLambdaHandler := reflect.ValueOf(wrapper(handlerFunc)) +func (whf *wrappedHandlerFunction) wrapperInternals(ctx context.Context, handlerFunc interface{}, eventJSON []byte, event reflect.Value, takesContext bool) (interface{}, error) { + wrappedLambdaHandler := reflect.ValueOf(whf.wrapper(handlerFunc)) argsWrapped := []reflect.Value{reflect.ValueOf(ctx), reflect.ValueOf(eventJSON), event, reflect.ValueOf(takesContext)} response := wrappedLambdaHandler.Call(argsWrapped)[0].Interface().([]reflect.Value) @@ -93,19 +99,23 @@ func wrapperInternals(ctx context.Context, handlerFunc interface{}, eventJSON [] } // WrapHandlerFunction Provides a lambda handler which wraps customer lambda handler with OTel Tracing -func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOption) interface{} { - o := InstrumentationOptions{ +func WrapHandlerFunction(handlerFunc interface{}, options ...Option) interface{} { + cfg := config{ TracerProvider: otel.GetTracerProvider(), Flusher: &noopFlusher{}, - EventToTextMapCarrierConverter: noopEventToTextMapCarrierConverter, + EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, Propagator: otel.GetTextMapPropagator(), } for _, opt := range options { - opt(&o) + opt.apply(&cfg) } - configuration = o + + i := instrumentor{} + i.configuration = cfg // Get a named tracer with package path as its name. - tracer = configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) + i.tracer = i.configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) + + whf := wrappedHandlerFunction{instrumentor: i} if handlerFunc == nil { return errorHandler(fmt.Errorf("handler is nil")) @@ -130,7 +140,7 @@ func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOpti return func(ctx context.Context) (interface{}, error) { var temp *interface{} event := reflect.ValueOf(temp) - return wrapperInternals(ctx, handlerFunc, []byte{}, event, takesContext) + return whf.wrapperInternals(ctx, handlerFunc, []byte{}, event, takesContext) } } @@ -153,16 +163,16 @@ func WrapHandlerFunction(handlerFunc interface{}, options ...InstrumentationOpti return nil, err } - return wrapperInternals(ctx, handlerFunc, remarshalledPayload, event.Elem(), takesContext) + return whf.wrapperInternals(ctx, handlerFunc, remarshalledPayload, event.Elem(), takesContext) } } // Adds OTel span surrounding customer handler call -func wrapper(handlerFunc interface{}) func(ctx context.Context, eventJSON []byte, event interface{}, takesContext bool) []reflect.Value { +func (whf *wrappedHandlerFunction) wrapper(handlerFunc interface{}) func(ctx context.Context, eventJSON []byte, event interface{}, takesContext bool) []reflect.Value { return func(ctx context.Context, eventJSON []byte, event interface{}, takesContext bool) []reflect.Value { - ctx, span := tracingBegin(ctx, eventJSON) - defer tracingEnd(ctx, span) + ctx, span := whf.instrumentor.tracingBegin(ctx, eventJSON) + defer whf.instrumentor.tracingEnd(ctx, span) handler := reflect.ValueOf(handlerFunc) var args []reflect.Value From 2c391fc82d9a1e30b0d44234a412facde031ce05 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:14:02 -0700 Subject: [PATCH 33/43] Bump dependencies to RC2 --- detectors/aws/lambda/go.mod | 4 ++-- detectors/aws/lambda/go.sum | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/detectors/aws/lambda/go.mod b/detectors/aws/lambda/go.mod index a1ba019067c..1eb21c35e3f 100644 --- a/detectors/aws/lambda/go.mod +++ b/detectors/aws/lambda/go.mod @@ -5,7 +5,7 @@ go 1.16 require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/otel v1.0.0-RC1 - go.opentelemetry.io/otel/sdk v1.0.0-RC1 + go.opentelemetry.io/otel v1.0.0-RC2 + go.opentelemetry.io/otel/sdk v1.0.0-RC2 gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect ) diff --git a/detectors/aws/lambda/go.sum b/detectors/aws/lambda/go.sum index 1d2f0c1f7c1..a3763f620a6 100644 --- a/detectors/aws/lambda/go.sum +++ b/detectors/aws/lambda/go.sum @@ -8,14 +8,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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.0-RC1 h1:4CeoX93DNTWt8awGK9JmNXzF9j7TyOu9upscEdtcdXc= -go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1 h1:G685iP3XiskCwk/z0eIabL55XUl2gk0cljhGk9sB0Yk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/sdk v1.0.0-RC1 h1:Sy2VLOOg24bipyC29PhuMXYNJrLsxkie8hyI7kUlG9Q= -go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= -go.opentelemetry.io/otel/trace v1.0.0-RC1 h1:jrjqKJZEibFrDz+umEASeU3LvdVyWKlnTh7XEfwrT58= -go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= +go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= +go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= +go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= +go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= +go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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/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= From b64863ebdf80d44e6d8bbf9cc3981fbac1d1f7b6 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 11:16:51 -0700 Subject: [PATCH 34/43] Add package READMEs --- detectors/aws/lambda/README.md | 67 ++++++++++ .../aws/aws-lambda-go/otellambda/README.md | 117 ++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 detectors/aws/lambda/README.md create mode 100644 instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md diff --git a/detectors/aws/lambda/README.md b/detectors/aws/lambda/README.md new file mode 100644 index 00000000000..0f8f1bbe24e --- /dev/null +++ b/detectors/aws/lambda/README.md @@ -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() +} +``` + +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. + +## Useful links + +- For more on FaaS attribute conventions, visit +- For more information on OpenTelemetry, visit: +- For more about 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 diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md new file mode 100644 index 00000000000..28c5a0eea42 --- /dev/null +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md @@ -0,0 +1,117 @@ +# OpenTelemetry AWS Lambda Instrumentation for Golang + +[![Go Reference][goref-image]][goref-url] +[![Apache License][license-image]][license-url] + +This module provides instrumentation for [`AWS Lambda`](https://docs.aws.amazon.com/lambda/latest/dg/golang-handler.html). + +## Installation + +```bash +go get -u go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda +``` + +## example +See [./example](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/instrumentation/github.com/aws/aws-lambda-go/otellambda/example) + +## Usage + +Create a sample Lambda Go application such as below. + +```go +package main + +import ( + "context" + "fmt" + "github.com/aws/aws-lambda-go/lambda" +) + +type MyEvent struct { + Name string `json:"name"` +} + +func HandleRequest(ctx context.Context, name MyEvent) (string, error) { + return fmt.Sprintf("Hello %s!", name.Name ), nil +} + +func main() { + lambda.Start(HandleRequest) +} +``` + +Now use the provided wrapper to instrument your basic Lambda function: +```go +// Add import +import "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" + +// wrap lambda handler function +func main() { + lambda.Start(otellambda.WrapHandlerFunction(HandleRequest)) +} +``` + +## AWS Lambda Instrumentation Options + +| Options | Input Type | Description | Default | +| --- | --- | --- | --- | +| `WithTracerProvider` | `trace.TracerProvider` | Provide a custom `TracerProvider` for creating spans. Consider using the [AWS Lambda Resource Detector][lambda-detector-url] with your tracer provider to improve tracing information. | `otel.GetTracerProvider()` +| `WithFlusher` | `otellambda.Flusher` | This instrumentation will call the `ForceFlush` method of its `Flusher` at the end of each invocation. Should you be using asynchronous logic (such as `sddktrace's BatchSpanProcessor`) it is very import for spans to be `ForceFlush`'ed before [Lambda freezes](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) to avoid data delays. | `Flusher` with noop `ForceFlush` +| `WithEventToTextMapCarrierConverter` | custom function `func xxx(eventJSON []byte) propagation.TextMapCarrier{}` | Function for providing custom logic to support retrieving trace header from different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway) and returning them in a `propagation.TextMapCarrier` which a Propagator can use to extract the trace header into the context. | Function which returns an empty `TextMapCarrier` - new spans will be part of a new Trace and have no parent past Lambda instrumentation span +| `WithPropagator` | `propagation.Propagator` | The `Propagator` the instrumentation will use to extract trace information into the context. | `otel.GetTextMapPropagator()` | + +### Usage With Options Example + +```go +var someHeaderKey = "Key" // used by propagator and converter to identify trace header + +type mockHTTPRequest struct { + Headers map[string][]string + Body string +} + +func mockConverter(eventJSON []byte) propagation.TextMapCarrier{ + var request mockHTTPRequest + _ = json.unmarshal(eventJSON, &request) + return propogation.HeaderCarrier{someHeaderKey: []string{request.Headers[someHeaderKey]}} +} + +type mockPropagator struct{} +// Extract - read from `someHeaderKey` +// Inject +// Fields + +func HandleRequest(ctx context.Context, request mockHTTPRequest) error { + return fmt.Sprintf("Hello %s!", request.Body ), nil +} + +func main() { + exp, _ := stdouttrace.New() + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exp)) + + lambda.Start(otellambda.WrapHandlerFunction(HandleRequest, + otellambda.WithTracerProvider(tp), + otellambda.WithFlusher(tp), + otellambda.WithEventToTextMapCarrierConverter(mockConverter), + otellambda.WithPropagator(mockPropagator{}))) +} +``` + +## Useful links + +- For more information on OpenTelemetry, visit: +- For more about 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/instrumentation/github.com/aws/aws-lambda-go/otellambda.svg +[goref-url]: https://pkg.go.dev/go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda +[discussions-url]: https://github.com/open-telemetry/opentelemetry-go/discussions +[lambda-detector-url]: https://github.com/open-telemetry/opentelemetry-go-contrib/blob/main/detectors/aws/lambda From e463802e2ac18321556affda5b5573d853e32906 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 13:15:18 -0700 Subject: [PATCH 35/43] Downgrade go version to 1.15 for CI --- detectors/aws/lambda/go.mod | 2 +- detectors/aws/lambda/go.sum | 1 + .../github.com/aws/aws-lambda-go/otellambda/example/go.mod | 2 +- .../github.com/aws/aws-lambda-go/otellambda/example/go.sum | 2 +- instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod | 2 +- instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum | 1 + .../github.com/aws/aws-lambda-go/otellambda/test/go.mod | 2 +- .../github.com/aws/aws-lambda-go/otellambda/test/go.sum | 1 + 8 files changed, 8 insertions(+), 5 deletions(-) diff --git a/detectors/aws/lambda/go.mod b/detectors/aws/lambda/go.mod index 1eb21c35e3f..1e19a3e4f73 100644 --- a/detectors/aws/lambda/go.mod +++ b/detectors/aws/lambda/go.mod @@ -1,6 +1,6 @@ module go.opentelemetry.io/contrib/detectors/aws/lambda -go 1.16 +go 1.15 require ( github.com/davecgh/go-spew v1.1.1 // indirect diff --git a/detectors/aws/lambda/go.sum b/detectors/aws/lambda/go.sum index a3763f620a6..e55f7ec727d 100644 --- a/detectors/aws/lambda/go.sum +++ b/detectors/aws/lambda/go.sum @@ -16,6 +16,7 @@ go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1 go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= 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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod index 94287f406d3..8d9175db39b 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod @@ -1,6 +1,6 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-g/otellambda/example -go 1.16 +go 1.15 replace ( go.opentelemetry.io/contrib/detectors/aws/lambda => ../../../../../../detectors/aws/lambda diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum index ad1aa9fbd74..e00570576ed 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -70,7 +70,6 @@ go.opentelemetry.io/otel/metric v0.22.0/go.mod h1:KcsUkBiYGW003DJ+ugd2aqIRIfjabD go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk= go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A= -go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= @@ -81,6 +80,7 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index ba1e87a828a..d5760f17652 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -1,6 +1,6 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda -go 1.16 +go 1.15 replace go.opentelemetry.io/contrib => ../../../../.. diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index a7c7b16bf04..9418aba069b 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -21,6 +21,7 @@ go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oK go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod index 16cfc7d4e23..839b56a8296 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod @@ -1,6 +1,6 @@ module go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda/test -go 1.16 +go 1.15 replace ( go.opentelemetry.io/contrib => ../../../../../.. diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index 6959c3ec852..6b8e4671501 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -30,6 +30,7 @@ go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1 go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= 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= From 804939b843dc9b335cfb03305d60db7009e085ae Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Wed, 28 Jul 2021 14:41:52 -0700 Subject: [PATCH 36/43] Minor refactoring --- .../aws/aws-lambda-go/otellambda/README.md | 2 +- .../aws/aws-lambda-go/otellambda/lambda.go | 28 +++++++++++++++---- .../aws-lambda-go/otellambda/wrapHandler.go | 21 +------------- .../otellambda/wrapLambdaHandler.go | 21 +------------- 4 files changed, 26 insertions(+), 46 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md index 28c5a0eea42..41f621d6485 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md @@ -57,7 +57,7 @@ func main() { | --- | --- | --- | --- | | `WithTracerProvider` | `trace.TracerProvider` | Provide a custom `TracerProvider` for creating spans. Consider using the [AWS Lambda Resource Detector][lambda-detector-url] with your tracer provider to improve tracing information. | `otel.GetTracerProvider()` | `WithFlusher` | `otellambda.Flusher` | This instrumentation will call the `ForceFlush` method of its `Flusher` at the end of each invocation. Should you be using asynchronous logic (such as `sddktrace's BatchSpanProcessor`) it is very import for spans to be `ForceFlush`'ed before [Lambda freezes](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) to avoid data delays. | `Flusher` with noop `ForceFlush` -| `WithEventToTextMapCarrierConverter` | custom function `func xxx(eventJSON []byte) propagation.TextMapCarrier{}` | Function for providing custom logic to support retrieving trace header from different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway) and returning them in a `propagation.TextMapCarrier` which a Propagator can use to extract the trace header into the context. | Function which returns an empty `TextMapCarrier` - new spans will be part of a new Trace and have no parent past Lambda instrumentation span +| `WithEventToTextMapCarrierConverter` | `func(eventJSON []byte) propagation.TextMapCarrier{}` | Function for providing custom logic to support retrieving trace header from different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway) and returning them in a `propagation.TextMapCarrier` which a Propagator can use to extract the trace header into the context. | Function which returns an empty `TextMapCarrier` - new spans will be part of a new Trace and have no parent past Lambda instrumentation span | `WithPropagator` | `propagation.Propagator` | The `Propagator` the instrumentation will use to extract trace information into the context. | `otel.GetTextMapPropagator()` | ### Usage With Options Example diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 7aac473de1c..23ffed445cd 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -22,6 +22,8 @@ import ( "github.com/aws/aws-lambda-go/lambdacontext" + "go.opentelemetry.io/contrib" + "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" semconv "go.opentelemetry.io/otel/semconv/v1.4.0" "go.opentelemetry.io/otel/trace" @@ -34,9 +36,25 @@ const ( var errorLogger = log.New(log.Writer(), "OTel Lambda Error: ", 0) type instrumentor struct { - configuration config - resourceAttributesToAddAsSpanAttributes []attribute.KeyValue - tracer trace.Tracer + configuration config + resAttrs []attribute.KeyValue + tracer trace.Tracer +} + +func newInstrumentor(opts ...Option) instrumentor { + cfg := config{ + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, + Propagator: otel.GetTextMapPropagator(), + } + for _, opt := range opts { + opt.apply(&cfg) + } + + return instrumentor{configuration: cfg, + tracer: cfg.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())), + resAttrs: []attribute.KeyValue{}} } // Logic to start OTel Tracing @@ -61,7 +79,7 @@ func (i *instrumentor) tracingBegin(ctx context.Context, eventJSON []byte) (cont // resource detectors are created before a lambda // invocation and therefore lack lambdacontext. // Create these attrs upon first invocation - if i.resourceAttributesToAddAsSpanAttributes == nil { + if len(i.resAttrs) == 0 { ctxFunctionArn := lc.InvokedFunctionArn attributes = append(attributes, semconv.FaaSIDKey.String(ctxFunctionArn)) arnParts := strings.Split(ctxFunctionArn, ":") @@ -69,7 +87,7 @@ func (i *instrumentor) tracingBegin(ctx context.Context, eventJSON []byte) (cont attributes = append(attributes, semconv.CloudAccountIDKey.String(arnParts[4])) } } - attributes = append(attributes, i.resourceAttributesToAddAsSpanAttributes...) + attributes = append(attributes, i.resAttrs...) } ctx, span = i.tracer.Start(ctx, spanName, trace.WithSpanKind(trace.SpanKindServer), trace.WithAttributes(attributes...)) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go index 438269b17dd..b0a26d5a8dc 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapHandler.go @@ -18,10 +18,6 @@ import ( "context" "github.com/aws/aws-lambda-go/lambda" - - "go.opentelemetry.io/contrib" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/trace" ) // wrappedHandler is a struct which holds an instrumentor @@ -50,20 +46,5 @@ func (h wrappedHandler) Invoke(ctx context.Context, payload []byte) ([]byte, err // WrapHandler Provides a Handler which wraps customer Handler with OTel Tracing func WrapHandler(handler lambda.Handler, options ...Option) lambda.Handler { - cfg := config{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, - EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, - Propagator: otel.GetTextMapPropagator(), - } - for _, opt := range options { - opt.apply(&cfg) - } - - i := instrumentor{} - i.configuration = cfg - // Get a named tracer with package path as its name. - i.tracer = i.configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) - - return wrappedHandler{instrumentor: i, handler: handler} + return wrappedHandler{instrumentor: newInstrumentor(options...), handler: handler} } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index f2b06e2a7ef..dd85ea8de0e 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -19,10 +19,6 @@ import ( "encoding/json" "fmt" "reflect" - - "go.opentelemetry.io/contrib" - "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/trace" ) // wrappedHandlerFunction is a struct which only holds an instrumentor and is @@ -100,22 +96,7 @@ func (whf *wrappedHandlerFunction) wrapperInternals(ctx context.Context, handler // WrapHandlerFunction Provides a lambda handler which wraps customer lambda handler with OTel Tracing func WrapHandlerFunction(handlerFunc interface{}, options ...Option) interface{} { - cfg := config{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, - EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, - Propagator: otel.GetTextMapPropagator(), - } - for _, opt := range options { - opt.apply(&cfg) - } - - i := instrumentor{} - i.configuration = cfg - // Get a named tracer with package path as its name. - i.tracer = i.configuration.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())) - - whf := wrappedHandlerFunction{instrumentor: i} + whf := wrappedHandlerFunction{instrumentor: newInstrumentor(options...)} if handlerFunc == nil { return errorHandler(fmt.Errorf("handler is nil")) From 8226dd37ba54d1db981e11606f2d9677d058a63f Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Thu, 29 Jul 2021 17:26:57 -0700 Subject: [PATCH 37/43] Add AWS Lambda Instrumentation - update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13e61d7c1c0..4c747a94d99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] +### Added + +- Add instrumentation for the `github.com/aws/aws-lambda-go` package. (#882) +- Add resource detector for AWS Lambda. (#882) + ## [0.22.0] - 2021-07-26 ### Added From 986e366f4c233c2ece4b28be6c701c9209993487 Mon Sep 17 00:00:00 2001 From: Garrett Egan <22334769+garrettwegan@users.noreply.github.com> Date: Fri, 30 Jul 2021 09:43:23 -0700 Subject: [PATCH 38/43] Rename EventToTextMapCarrierConverter to EventToCarrier --- .../aws/aws-lambda-go/otellambda/README.md | 8 +++---- .../aws/aws-lambda-go/otellambda/config.go | 23 ++++++++++--------- .../aws/aws-lambda-go/otellambda/lambda.go | 14 +++++------ .../aws/aws-lambda-go/otellambda/test/go.sum | 4 ---- .../otellambda/test/lambda_test.go | 8 +++---- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md index 41f621d6485..9b0171fd195 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md @@ -57,20 +57,20 @@ func main() { | --- | --- | --- | --- | | `WithTracerProvider` | `trace.TracerProvider` | Provide a custom `TracerProvider` for creating spans. Consider using the [AWS Lambda Resource Detector][lambda-detector-url] with your tracer provider to improve tracing information. | `otel.GetTracerProvider()` | `WithFlusher` | `otellambda.Flusher` | This instrumentation will call the `ForceFlush` method of its `Flusher` at the end of each invocation. Should you be using asynchronous logic (such as `sddktrace's BatchSpanProcessor`) it is very import for spans to be `ForceFlush`'ed before [Lambda freezes](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-context.html) to avoid data delays. | `Flusher` with noop `ForceFlush` -| `WithEventToTextMapCarrierConverter` | `func(eventJSON []byte) propagation.TextMapCarrier{}` | Function for providing custom logic to support retrieving trace header from different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway) and returning them in a `propagation.TextMapCarrier` which a Propagator can use to extract the trace header into the context. | Function which returns an empty `TextMapCarrier` - new spans will be part of a new Trace and have no parent past Lambda instrumentation span +| `WithEventToCarrier` | `func(eventJSON []byte) propagation.TextMapCarrier{}` | Function for providing custom logic to support retrieving trace header from different event types that are handled by AWS Lambda (e.g., SQS, CloudWatch, Kinesis, API Gateway) and returning them in a `propagation.TextMapCarrier` which a Propagator can use to extract the trace header into the context. | Function which returns an empty `TextMapCarrier` - new spans will be part of a new Trace and have no parent past Lambda instrumentation span | `WithPropagator` | `propagation.Propagator` | The `Propagator` the instrumentation will use to extract trace information into the context. | `otel.GetTextMapPropagator()` | ### Usage With Options Example ```go -var someHeaderKey = "Key" // used by propagator and converter to identify trace header +var someHeaderKey = "Key" // used by propagator and EventToCarrier function to identify trace header type mockHTTPRequest struct { Headers map[string][]string Body string } -func mockConverter(eventJSON []byte) propagation.TextMapCarrier{ +func mockEventToCarrier(eventJSON []byte) propagation.TextMapCarrier{ var request mockHTTPRequest _ = json.unmarshal(eventJSON, &request) return propogation.HeaderCarrier{someHeaderKey: []string{request.Headers[someHeaderKey]}} @@ -94,7 +94,7 @@ func main() { lambda.Start(otellambda.WrapHandlerFunction(HandleRequest, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp), - otellambda.WithEventToTextMapCarrierConverter(mockConverter), + otellambda.WithEventToCarrier(mockEventToCarrier), otellambda.WithPropagator(mockPropagator{}))) } ``` diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go index 1ad34e8d046..fc4309379d1 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/config.go @@ -38,20 +38,20 @@ func (*noopFlusher) ForceFlush(context.Context) error { return nil } // Compile time check our noopFlusher implements Flusher var _ Flusher = &noopFlusher{} -// An EventToTextMapCarrierConverter defines how the instrumentation should +// An EventToCarrier function defines how the instrumentation should // prepare a TextMapCarrier for the configured propagator to read from. This // extra step is necessary because Lambda does not have HTTP headers to read // from and instead stores the headers it was invoked with (including TraceID, etc.) // as part of the invocation event. If using the AWS XRay tracing then the // trace information is instead stored in the Lambda environment. -type EventToTextMapCarrierConverter func(eventJSON []byte) propagation.TextMapCarrier +type EventToCarrier func(eventJSON []byte) propagation.TextMapCarrier -func emptyEventToTextMapCarrierConverter([]byte) propagation.TextMapCarrier { +func emptyEventToCarrier([]byte) propagation.TextMapCarrier { return propagation.HeaderCarrier{} } -// Compile time check our emptyEventToTextMapCarrierConverter implements EventToTextMapCarrierConverter -var _ EventToTextMapCarrierConverter = emptyEventToTextMapCarrierConverter +// Compile time check our emptyEventToCarrier implements EventToCarrier +var _ EventToCarrier = emptyEventToCarrier type Option interface { apply(*config) @@ -77,12 +77,13 @@ type config struct { // default can result in long data delays in asynchronous settings Flusher Flusher - // EventToTextMapCarrierConverter is the mechanism used to retrieve the TraceID + // EventToCarrier is the mechanism used to retrieve the TraceID // from the event or environment and generate a TextMapCarrier which // can then be used by a Propagator to extract the TraceID into our context - // The default value of eventToTextMapCarrierConverter returns an empty - // HeaderCarrier, using this default will cause all spans to be not be traced - EventToTextMapCarrierConverter EventToTextMapCarrierConverter + // The default value of eventToCarrier is emptyEventToCarrier which returns + // an empty HeaderCarrier, using this default will cause new spans to be part + // of a new Trace and have no parent past our Lambda instrumentation span + EventToCarrier EventToCarrier // Propagator is the Propagator which will be used // to extract Trace info into the context @@ -103,9 +104,9 @@ func WithFlusher(flusher Flusher) Option { }) } -func WithEventToTextMapCarrierConverter(eventToTextMapCarrierConverter EventToTextMapCarrierConverter) Option { +func WithEventToCarrier(eventToCarrier EventToCarrier) Option { return optionFunc(func(c *config) { - c.EventToTextMapCarrierConverter = eventToTextMapCarrierConverter + c.EventToCarrier = eventToCarrier }) } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go index 23ffed445cd..593f304d795 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda.go @@ -43,24 +43,24 @@ type instrumentor struct { func newInstrumentor(opts ...Option) instrumentor { cfg := config{ - TracerProvider: otel.GetTracerProvider(), - Flusher: &noopFlusher{}, - EventToTextMapCarrierConverter: emptyEventToTextMapCarrierConverter, - Propagator: otel.GetTextMapPropagator(), + TracerProvider: otel.GetTracerProvider(), + Flusher: &noopFlusher{}, + EventToCarrier: emptyEventToCarrier, + Propagator: otel.GetTextMapPropagator(), } for _, opt := range opts { opt.apply(&cfg) } return instrumentor{configuration: cfg, - tracer: cfg.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())), - resAttrs: []attribute.KeyValue{}} + tracer: cfg.TracerProvider.Tracer(tracerName, trace.WithInstrumentationVersion(contrib.SemVersion())), + resAttrs: []attribute.KeyValue{}} } // Logic to start OTel Tracing func (i *instrumentor) tracingBegin(ctx context.Context, eventJSON []byte) (context.Context, trace.Span) { // Add trace id to context - mc := i.configuration.EventToTextMapCarrierConverter(eventJSON) + mc := i.configuration.EventToCarrier(eventJSON) ctx = i.configuration.Propagator.Extract(ctx, mc) var span trace.Span diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index 6b8e4671501..e317835b088 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -18,14 +18,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/sdk v1.0.0-RC1/go.mod h1:kj6yPn7Pgt5ByRuwesbaWcRLA+V7BSDg3Hf8xRvsvf8= go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= -go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7 h1:iGu644GcxtEcrInvDsQRCwJjtCIOlT2V7IRt6ah2Whw= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index effed697235..386401b9990 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -342,12 +342,12 @@ var ( } ) -func mockRequestToTextMapCarrierConverter(eventJSON []byte) propagation.TextMapCarrier { +func mockRequestCarrier(eventJSON []byte) propagation.TextMapCarrier { var event mockRequest err := json.Unmarshal(eventJSON, &event) if err != nil { fmt.Println("event type: ", reflect.TypeOf(event)) - panic("This TextMapCarrierConverter only supports events of type mockRequest") + panic("mockRequestCarrier only supports events of type mockRequest") } return propagation.HeaderCarrier{mockPropagatorKey: []string{event.Headers[mockPropagatorKey]}} } @@ -365,7 +365,7 @@ func TestWrapHandlerFunctionTracingWithMockPropagator(t *testing.T) { wrapped := otellambda.WrapHandlerFunction(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithPropagator(mockPropagator{}), - otellambda.WithEventToTextMapCarrierConverter(mockRequestToTextMapCarrierConverter)) + otellambda.WithEventToCarrier(mockRequestCarrier)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockPropagatorTestsContext), reflect.ValueOf(mockPropagatorTestsEvent)}) @@ -386,7 +386,7 @@ func TestWrapHandlerTracingWithMockPropagator(t *testing.T) { wrapped := otellambda.WrapHandler(emptyHandler{}, otellambda.WithTracerProvider(tp), otellambda.WithPropagator(mockPropagator{}), - otellambda.WithEventToTextMapCarrierConverter(mockRequestToTextMapCarrierConverter)) + otellambda.WithEventToCarrier(mockRequestCarrier)) payload, _ := json.Marshal(mockPropagatorTestsEvent) _, err := wrapped.Invoke(mockPropagatorTestsContext, payload) From 1754a2390887c17d337df06d6c8eaae098b9ec33 Mon Sep 17 00:00:00 2001 From: Bhautik Pipaliya <56270044+bhautikpip@users.noreply.github.com> Date: Fri, 13 Aug 2021 11:43:49 -0700 Subject: [PATCH 39/43] Update CHANGELOG.md Co-authored-by: garrettwegan <22334769+garrettwegan@users.noreply.github.com> --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 491d2d11b88..2ff7a5d0061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +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. (#882) -- Add resource detector for AWS Lambda. (#882) +- Add instrumentation for the `github.com/aws/aws-lambda-go` package. (#983) +- Add resource detector for AWS Lambda. (#983) ### Changed From 92b045b58bbaa9fb46be4bfe7285b5d3813e4b64 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Wed, 13 Oct 2021 14:08:35 -0700 Subject: [PATCH 40/43] updated dependencies to latest version --- detectors/aws/lambda/go.mod | 4 +- detectors/aws/lambda/go.sum | 12 ++--- .../aws-lambda-go/otellambda/example/go.mod | 14 +++--- .../aws-lambda-go/otellambda/example/go.sum | 50 +++++++++---------- .../aws/aws-lambda-go/otellambda/test/go.mod | 14 +++--- .../aws/aws-lambda-go/otellambda/test/go.sum | 10 ++-- 6 files changed, 52 insertions(+), 52 deletions(-) diff --git a/detectors/aws/lambda/go.mod b/detectors/aws/lambda/go.mod index 1e19a3e4f73..d733938ec2f 100644 --- a/detectors/aws/lambda/go.mod +++ b/detectors/aws/lambda/go.mod @@ -5,7 +5,7 @@ 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.0-RC2 - go.opentelemetry.io/otel/sdk v1.0.0-RC2 + 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 ) diff --git a/detectors/aws/lambda/go.sum b/detectors/aws/lambda/go.sum index e55f7ec727d..37288a60436 100644 --- a/detectors/aws/lambda/go.sum +++ b/detectors/aws/lambda/go.sum @@ -8,12 +8,12 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN 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.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= -go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= -go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= -go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= -go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod index 8d9175db39b..d199cda0a81 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.mod @@ -11,12 +11,12 @@ require ( github.com/aws/aws-lambda-go v1.25.0 github.com/aws/aws-sdk-go-v2/config v1.5.0 github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1 - go.opentelemetry.io/contrib/detectors/aws/lambda v0.22.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.22.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0 - go.opentelemetry.io/otel v1.0.0-RC2 - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2 - go.opentelemetry.io/otel/sdk v1.0.0-RC2 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.24.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.24.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.24.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0 + go.opentelemetry.io/otel v1.0.1 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.1 + go.opentelemetry.io/otel/sdk v1.0.1 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum index e00570576ed..6e3c6e12ffa 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -2,9 +2,9 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/aws/aws-lambda-go v1.24.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= github.com/aws/aws-lambda-go v1.25.0 h1:hv0Av6ooQhnqMS2jqeaph0izIwwaV2N6gsT5ad17Ihw= github.com/aws/aws-lambda-go v1.25.0/go.mod h1:jJmlefzPfGnckuHdXX7/80O3BvUUi12XOkbv4w9SGLU= -github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo= -github.com/aws/aws-sdk-go-v2 v1.7.1 h1:TswSc7KNqZ/K1Ijt3IkpXk/2+62vi3Q82Yrr5wSbRBQ= github.com/aws/aws-sdk-go-v2 v1.7.1/go.mod h1:L5LuPC1ZgDr2xQS7AmIec/Jlc7O/Y1u2KxJyNVab250= +github.com/aws/aws-sdk-go-v2 v1.9.0 h1:+S+dSqQCN3MSU5vJRu1HqHrq00cJn6heIMU7X9hcsoo= +github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= github.com/aws/aws-sdk-go-v2/config v1.5.0 h1:tRQcWXVmO7wC+ApwYc2LiYKfIBoIrdzcJ+7HIh6AlR0= github.com/aws/aws-sdk-go-v2/config v1.5.0/go.mod h1:RWlPOAW3E3tbtNAqTwvSW54Of/yP3oiZXMI0xfUdjyA= github.com/aws/aws-sdk-go-v2/credentials v1.3.1 h1:fFeqL5+9kwFKsCb2oci5yAIDsWYqn/Nga8oQ5bIasI8= @@ -19,17 +19,15 @@ github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1 h1:VJe/XEhrfy github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.1/go.mod h1:zceowr5Z1Nh2WVP8bf/3ikB41IZW59E4yIYbg+pC6mw= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.1 h1:1ds3HkMQEBx9XvOkqsPuqBmNFn0w8XEDuB4LOi6KepU= github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.5.1/go.mod h1:6EQZIwNNvHpq/2/QSJnp4+ECvqIy55w95Ofs0ze+nGQ= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1 h1:cKr6St+CtC3/dl/rEBJvlk7A/IN5D5F02GNkGzfbtVU= -github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1/go.mod h1:rLiOUrPLW/Er5kRcQ7NkwbjlijluLsrIbu/iyl35RO4= github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1 h1:HiXhafnqG0AkVJIZA/BHhFvuc/8xFdUO1uaeqF2Artc= github.com/aws/aws-sdk-go-v2/service/s3 v1.11.1/go.mod h1:XLAGFrEjbvMCLvAtWLLP32yTv8GpBquCApZEycDLunI= github.com/aws/aws-sdk-go-v2/service/sso v1.3.1 h1:H2ZLWHUbbeYtghuqCY5s/7tbBM99PAwCioRJF8QvV/U= github.com/aws/aws-sdk-go-v2/service/sso v1.3.1/go.mod h1:J3A3RGUvuCZjvSuZEcOpHDnzZP/sKbhDWV2T1EOzFIM= github.com/aws/aws-sdk-go-v2/service/sts v1.6.0 h1:Y9r6mrzOyAYz4qKaluSH19zqH1236il/nGbsPKOUT0s= github.com/aws/aws-sdk-go-v2/service/sts v1.6.0/go.mod h1:q7o0j7d7HrJk/vr9uUt3BVRASvcU7gYZB9PUgPiByXg= -github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw= -github.com/aws/smithy-go v1.6.0 h1:T6puApfBcYiTIsaI+SYWqanjMt5pc3aoyyDrI+0YH54= github.com/aws/smithy-go v1.6.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= +github.com/aws/smithy-go v1.8.0 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -37,7 +35,6 @@ 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/felixge/httpsnoop v1.0.2 h1:+nS9g82KMXccJ/wp0zyRW9ZBHFETmMGtkk+2CTTrW4o= github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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= @@ -54,27 +51,28 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= go.opentelemetry.io/contrib v0.22.0 h1:0F7gDEjgb1WGn4ODIjaCAg75hmqF+UN0LiVgwxsCodc= go.opentelemetry.io/contrib v0.22.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0 h1:yvHsET05+W6mGbiBmpzeSNfguFl7wdGc7wnZzL6oXZg= -go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.22.0/go.mod h1:SYNRbn31XulM3soVaBCla9PC47il0lxsiIVPGVDdJLE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0 h1:WHjZguqT+3UjTgFum33hWZYybDVnx8u9q5/kQDfaGTs= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0/go.mod h1:o3MuU25bYroYnc2TOKe8mTk8f9X1oPFO6C5RCoPKtSU= -go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I= -go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.24.0 h1:JKp/X40ED2m1wr1fDlYteCjrLSFeNQxzDGfwSYVu38Y= +go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.24.0/go.mod h1:Pw7z7OmZppGj5rd3QHTPFt2GO820JNVJWdImqLsoKpg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0 h1:qW6j1kJU24yo2xIu16Py4m4AXn1dd+s2uKllGnTFAm0= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0/go.mod h1:7W3JSDYTtH3qKKHrS1fMiwLtK7iZFLPq1+7htfspX/E= go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2 h1:crksoFyTPDDywRJDUW36OZma+C3HhcYwQLPUZZMXFO0= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.0-RC2/go.mod h1:6kVxj1C/f3irP/IeeZNbcEwbg3rwnM6a7bCrcGbIJeI= -go.opentelemetry.io/otel/internal/metric v0.22.0 h1:Q9bS02XRykSRIbggaU4hVF9oWOP9PyILu26zJWoKmk0= -go.opentelemetry.io/otel/internal/metric v0.22.0/go.mod h1:7qVuMihW/ktMonEfOvBXuh6tfMvvEyoIDgeJNRloYbQ= -go.opentelemetry.io/otel/metric v0.22.0 h1:/qv10BzznqEifrXBwsTT370OCN1PRgt+mnjzMwxJKrQ= -go.opentelemetry.io/otel/metric v0.22.0/go.mod h1:KcsUkBiYGW003DJ+ugd2aqIRIfjabD9jeOUXqsAtrq0= -go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk= -go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A= -go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= -go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= -go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg= -go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ= +go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= +go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= +go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.1 h1:QaXn87hD37gomnr0W9OVju7ouaijrT7+92uurmn2zvQ= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.0.1/go.mod h1:B1r9v/IqMtkB0lIGbbayqT6f2awSH0EDZya1Yu4p1pU= +go.opentelemetry.io/otel/internal/metric v0.23.0 h1:mPfzm9Iqhw7G2nDBmUAjFTfPqLZPbOW2k7QI57ITbaI= +go.opentelemetry.io/otel/internal/metric v0.23.0/go.mod h1:z+RPiDJe30YnCrOhFGivwBS+DU1JU/PiLKkk4re2DNY= +go.opentelemetry.io/otel/metric v0.23.0 h1:mYCcDxi60P4T27/0jchIDFa1WHEfQeU3zH9UEMpnj2c= +go.opentelemetry.io/otel/metric v0.23.0/go.mod h1:G/Nn9InyNnIv7J6YVkQfpc0JCfKBNJaERBGw08nqmVQ= +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.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo= +go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= +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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod index 839b56a8296..44c8d20df58 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.mod @@ -12,11 +12,11 @@ replace ( require ( github.com/aws/aws-lambda-go v1.25.0 github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/contrib v0.22.0 - go.opentelemetry.io/contrib/detectors/aws/lambda v0.22.0 - go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.22.0 - go.opentelemetry.io/contrib/propagators/aws v0.22.0 - go.opentelemetry.io/otel v1.0.0-RC2 - go.opentelemetry.io/otel/sdk v1.0.0-RC2 - go.opentelemetry.io/otel/trace v1.0.0-RC2 + go.opentelemetry.io/contrib v0.24.0 + go.opentelemetry.io/contrib/detectors/aws/lambda v0.24.0 + go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda v0.24.0 + go.opentelemetry.io/contrib/propagators/aws v0.24.0 + go.opentelemetry.io/otel v1.0.1 + go.opentelemetry.io/otel/sdk v1.0.1 + go.opentelemetry.io/otel/trace v1.0.1 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index e317835b088..57c75f902ca 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -18,12 +18,14 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs= -go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw= -go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= +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.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +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= From 93e9916845d2b1f0f3349b76431b1bc60a178937 Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Tue, 19 Oct 2021 12:22:51 -0700 Subject: [PATCH 41/43] added logging library and minor changes --- .../aws-lambda-go/otellambda/example/go.sum | 6 ++--- .../aws-lambda-go/otellambda/example/main.go | 25 ++++++++++--------- .../aws/aws-lambda-go/otellambda/go.mod | 6 ++--- .../aws/aws-lambda-go/otellambda/go.sum | 8 +++--- .../aws/aws-lambda-go/otellambda/test/go.sum | 2 -- 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum index 6e3c6e12ffa..f235b9b4dd3 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/go.sum @@ -49,13 +49,12 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/contrib v0.22.0 h1:0F7gDEjgb1WGn4ODIjaCAg75hmqF+UN0LiVgwxsCodc= -go.opentelemetry.io/contrib v0.22.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= +go.opentelemetry.io/contrib v0.24.0 h1:bVBRFM9tOQkTlf45xEmr29hNyASQeYGrJf4iLzn2WOg= +go.opentelemetry.io/contrib v0.24.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.24.0 h1:JKp/X40ED2m1wr1fDlYteCjrLSFeNQxzDGfwSYVu38Y= go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.24.0/go.mod h1:Pw7z7OmZppGj5rd3QHTPFt2GO820JNVJWdImqLsoKpg= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0 h1:qW6j1kJU24yo2xIu16Py4m4AXn1dd+s2uKllGnTFAm0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.24.0/go.mod h1:7W3JSDYTtH3qKKHrS1fMiwLtK7iZFLPq1+7htfspX/E= -go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= go.opentelemetry.io/otel v1.0.0-RC3/go.mod h1:Ka5j3ua8tZs4Rkq4Ex3hwgBgOchyPVq5S6P2lz//nKQ= go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg= go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= @@ -68,7 +67,6 @@ go.opentelemetry.io/otel/metric v0.23.0 h1:mYCcDxi60P4T27/0jchIDFa1WHEfQeU3zH9UE go.opentelemetry.io/otel/metric v0.23.0/go.mod h1:G/Nn9InyNnIv7J6YVkQfpc0JCfKBNJaERBGw08nqmVQ= 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.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= go.opentelemetry.io/otel/trace v1.0.0-RC3/go.mod h1:VUt2TUYd8S2/ZRX09ZDFZQwn2RqfMB5MzO17jBojGxo= go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs= go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index 28d36df0b2e..595d97502b1 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -17,8 +17,8 @@ package main import ( "context" "encoding/json" - "fmt" "io" + "log" "net/http" "github.com/aws/aws-lambda-go/lambda" @@ -38,7 +38,7 @@ func lambdaHandler(ctx context.Context) error { // init aws config cfg, err := awsConfig.LoadDefaultConfig(ctx) if err != nil { - panic("configuration error, " + err.Error()) + return err } // instrument all aws clients @@ -49,12 +49,12 @@ func lambdaHandler(ctx context.Context) error { input := &s3.ListBucketsInput{} result, err := s3Client.ListBuckets(ctx, input) if err != nil { - fmt.Printf("Got an error retrieving buckets, %v", err) + return err } - fmt.Println("Buckets:") + log.Println("Buckets:") for _, bucket := range result.Buckets { - fmt.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) + log.Println(*bucket.Name + ": " + bucket.CreationDate.Format("2006-01-02 15:04:05 Monday")) } // HTTP @@ -66,29 +66,29 @@ func lambdaHandler(ctx context.Context) error { } req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://api.github.com/repos/open-telemetry/opentelemetry-go/releases/latest", nil) if err != nil { - fmt.Printf("failed to create http request, %v\n", err) + log.Printf("failed to create http request, %v\n", err) return err } res, err := client.Do(req) if err != nil { - fmt.Printf("failed to do http request, %v\n", err) + log.Printf("failed to do http request, %v\n", err) return err } defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { - fmt.Printf("failed to close http response body, %v\n", err) + log.Printf("failed to close http response body, %v\n", err) } }(res.Body) var data map[string]interface{} err = json.NewDecoder(res.Body).Decode(&data) if err != nil { - fmt.Printf("failed to read http response body, %v\n", err) + log.Printf("failed to read http response body, %v\n", err) } - fmt.Printf("Latest OTel Go Release is '%s'\n", data["name"]) + log.Printf("Latest OTel Go Release is '%s'\n", data["name"]) return nil } @@ -98,14 +98,15 @@ func main() { exp, err := stdouttrace.New() if err != nil { - fmt.Printf("failed to initialize stdout exporter %v\n", err) + log.Printf("failed to initialize stdout exporter %v\n", err) return } detector := lambdadetector.NewResourceDetector() res, err := detector.Detect(ctx) if err != nil { - fmt.Printf("failed to detect lambda resources: %v\n", err) + log.Fatalf("failed to detect lambda resources: %v\n", err) + return } tp := sdktrace.NewTracerProvider( diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod index d5760f17652..5fc958de0f3 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.mod @@ -7,7 +7,7 @@ replace go.opentelemetry.io/contrib => ../../../../.. require ( github.com/aws/aws-lambda-go v1.24.0 github.com/stretchr/testify v1.7.0 - go.opentelemetry.io/contrib v0.22.0 - go.opentelemetry.io/otel v1.0.0-RC2 - go.opentelemetry.io/otel/trace v1.0.0-RC2 + go.opentelemetry.io/contrib v0.24.0 + go.opentelemetry.io/otel v1.0.1 + go.opentelemetry.io/otel/trace v1.0.1 ) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum index 9418aba069b..f42a9801ea8 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/go.sum @@ -17,10 +17,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg= -go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= -go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w= -go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= +go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc= +go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU= +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/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= diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum index 57c75f902ca..6f5d0bf59ec 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/go.sum @@ -18,12 +18,10 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= -go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM= 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.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4= 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= From cbc1242c8ce312a6e0eaba77a54e483ad8ccd4ba Mon Sep 17 00:00:00 2001 From: bhautikpip Date: Thu, 21 Oct 2021 16:15:14 -0700 Subject: [PATCH 42/43] modified lambda handler function name --- .../aws/aws-lambda-go/otellambda/README.md | 4 ++-- .../github.com/aws/aws-lambda-go/otellambda/doc.go | 2 +- .../aws/aws-lambda-go/otellambda/example/main.go | 2 +- .../aws/aws-lambda-go/otellambda/lambda_test.go | 8 ++++---- .../aws/aws-lambda-go/otellambda/test/lambda_test.go | 12 ++++++------ .../aws-lambda-go/otellambda/wrapLambdaHandler.go | 4 ++-- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md index 9b0171fd195..583d748119c 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/README.md @@ -47,7 +47,7 @@ import "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go // wrap lambda handler function func main() { - lambda.Start(otellambda.WrapHandlerFunction(HandleRequest)) + lambda.Start(otellambda.InstrumentHandler(HandleRequest)) } ``` @@ -91,7 +91,7 @@ func main() { tp := sdktrace.NewTracerProvider( sdktrace.WithBatcher(exp)) - lambda.Start(otellambda.WrapHandlerFunction(HandleRequest, + lambda.Start(otellambda.InstrumentHandler(HandleRequest, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(tp), otellambda.WithEventToCarrier(mockEventToCarrier), diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go index 100fce7001d..8bce481e3b6 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/doc.go @@ -17,6 +17,6 @@ // Two wrappers are provided which can be used to instrument Lambda, // one for each Lambda entrypoint. Their usages are shown below. // -// lambda.Start() entrypoint: lambda.Start(otellambda.WrapHandlerFunction()) +// lambda.Start() entrypoint: lambda.Start(otellambda.InstrumentHandler()) // lambda.StartHandler() entrypoint: lambda.StartHandler(otellambda.WrapHandler()) package otellambda // import "go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-lambda-go/otellambda" diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go index 595d97502b1..834c49260b4 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/example/main.go @@ -117,5 +117,5 @@ func main() { // Downstream spans use global tracer provider otel.SetTracerProvider(tp) - lambda.Start(otellambda.WrapHandlerFunction(lambdaHandler, otellambda.WithTracerProvider(tp))) + lambda.Start(otellambda.InstrumentHandler(lambdaHandler, otellambda.WithTracerProvider(tp))) } diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go index 6febd43c47f..caa823ce8af 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/lambda_test.go @@ -130,7 +130,7 @@ func TestLambdaHandlerSignatures(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("testCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := WrapHandlerFunction(testCase.handler) + lambdaHandler := InstrumentHandler(testCase.handler) handler := reflect.ValueOf(lambdaHandler) resp := handler.Call(testCase.args) assert.Equal(t, 2, len(resp)) @@ -227,7 +227,7 @@ func TestHandlerInvokes(t *testing.T) { for i, testCase := range testCases { testCase := testCase t.Run(fmt.Sprintf("lambdaHandlerTestCase[%d] %s", i, testCase.name), func(t *testing.T) { - lambdaHandler := WrapHandlerFunction(testCase.handler) + lambdaHandler := InstrumentHandler(testCase.handler) handler := reflect.ValueOf(lambdaHandler) handlerType := handler.Type() @@ -265,13 +265,13 @@ func TestHandlerInvokes(t *testing.T) { } } -func BenchmarkWrapHandlerFunction(b *testing.B) { +func BenchmarkInstrumentHandler(b *testing.B) { setEnvVars() customerHandler := func(ctx context.Context, payload int) error { return nil } - wrapped := WrapHandlerFunction(customerHandler) + wrapped := InstrumentHandler(customerHandler) wrappedCallable := reflect.ValueOf(wrapped) ctx := reflect.ValueOf(mockContext) payload := reflect.ValueOf(0) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go index 386401b9990..cce52cf5f19 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/test/lambda_test.go @@ -171,7 +171,7 @@ func assertStubEqualsIgnoreTime(t *testing.T, expected tracetest.SpanStub, actua assert.Equal(t, expected.InstrumentationLibrary, actual.InstrumentationLibrary) } -func TestWrapHandlerFunctionTracing(t *testing.T) { +func TestInstrumentHandlerTracing(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() @@ -180,7 +180,7 @@ func TestWrapHandlerFunctionTracing(t *testing.T) { } // No flusher needed as SimpleSpanProcessor is synchronous - wrapped := otellambda.WrapHandlerFunction(customerHandler, otellambda.WithTracerProvider(tp)) + wrapped := otellambda.InstrumentHandler(customerHandler, otellambda.WithTracerProvider(tp)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) assert.Len(t, resp, 2) @@ -217,7 +217,7 @@ func (mf *mockFlusher) ForceFlush(context.Context) error { var _ otellambda.Flusher = &mockFlusher{} -func TestWrapHandlerFunctionTracingWithFlusher(t *testing.T) { +func TestInstrumentHandlerTracingWithFlusher(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() @@ -226,7 +226,7 @@ func TestWrapHandlerFunctionTracingWithFlusher(t *testing.T) { } flusher := mockFlusher{} - wrapped := otellambda.WrapHandlerFunction(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(&flusher)) + wrapped := otellambda.InstrumentHandler(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithFlusher(&flusher)) wrappedCallable := reflect.ValueOf(wrapped) resp := wrappedCallable.Call([]reflect.Value{reflect.ValueOf(mockContext)}) assert.Len(t, resp, 2) @@ -352,7 +352,7 @@ func mockRequestCarrier(eventJSON []byte) propagation.TextMapCarrier { return propagation.HeaderCarrier{mockPropagatorKey: []string{event.Headers[mockPropagatorKey]}} } -func TestWrapHandlerFunctionTracingWithMockPropagator(t *testing.T) { +func TestInstrumentHandlerTracingWithMockPropagator(t *testing.T) { setEnvVars() tp, memExporter := initMockTracerProvider() @@ -362,7 +362,7 @@ func TestWrapHandlerFunctionTracingWithMockPropagator(t *testing.T) { } // No flusher needed as SimpleSpanProcessor is synchronous - wrapped := otellambda.WrapHandlerFunction(customerHandler, + wrapped := otellambda.InstrumentHandler(customerHandler, otellambda.WithTracerProvider(tp), otellambda.WithPropagator(mockPropagator{}), otellambda.WithEventToCarrier(mockRequestCarrier)) diff --git a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go index dd85ea8de0e..54a6beb7a60 100644 --- a/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go +++ b/instrumentation/github.com/aws/aws-lambda-go/otellambda/wrapLambdaHandler.go @@ -94,8 +94,8 @@ func (whf *wrappedHandlerFunction) wrapperInternals(ctx context.Context, handler return val, err } -// WrapHandlerFunction Provides a lambda handler which wraps customer lambda handler with OTel Tracing -func WrapHandlerFunction(handlerFunc interface{}, options ...Option) interface{} { +// InstrumentHandler Provides a lambda handler which wraps customer lambda handler with OTel Tracing +func InstrumentHandler(handlerFunc interface{}, options ...Option) interface{} { whf := wrappedHandlerFunction{instrumentor: newInstrumentor(options...)} if handlerFunc == nil { From 8dd0fe899d481897637612473815e1d689fd5495 Mon Sep 17 00:00:00 2001 From: Anthony Mirabella Date: Mon, 25 Oct 2021 09:34:45 -0700 Subject: [PATCH 43/43] Update detectors/aws/lambda/detector.go Co-authored-by: William Armiros <54150514+willarmiros@users.noreply.github.com> --- detectors/aws/lambda/detector.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/detectors/aws/lambda/detector.go b/detectors/aws/lambda/detector.go index 44501f5d5cb..d34540e166c 100644 --- a/detectors/aws/lambda/detector.go +++ b/detectors/aws/lambda/detector.go @@ -24,6 +24,8 @@ import ( semconv "go.opentelemetry.io/otel/semconv/v1.4.0" ) +// For a complete list of reserved environment variables in Lambda, see: +// https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html const ( lambdaFunctionNameEnvVar = "AWS_LAMBDA_FUNCTION_NAME" awsRegionEnvVar = "AWS_REGION"