diff --git a/collector/Makefile b/collector/Makefile index 679e71cd41..48a665e033 100644 --- a/collector/Makefile +++ b/collector/Makefile @@ -6,6 +6,7 @@ BUCKET_NAME:=lambda-artifacts-$(shell dd if=/dev/random bs=8 count=1 2>/dev/null LAYER_NAME:=otel-collector OTELCOL_VERSION=$(shell cat VERSION) GIT_SHA=$(shell git rev-parse HEAD) +COLLECTOR_CONTRIB_VERSION=$(shell grep 'opentelemetry-collector-contrib/processor/attributesprocessor ' lambdacomponents/go.mod | awk '{print $$2}') GOARCH ?= amd64 GOBUILD=GO111MODULE=on CGO_ENABLED=0 installsuffix=cgo go build -trimpath$(if ${BUILDTAGS}, -tags "${BUILDTAGS}",) BUILD_INFO_IMPORT_PATH=main @@ -33,11 +34,16 @@ clean: rm -rf build/ .PHONY: build -build: clean set-otelcol-version +build: clean set-otelcol-version sync-resource-detection-fork @echo Building otel collector extension, $(shell go version) mkdir -p $(BUILD_SPACE)/extensions GOOS=linux GOARCH=$(GOARCH) $(GOBUILD) $(LDFLAGS) -o $(BUILD_SPACE)/extensions . +.PHONY: sync-resource-detection-fork +sync-resource-detection-fork: + @echo Syncing minimal resourcedetectionprocessor fork from upstream $(COLLECTOR_CONTRIB_VERSION) + cd lambdacomponents/processor/resourcedetectionprocessor && bash sync-from-upstream.sh $(COLLECTOR_CONTRIB_VERSION) + .PHONY: package package: build @echo Package zip file for collector extension layer diff --git a/collector/README.md b/collector/README.md index 79378e6f41..4dd237b5fd 100644 --- a/collector/README.md +++ b/collector/README.md @@ -195,3 +195,34 @@ When used with the batch processor the decouple processor must be the last proce is successfully exported before the lambda environment is frozen. As stated previously in the auto-configuration section, the OpenTelemetry Lambda Layer will automatically add the decouple processor to the end of the processors if the batch is used and the decouple processor is not. The result will be the same whether you configure it manually or not. + +## Minimal `resourcedetectionprocessor` fork + +The upstream `resourcedetectionprocessor` from `opentelemetry-collector-contrib` compiles 26 cloud-provider detectors into every binary (EC2, ECS, EKS, GCP, Kubernetes, Docker, Azure, DigitalOcean, etc.), even though the default Lambda config only uses `env` and `lambda`. This adds large transitive dependencies — AWS SDK v2/EC2, Kubernetes client, GCP SDK, Docker, Azure SDK — that bloat the Lambda binary and increase cold-start time. + +This repository ships a minimal local fork at `lambdacomponents/processor/resourcedetectionprocessor/` that includes only the `env` and `lambda` detectors. Both read exclusively from environment variables and have no cloud SDK dependencies. The fork is wired into the build via a `replace` directive in `lambdacomponents/go.mod`; no import paths in application code are affected. + +### How the sync works + +The fork is kept in sync with upstream using two patch files and a script: + +| File | Purpose | +|---|---| +| `lambdacomponents/processor/resourcedetectionprocessor/factory.patch` | Diff that strips the 24 unused detectors from `factory.go` | +| `lambdacomponents/processor/resourcedetectionprocessor/config.patch` | Diff that strips unused detector config structs from `config.go` | +| `lambdacomponents/processor/resourcedetectionprocessor/sync-from-upstream.sh` | Fetches all upstream files and applies the patches | + +`make build` (and `make package`) automatically runs the sync against the version of `opentelemetry-collector-contrib` declared in `lambdacomponents/go.mod`, so the fork is always up to date when building. + +### Upgrading to a new upstream version + +When the `opentelemetry-collector-contrib` version is bumped in `lambdacomponents/go.mod`, a `make build` will automatically re-sync. If the upstream `factory.go` or `config.go` have changed in ways that prevent the patch from applying cleanly, the sync script will stop with an error and print instructions for regenerating the patches: + +```shell +cd lambdacomponents/processor/resourcedetectionprocessor +./sync-from-upstream.sh v0.146.0 +# if the patch fails to apply, regenerate it: +diff -u /tmp/rdp_factory_upstream.go factory.go > factory.patch +diff -u /tmp/rdp_config_upstream.go config.go > config.patch +# then commit all changes +``` diff --git a/collector/go.mod b/collector/go.mod index 35bd8dab60..0b8236b69c 100644 --- a/collector/go.mod +++ b/collector/go.mod @@ -6,6 +6,8 @@ replace github.com/open-telemetry/opentelemetry-lambda/collector/lambdacomponent replace github.com/open-telemetry/opentelemetry-lambda/collector/lambdalifecycle => ./lambdalifecycle +replace github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor => ./lambdacomponents/processor/resourcedetectionprocessor + replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor => ./processor/coldstartprocessor replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/decoupleprocessor => ./processor/decoupleprocessor @@ -60,6 +62,7 @@ require ( github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 // indirect github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18 // indirect + github.com/aws/aws-sdk-go-v2/service/ec2 v1.283.0 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 // indirect github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.10 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 // indirect @@ -103,6 +106,7 @@ require ( github.com/hashicorp/go-version v1.8.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect + github.com/hetznercloud/hcloud-go/v2 v2.36.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jonboulle/clockwork v0.5.0 // indirect @@ -118,6 +122,7 @@ require ( github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect github.com/magefile/mage v1.15.0 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect @@ -140,6 +145,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.145.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor v0.145.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.145.0 // indirect + github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor v0.145.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.145.0 // indirect github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor v0.145.0 // indirect github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor v0.98.0 // indirect @@ -158,7 +164,7 @@ require ( github.com/prometheus/prometheus v0.309.2-0.20260113170727-c7bc56cf6c8f // indirect github.com/prometheus/sigv4 v0.3.0 // indirect github.com/rs/cors v1.11.1 // indirect - github.com/shirou/gopsutil/v4 v4.25.12 // indirect + github.com/shirou/gopsutil/v4 v4.26.1 // indirect github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/tg123/go-htpasswd v1.2.4 // indirect diff --git a/collector/go.sum b/collector/go.sum index 778f1dffc1..a9958e86bf 100644 --- a/collector/go.sum +++ b/collector/go.sum @@ -58,8 +58,8 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEG github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18 h1:eZioDaZGJ0tMM4gzmkNIO2aAoQd+je7Ug7TkvAzlmkU= github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18/go.mod h1:CCXwUKAJdoWr6/NcxZ+zsiPr6oH/Q5aTooRGYieAyj4= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0 h1:o7eJKe6VYAnqERPlLAvDW5VKXV6eTKv1oxTpMoDP378= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.283.0 h1:o1GTyhiyvSEy7uMiD9rImR4SQLrAQ2y6q1HE4cCU8E4= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.283.0/go.mod h1:Uy+C+Sc58jozdoL1McQr8bDsEvNFx+/nBY+vpO1HVUY= github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 h1:IZpZatHsscdOKjwmDXC6idsCXmm3F/obutAUNjnX+OM= github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0= @@ -258,8 +258,8 @@ github.com/hashicorp/nomad/api v0.0.0-20260106084653-e8f2200c7039 h1:77URO0yPjlP github.com/hashicorp/nomad/api v0.0.0-20260106084653-e8f2200c7039/go.mod h1:sldFTIgs+FsUeKU3LwVjviAIuksxD8TzDOn02MYwslE= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hetznercloud/hcloud-go/v2 v2.33.0 h1:g9hwuo60IXbupXJCYMlO4xDXgxxMPuFk31iOpLXDCV4= -github.com/hetznercloud/hcloud-go/v2 v2.33.0/go.mod h1:GzYEl7slIGKc6Ttt08hjiJvGj8/PbWzcQf6IUi02dIs= +github.com/hetznercloud/hcloud-go/v2 v2.36.0 h1:HlLL/aaVXUulqe+rsjoJmrxKhPi1MflL5O9iq5QEtvo= +github.com/hetznercloud/hcloud-go/v2 v2.36.0/go.mod h1:MnN/QJEa/RYNQiiVoJjNHPntM7Z1wlYPgJ2HA40/cDE= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= @@ -314,8 +314,8 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -423,8 +423,8 @@ github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 h1:ObX9hZmK+VmijreZO/8x9pQ8/P/ToHD/bdSb4Eg4tUo= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36/go.mod h1:LEsDu4BubxK7/cWhtlQWfuxwL4rf/2UEpxXz1o1EMtM= -github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY= -github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= +github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo= +github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= diff --git a/collector/lambdacomponents/default.go b/collector/lambdacomponents/default.go index 7d4cddfd12..f235ddb0ba 100644 --- a/collector/lambdacomponents/default.go +++ b/collector/lambdacomponents/default.go @@ -23,6 +23,7 @@ import ( "github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor" "github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor" "github.com/open-telemetry/opentelemetry-lambda/collector/processor/decoupleprocessor" @@ -67,6 +68,7 @@ func Components(extensionID string) (otelcol.Factories, error) { filterprocessor.NewFactory(), memorylimiterprocessor.NewFactory(), probabilisticsamplerprocessor.NewFactory(), + resourcedetectionprocessor.NewFactory(), resourceprocessor.NewFactory(), spanprocessor.NewFactory(), coldstartprocessor.NewFactory(), diff --git a/collector/lambdacomponents/go.mod b/collector/lambdacomponents/go.mod index 3de3503ebd..5ed9581c78 100644 --- a/collector/lambdacomponents/go.mod +++ b/collector/lambdacomponents/go.mod @@ -10,6 +10,7 @@ require ( github.com/open-telemetry/opentelemetry-collector-contrib/processor/attributesprocessor v0.145.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/filterprocessor v0.145.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/probabilisticsamplerprocessor v0.145.0 + github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor v0.145.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourceprocessor v0.145.0 github.com/open-telemetry/opentelemetry-collector-contrib/processor/spanprocessor v0.145.0 github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor v0.98.0 @@ -137,7 +138,7 @@ require ( github.com/prometheus/prometheus v0.309.2-0.20260113170727-c7bc56cf6c8f // indirect github.com/prometheus/sigv4 v0.3.0 // indirect github.com/rs/cors v1.11.1 // indirect - github.com/shirou/gopsutil/v4 v4.25.12 // indirect + github.com/shirou/gopsutil/v4 v4.26.1 // indirect github.com/spf13/cobra v1.10.2 // indirect github.com/spf13/pflag v1.0.10 // indirect github.com/stretchr/testify v1.11.1 // indirect @@ -267,6 +268,8 @@ replace github.com/open-telemetry/opentelemetry-lambda/collector => ../ replace github.com/open-telemetry/opentelemetry-lambda/collector/lambdalifecycle => ../lambdalifecycle +replace github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor => ./processor/resourcedetectionprocessor + replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/coldstartprocessor => ../processor/coldstartprocessor replace github.com/open-telemetry/opentelemetry-lambda/collector/processor/decoupleprocessor => ../processor/decoupleprocessor diff --git a/collector/lambdacomponents/go.sum b/collector/lambdacomponents/go.sum index acb955d770..b422bcd7da 100644 --- a/collector/lambdacomponents/go.sum +++ b/collector/lambdacomponents/go.sum @@ -54,8 +54,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoy github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0 h1:o7eJKe6VYAnqERPlLAvDW5VKXV6eTKv1oxTpMoDP378= -github.com/aws/aws-sdk-go-v2/service/ec2 v1.279.0/go.mod h1:Wg68QRgy2gEGGdmTPU/UbVpdv8sM14bUZmF64KFwAsY= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.283.0 h1:o1GTyhiyvSEy7uMiD9rImR4SQLrAQ2y6q1HE4cCU8E4= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.283.0/go.mod h1:Uy+C+Sc58jozdoL1McQr8bDsEvNFx+/nBY+vpO1HVUY= github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0 h1:IZpZatHsscdOKjwmDXC6idsCXmm3F/obutAUNjnX+OM= github.com/aws/aws-sdk-go-v2/service/ecs v1.70.0/go.mod h1:LQMlcWBoiFVD3vUVEz42ST0yTiaDujv2dRE6sXt1yPE= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0= @@ -246,8 +246,8 @@ github.com/hashicorp/nomad/api v0.0.0-20260106084653-e8f2200c7039 h1:77URO0yPjlP github.com/hashicorp/nomad/api v0.0.0-20260106084653-e8f2200c7039/go.mod h1:sldFTIgs+FsUeKU3LwVjviAIuksxD8TzDOn02MYwslE= github.com/hashicorp/serf v0.10.1 h1:Z1H2J60yRKvfDYAOZLd2MU0ND4AH/WDz7xYHDWQsIPY= github.com/hashicorp/serf v0.10.1/go.mod h1:yL2t6BqATOLGc5HF7qbFkTfXoPIY0WZdWHfEvMqbG+4= -github.com/hetznercloud/hcloud-go/v2 v2.33.0 h1:g9hwuo60IXbupXJCYMlO4xDXgxxMPuFk31iOpLXDCV4= -github.com/hetznercloud/hcloud-go/v2 v2.33.0/go.mod h1:GzYEl7slIGKc6Ttt08hjiJvGj8/PbWzcQf6IUi02dIs= +github.com/hetznercloud/hcloud-go/v2 v2.36.0 h1:HlLL/aaVXUulqe+rsjoJmrxKhPi1MflL5O9iq5QEtvo= +github.com/hetznercloud/hcloud-go/v2 v2.36.0/go.mod h1:MnN/QJEa/RYNQiiVoJjNHPntM7Z1wlYPgJ2HA40/cDE= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= @@ -302,8 +302,8 @@ github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa1 github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= +github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= @@ -407,8 +407,8 @@ github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36 h1:ObX9hZmK+VmijreZO/8x9pQ8/P/ToHD/bdSb4Eg4tUo= github.com/scaleway/scaleway-sdk-go v1.0.0-beta.36/go.mod h1:LEsDu4BubxK7/cWhtlQWfuxwL4rf/2UEpxXz1o1EMtM= -github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY= -github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU= +github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo= +github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc= github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU= github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4= github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= diff --git a/collector/lambdacomponents/processor/resourcedetection.go b/collector/lambdacomponents/processor/resourcedetection.go new file mode 100644 index 0000000000..1bfb72ebc0 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetection.go @@ -0,0 +1,28 @@ +//go:build lambdacomponents.custom && (lambdacomponents.all || lambdacomponents.processor.all || lambdacomponents.processor.resourcedetection) + +// 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 processor + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + "go.opentelemetry.io/collector/processor" +) + +func init() { + Factories = append(Factories, func(extensionId string) processor.Factory { + return resourcedetectionprocessor.NewFactory() + }) +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/config.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/config.go new file mode 100644 index 0000000000..b4aa7bcdce --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/config.go @@ -0,0 +1,64 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// This is a minimal fork of github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor +// Synced from: v0.145.0 +// Only the env and lambda detectors are included. +// +// To sync with a new upstream version: +// 1. Copy factory.go, config.go, resourcedetection_processor.go from the new version +// 2. Copy internal/resourcedetection.go, internal/context.go, internal/env/, internal/aws/lambda/ from the new version +// 3. Copy internal/metadata/generated_status.go and internal/metadata/generated_feature_gates.go from the new version +// 4. Re-apply the factory.go + config.go trimming (keep only env + lambda) +// 5. Update go.mod versions to match the new collector-contrib release +// 6. Run go mod tidy in this directory and in collector/lambdacomponents/ + +package resourcedetectionprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + +import ( + "time" + + "go.opentelemetry.io/collector/config/confighttp" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" +) + +// Config defines configuration for Resource processor. +type Config struct { + // Detectors is an ordered list of named detectors that should be + // run to attempt to detect resource information. + Detectors []string `mapstructure:"detectors"` + // Override indicates whether any existing resource attributes + // should be overridden or preserved. Defaults to true. + Override bool `mapstructure:"override"` + // DetectorConfig is a list of settings specific to all detectors + DetectorConfig DetectorConfig `mapstructure:",squash"` + // HTTP client settings for the detector + // Timeout default is 5s + confighttp.ClientConfig `mapstructure:",squash"` + // If > 0, periodically re-run detection for all configured detectors. + // When 0 (default), no periodic refresh occurs. + RefreshInterval time.Duration `mapstructure:"refresh_interval"` +} + +// DetectorConfig contains user-specified configurations unique to all individual detectors +type DetectorConfig struct { + // LambdaConfig contains user-specified configurations for the lambda detector + LambdaConfig lambda.Config `mapstructure:"lambda"` +} + +func detectorCreateDefaultConfig() DetectorConfig { + return DetectorConfig{ + LambdaConfig: lambda.CreateDefaultConfig(), + } +} + +func (d *DetectorConfig) GetConfigFromType(detectorType internal.DetectorType) internal.DetectorConfig { + switch detectorType { + case lambda.TypeStr: + return d.LambdaConfig + default: + return nil + } +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/config.patch b/collector/lambdacomponents/processor/resourcedetectionprocessor/config.patch new file mode 100644 index 0000000000..fab8d0bc04 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/config.patch @@ -0,0 +1,213 @@ +--- a/config.go ++++ b/config.go +@@ -1,6 +1,18 @@ + // Copyright The OpenTelemetry Authors + // SPDX-License-Identifier: Apache-2.0 + ++// This is a minimal fork of github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor ++// Synced from: v0.145.0 ++// Only the env and lambda detectors are included. ++// ++// To sync with a new upstream version: ++// 1. Copy factory.go, config.go, resourcedetection_processor.go from the new version ++// 2. Copy internal/resourcedetection.go, internal/context.go, internal/env/, internal/aws/lambda/ from the new version ++// 3. Copy internal/metadata/generated_status.go and internal/metadata/generated_feature_gates.go from the new version ++// 4. Re-apply the factory.go + config.go trimming (keep only env + lambda) ++// 5. Update go.mod versions to match the new collector-contrib release ++// 6. Run go mod tidy in this directory and in collector/lambdacomponents/ ++ + package resourcedetectionprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + + import ( +@@ -9,30 +21,7 @@ + "go.opentelemetry.io/collector/config/confighttp" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/akamai" +- alibabaecs "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/alibaba/ecs" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/digitalocean" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/hetzner" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/k8snode" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openstack/nova" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/oraclecloud" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/scaleway" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/upcloud" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/vultr" + ) + + // Config defines configuration for Resource processor. +@@ -55,158 +44,20 @@ + + // DetectorConfig contains user-specified configurations unique to all individual detectors + type DetectorConfig struct { +- // AlibabaECSConfig contains user-specified configurations for the Alibaba Cloud ECS detector +- AlibabaECSConfig alibabaecs.Config `mapstructure:"alibaba_ecs"` +- +- // EC2Config contains user-specified configurations for the EC2 detector +- EC2Config ec2.Config `mapstructure:"ec2"` +- +- // ECSConfig contains user-specified configurations for the ECS detector +- ECSConfig ecs.Config `mapstructure:"ecs"` +- +- // EKSConfig contains user-specified configurations for the EKS detector +- EKSConfig eks.Config `mapstructure:"eks"` +- +- // Elasticbeanstalk contains user-specified configurations for the elasticbeanstalk detector +- ElasticbeanstalkConfig elasticbeanstalk.Config `mapstructure:"elasticbeanstalk"` +- +- // Lambda contains user-specified configurations for the lambda detector ++ // LambdaConfig contains user-specified configurations for the lambda detector + LambdaConfig lambda.Config `mapstructure:"lambda"` +- +- // Azure contains user-specified configurations for the azure detector +- AzureConfig azure.Config `mapstructure:"azure"` +- +- // Aks contains user-specified configurations for the aks detector +- AksConfig aks.Config `mapstructure:"aks"` +- +- // ConsulConfig contains user-specified configurations for the Consul detector +- ConsulConfig consul.Config `mapstructure:"consul"` +- +- // DigitalOceanConfig contains user-specified configurations for the docker detector +- DigitalOceanConfig digitalocean.Config `mapstructure:"digitalocean"` +- +- // DockerConfig contains user-specified configurations for the docker detector +- DockerConfig docker.Config `mapstructure:"docker"` +- +- // GcpConfig contains user-specified configurations for the gcp detector +- GcpConfig gcp.Config `mapstructure:"gcp"` +- +- // HerokuConfig contains user-specified configurations for the heroku detector +- HerokuConfig heroku.Config `mapstructure:"heroku"` +- +- // HetznerConfig contains user-specified configurations for the hetzner detector +- HetznerConfig hetzner.Config `mapstructure:"hetzner"` +- +- // SystemConfig contains user-specified configurations for the System detector +- SystemConfig system.Config `mapstructure:"system"` +- +- // OpenShift contains user-specified configurations for the OpenShift detector +- OpenShiftConfig openshift.Config `mapstructure:"openshift"` +- +- // OpenStackNovaConfig contains user-specified configurations for the OpenStackNova detector +- OpenStackNovaConfig nova.Config `mapstructure:"nova"` +- +- // OracleCloud contains user-specified configurations for the OracleCloud detector +- OracleCloudConfig oraclecloud.Config `mapstructure:"oraclecloud"` +- +- // K8SNode contains user-specified configurations for the K8SNode detector +- K8SNodeConfig k8snode.Config `mapstructure:"k8snode"` +- +- // Kubeadm contains user-specified configurations for the Kubeadm detector +- KubeadmConfig kubeadm.Config `mapstructure:"kubeadm"` +- +- // AkamaiConfig contains user-specified configurations for the akamai detector +- AkamaiConfig akamai.Config `mapstructure:"akamai"` +- +- // ScalewayConfig contains user-specified configurations for the scaleway detector +- ScalewayConfig scaleway.Config `mapstructure:"scaleway"` +- +- // UpcloudConfig contains user-specified configurations for the upcloud detector +- UpcloudConfig upcloud.Config `mapstructure:"upcloud"` +- +- // VultrConfig contains user-specified configurations for the vultr detector +- VultrConfig vultr.Config `mapstructure:"vultr"` + } + + func detectorCreateDefaultConfig() DetectorConfig { + return DetectorConfig{ +- AlibabaECSConfig: alibabaecs.CreateDefaultConfig(), +- EC2Config: ec2.CreateDefaultConfig(), +- ECSConfig: ecs.CreateDefaultConfig(), +- EKSConfig: eks.CreateDefaultConfig(), +- ElasticbeanstalkConfig: elasticbeanstalk.CreateDefaultConfig(), +- LambdaConfig: lambda.CreateDefaultConfig(), +- AzureConfig: azure.CreateDefaultConfig(), +- AksConfig: aks.CreateDefaultConfig(), +- ConsulConfig: consul.CreateDefaultConfig(), +- DigitalOceanConfig: digitalocean.CreateDefaultConfig(), +- DockerConfig: docker.CreateDefaultConfig(), +- GcpConfig: gcp.CreateDefaultConfig(), +- HerokuConfig: heroku.CreateDefaultConfig(), +- HetznerConfig: hetzner.CreateDefaultConfig(), +- SystemConfig: system.CreateDefaultConfig(), +- OpenShiftConfig: openshift.CreateDefaultConfig(), +- OpenStackNovaConfig: nova.CreateDefaultConfig(), +- OracleCloudConfig: oraclecloud.CreateDefaultConfig(), +- K8SNodeConfig: k8snode.CreateDefaultConfig(), +- KubeadmConfig: kubeadm.CreateDefaultConfig(), +- AkamaiConfig: akamai.CreateDefaultConfig(), +- ScalewayConfig: scaleway.CreateDefaultConfig(), +- UpcloudConfig: upcloud.CreateDefaultConfig(), +- VultrConfig: vultr.CreateDefaultConfig(), ++ LambdaConfig: lambda.CreateDefaultConfig(), + } + } + + func (d *DetectorConfig) GetConfigFromType(detectorType internal.DetectorType) internal.DetectorConfig { + switch detectorType { +- case alibabaecs.TypeStr: +- return d.AlibabaECSConfig +- case ec2.TypeStr: +- return d.EC2Config +- case ecs.TypeStr: +- return d.ECSConfig +- case eks.TypeStr: +- return d.EKSConfig +- case elasticbeanstalk.TypeStr: +- return d.ElasticbeanstalkConfig + case lambda.TypeStr: + return d.LambdaConfig +- case azure.TypeStr: +- return d.AzureConfig +- case aks.TypeStr: +- return d.AksConfig +- case consul.TypeStr: +- return d.ConsulConfig +- case digitalocean.TypeStr: +- return d.DigitalOceanConfig +- case docker.TypeStr: +- return d.DockerConfig +- case gcp.TypeStr: +- return d.GcpConfig +- case heroku.TypeStr: +- return d.HerokuConfig +- case hetzner.TypeStr: +- return d.HetznerConfig +- case system.TypeStr: +- return d.SystemConfig +- case openshift.TypeStr: +- return d.OpenShiftConfig +- case nova.TypeStr: +- return d.OpenStackNovaConfig +- case oraclecloud.TypeStr: +- return d.OracleCloudConfig +- case k8snode.TypeStr: +- return d.K8SNodeConfig +- case kubeadm.TypeStr: +- return d.KubeadmConfig +- case akamai.TypeStr: +- return d.AkamaiConfig +- case scaleway.TypeStr: +- return d.ScalewayConfig +- case upcloud.TypeStr: +- return d.UpcloudConfig +- case vultr.TypeStr: +- return d.VultrConfig + default: + return nil + } diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.go new file mode 100644 index 0000000000..6d3912b939 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.go @@ -0,0 +1,217 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// This is a minimal fork of github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor +// Synced from: v0.145.0 +// Only the env and lambda detectors are included — no AWS SDK EC2, no Kubernetes, no Docker, no GCP, no Azure, etc. +// +// To upgrade to a new upstream version, run from this directory: +// ./sync-from-upstream.sh (e.g. ./sync-from-upstream.sh v0.146.0) + +package resourcedetectionprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + +import ( + "context" + "strings" + "sync" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/confighttp" + "go.opentelemetry.io/collector/consumer" + "go.opentelemetry.io/collector/consumer/xconsumer" + "go.opentelemetry.io/collector/processor" + "go.opentelemetry.io/collector/processor/processorhelper" + "go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper" + "go.opentelemetry.io/collector/processor/xprocessor" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/metadata" +) + +var consumerCapabilities = consumer.Capabilities{MutatesData: true} + +type factory struct { + resourceProviderFactory *internal.ResourceProviderFactory + + // providers stores a provider for each named processor that + // may have a different set of detectors configured. + providers map[component.ID]*internal.ResourceProvider + lock sync.Mutex +} + +// NewFactory creates a new factory for ResourceDetection processor. +func NewFactory() processor.Factory { + resourceProviderFactory := internal.NewProviderFactory(map[internal.DetectorType]internal.DetectorFactory{ + env.TypeStr: env.NewDetector, + lambda.TypeStr: lambda.NewDetector, + }) + + f := &factory{ + resourceProviderFactory: resourceProviderFactory, + providers: map[component.ID]*internal.ResourceProvider{}, + } + + return xprocessor.NewFactory( + metadata.Type, + createDefaultConfig, + xprocessor.WithTraces(f.createTracesProcessor, metadata.TracesStability), + xprocessor.WithMetrics(f.createMetricsProcessor, metadata.MetricsStability), + xprocessor.WithLogs(f.createLogsProcessor, metadata.LogsStability), + xprocessor.WithProfiles(f.createProfilesProcessor, metadata.ProfilesStability)) +} + +func createDefaultConfig() component.Config { + return &Config{ + Detectors: []string{env.TypeStr}, + ClientConfig: defaultClientConfig(), + Override: true, + DetectorConfig: detectorCreateDefaultConfig(), + } +} + +func defaultClientConfig() confighttp.ClientConfig { + httpClientSettings := confighttp.NewDefaultClientConfig() + httpClientSettings.Timeout = 5 * time.Second + return httpClientSettings +} + +func (f *factory) createTracesProcessor( + ctx context.Context, + set processor.Settings, + cfg component.Config, + nextConsumer consumer.Traces, +) (processor.Traces, error) { + rdp, err := f.getResourceDetectionProcessor(set, cfg) + if err != nil { + return nil, err + } + + return processorhelper.NewTraces( + ctx, + set, + cfg, + nextConsumer, + rdp.processTraces, + processorhelper.WithCapabilities(consumerCapabilities), + processorhelper.WithStart(rdp.Start), + processorhelper.WithShutdown(rdp.Shutdown), + ) +} + +func (f *factory) createMetricsProcessor( + ctx context.Context, + set processor.Settings, + cfg component.Config, + nextConsumer consumer.Metrics, +) (processor.Metrics, error) { + rdp, err := f.getResourceDetectionProcessor(set, cfg) + if err != nil { + return nil, err + } + + return processorhelper.NewMetrics( + ctx, + set, + cfg, + nextConsumer, + rdp.processMetrics, + processorhelper.WithCapabilities(consumerCapabilities), + processorhelper.WithStart(rdp.Start), + processorhelper.WithShutdown(rdp.Shutdown), + ) +} + +func (f *factory) createLogsProcessor( + ctx context.Context, + set processor.Settings, + cfg component.Config, + nextConsumer consumer.Logs, +) (processor.Logs, error) { + rdp, err := f.getResourceDetectionProcessor(set, cfg) + if err != nil { + return nil, err + } + + return processorhelper.NewLogs( + ctx, + set, + cfg, + nextConsumer, + rdp.processLogs, + processorhelper.WithCapabilities(consumerCapabilities), + processorhelper.WithStart(rdp.Start), + processorhelper.WithShutdown(rdp.Shutdown), + ) +} + +func (f *factory) createProfilesProcessor( + ctx context.Context, + set processor.Settings, + cfg component.Config, + nextConsumer xconsumer.Profiles, +) (xprocessor.Profiles, error) { + rdp, err := f.getResourceDetectionProcessor(set, cfg) + if err != nil { + return nil, err + } + + return xprocessorhelper.NewProfiles( + ctx, + set, + cfg, + nextConsumer, + rdp.processProfiles, + xprocessorhelper.WithCapabilities(consumerCapabilities), + xprocessorhelper.WithStart(rdp.Start), + xprocessorhelper.WithShutdown(rdp.Shutdown), + ) +} + +func (f *factory) getResourceDetectionProcessor( + params processor.Settings, + cfg component.Config, +) (*resourceDetectionProcessor, error) { + oCfg := cfg.(*Config) + provider, err := f.getResourceProvider(params, oCfg.Timeout, oCfg.Detectors, oCfg.DetectorConfig) + if err != nil { + return nil, err + } + + return &resourceDetectionProcessor{ + provider: provider, + override: oCfg.Override, + httpClientSettings: oCfg.ClientConfig, + refreshInterval: oCfg.RefreshInterval, + telemetrySettings: params.TelemetrySettings, + }, nil +} + +func (f *factory) getResourceProvider( + params processor.Settings, + timeout time.Duration, + configuredDetectors []string, + detectorConfigs DetectorConfig, +) (*internal.ResourceProvider, error) { + f.lock.Lock() + defer f.lock.Unlock() + + if provider, ok := f.providers[params.ID]; ok { + return provider, nil + } + + detectorTypes := make([]internal.DetectorType, 0, len(configuredDetectors)) + for _, key := range configuredDetectors { + detectorTypes = append(detectorTypes, internal.DetectorType(strings.TrimSpace(key))) + } + + provider, err := f.resourceProviderFactory.CreateResourceProvider(params, timeout, &detectorConfigs, detectorTypes...) + if err != nil { + return nil, err + } + + f.providers[params.ID] = provider + return provider, nil +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.patch b/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.patch new file mode 100644 index 0000000000..918b91b600 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/factory.patch @@ -0,0 +1,119 @@ +--- a/factory.go ++++ b/factory.go +@@ -1,6 +1,13 @@ + // Copyright The OpenTelemetry Authors + // SPDX-License-Identifier: Apache-2.0 + ++// This is a minimal fork of github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor ++// Synced from: v0.145.0 ++// Only the env and lambda detectors are included — no AWS SDK EC2, no Kubernetes, no Docker, no GCP, no Azure, etc. ++// ++// To upgrade to a new upstream version, run from this directory: ++// ./sync-from-upstream.sh (e.g. ./sync-from-upstream.sh v0.146.0) ++ + package resourcedetectionprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + + import ( +@@ -19,33 +26,9 @@ + "go.opentelemetry.io/collector/processor/xprocessor" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/akamai" +- alibabaecs "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/alibaba/ecs" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ec2" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/ecs" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/eks" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/elasticbeanstalk" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/azure/aks" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/consul" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/digitalocean" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/docker" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/dynatrace" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/gcp" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/heroku" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/hetzner" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/k8snode" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/kubeadm" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/metadata" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openshift" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/openstack/nova" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/oraclecloud" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/scaleway" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/system" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/upcloud" +- "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/vultr" + ) + + var consumerCapabilities = consumer.Capabilities{MutatesData: true} +@@ -54,7 +37,7 @@ + resourceProviderFactory *internal.ResourceProviderFactory + + // providers stores a provider for each named processor that +- // may a different set of detectors configured. ++ // may have a different set of detectors configured. + providers map[component.ID]*internal.ResourceProvider + lock sync.Mutex + } +@@ -62,32 +45,8 @@ + // NewFactory creates a new factory for ResourceDetection processor. + func NewFactory() processor.Factory { + resourceProviderFactory := internal.NewProviderFactory(map[internal.DetectorType]internal.DetectorFactory{ +- akamai.TypeStr: akamai.NewDetector, +- alibabaecs.TypeStr: alibabaecs.NewDetector, +- aks.TypeStr: aks.NewDetector, +- azure.TypeStr: azure.NewDetector, +- consul.TypeStr: consul.NewDetector, +- digitalocean.TypeStr: digitalocean.NewDetector, +- docker.TypeStr: docker.NewDetector, +- ec2.TypeStr: ec2.NewDetector, +- ecs.TypeStr: ecs.NewDetector, +- eks.TypeStr: eks.NewDetector, +- elasticbeanstalk.TypeStr: elasticbeanstalk.NewDetector, +- lambda.TypeStr: lambda.NewDetector, +- env.TypeStr: env.NewDetector, +- gcp.TypeStr: gcp.NewDetector, +- heroku.TypeStr: heroku.NewDetector, +- hetzner.TypeStr: hetzner.NewDetector, +- scaleway.TypeStr: scaleway.NewDetector, +- system.TypeStr: system.NewDetector, +- openshift.TypeStr: openshift.NewDetector, +- nova.TypeStr: nova.NewDetector, +- oraclecloud.TypeStr: oraclecloud.NewDetector, +- k8snode.TypeStr: k8snode.NewDetector, +- kubeadm.TypeStr: kubeadm.NewDetector, +- dynatrace.TypeStr: dynatrace.NewDetector, +- upcloud.TypeStr: upcloud.NewDetector, +- vultr.TypeStr: vultr.NewDetector, ++ env.TypeStr: env.NewDetector, ++ lambda.TypeStr: lambda.NewDetector, + }) + + f := &factory{ +@@ -104,20 +63,12 @@ + xprocessor.WithProfiles(f.createProfilesProcessor, metadata.ProfilesStability)) + } + +-// Type gets the type of the Option config created by this factory. +-func (*factory) Type() component.Type { +- return metadata.Type +-} +- + func createDefaultConfig() component.Config { + return &Config{ +- Detectors: []string{env.TypeStr}, +- ClientConfig: defaultClientConfig(), +- Override: true, +- DetectorConfig: detectorCreateDefaultConfig(), +- RefreshInterval: 0, +- // TODO: Once issue(https://github.com/open-telemetry/opentelemetry-collector/issues/4001) gets resolved, +- // Set the default value of 'hostname_source' here instead of 'system' detector ++ Detectors: []string{env.TypeStr}, ++ ClientConfig: defaultClientConfig(), ++ Override: true, ++ DetectorConfig: detectorCreateDefaultConfig(), + } + } + diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/go.mod b/collector/lambdacomponents/processor/resourcedetectionprocessor/go.mod new file mode 100644 index 0000000000..0fcfd8b66e --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/go.mod @@ -0,0 +1,72 @@ +module github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor + +go 1.24.0 + +require ( + github.com/cenkalti/backoff/v5 v5.0.3 + go.opentelemetry.io/collector/component v1.51.0 + go.opentelemetry.io/collector/config/confighttp v0.145.0 + go.opentelemetry.io/collector/confmap v1.51.0 + go.opentelemetry.io/collector/consumer v1.51.0 + go.opentelemetry.io/collector/consumer/xconsumer v0.145.0 + go.opentelemetry.io/collector/featuregate v1.51.0 + go.opentelemetry.io/collector/pdata v1.51.0 + go.opentelemetry.io/collector/pdata/pprofile v0.145.0 + go.opentelemetry.io/collector/processor v1.51.0 + go.opentelemetry.io/collector/processor/processorhelper v0.145.0 + go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.145.0 + go.opentelemetry.io/collector/processor/xprocessor v0.145.0 + go.opentelemetry.io/otel v1.40.0 + go.uber.org/zap v1.27.1 +) + +require ( + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect + github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-viper/mapstructure/v2 v2.5.0 // indirect + github.com/gobwas/glob v0.2.3 // indirect + github.com/golang/snappy v1.0.0 // indirect + github.com/google/go-tpm v0.9.8 // indirect + github.com/hashicorp/go-version v1.8.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.18.3 // indirect + github.com/knadh/koanf/maps v0.1.2 // indirect + github.com/knadh/koanf/providers/confmap v1.0.0 // indirect + github.com/knadh/koanf/v2 v2.3.2 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/pierrec/lz4/v4 v4.1.23 // indirect + github.com/rs/cors v1.11.1 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/client v1.51.0 // indirect + go.opentelemetry.io/collector/config/configauth v1.51.0 // indirect + go.opentelemetry.io/collector/config/configcompression v1.51.0 // indirect + go.opentelemetry.io/collector/config/configmiddleware v1.51.0 // indirect + go.opentelemetry.io/collector/config/confignet v1.51.0 // indirect + go.opentelemetry.io/collector/config/configopaque v1.51.0 // indirect + go.opentelemetry.io/collector/config/configoptional v1.51.0 // indirect + go.opentelemetry.io/collector/config/configtls v1.51.0 // indirect + go.opentelemetry.io/collector/confmap/xconfmap v0.145.0 // indirect + go.opentelemetry.io/collector/extension/extensionauth v1.51.0 // indirect + go.opentelemetry.io/collector/extension/extensionmiddleware v0.145.0 // indirect + go.opentelemetry.io/collector/internal/componentalias v0.145.0 // indirect + go.opentelemetry.io/collector/pipeline v1.51.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect + go.opentelemetry.io/otel/metric v1.40.0 // indirect + go.opentelemetry.io/otel/trace v1.40.0 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/net v0.49.0 // indirect + golang.org/x/sys v0.40.0 // indirect + golang.org/x/text v0.33.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b // indirect + google.golang.org/grpc v1.78.0 // indirect + google.golang.org/protobuf v1.36.11 // indirect +) diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/go.sum b/collector/lambdacomponents/processor/resourcedetectionprocessor/go.sum new file mode 100644 index 0000000000..2c241691ea --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/go.sum @@ -0,0 +1,190 @@ +github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM= +github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f h1:RJ+BDPLSHQO7cSjKBqjPJSbi1qfk9WcsjQDtZiw3dZw= +github.com/foxboron/go-tpm-keyfiles v0.0.0-20251226215517-609e4778396f/go.mod h1:VHbbch/X4roIY22jL1s3qRbZhCiRIgUAF/PdSUcx2io= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= +github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= +github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/go-tpm v0.9.8 h1:slArAR9Ft+1ybZu0lBwpSmpwhRXaa85hWtMinMyRAWo= +github.com/google/go-tpm v0.9.8/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY= +github.com/google/go-tpm-tools v0.4.7 h1:J3ycC8umYxM9A4eF73EofRZu4BxY0jjQnUnkhIBbvws= +github.com/google/go-tpm-tools v0.4.7/go.mod h1:gSyXTZHe3fgbzb6WEGd90QucmsnT1SRdlye82gH8QjQ= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/hashicorp/go-version v1.8.0 h1:KAkNb1HAiZd1ukkxDFGmokVZe1Xy9HG6NUp+bPle2i4= +github.com/hashicorp/go-version v1.8.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= +github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= +github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo= +github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= +github.com/knadh/koanf/providers/confmap v1.0.0 h1:mHKLJTE7iXEys6deO5p6olAiZdG5zwp8Aebir+/EaRE= +github.com/knadh/koanf/providers/confmap v1.0.0/go.mod h1:txHYHiI2hAtF0/0sCmcuol4IDcuQbKTybiB1nOcUo1A= +github.com/knadh/koanf/v2 v2.3.2 h1:Ee6tuzQYFwcZXQpc2MiVeC6qHMandf5SMUJJNoFp/c4= +github.com/knadh/koanf/v2 v2.3.2/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee h1:W5t00kpgFdJifH4BDsTlE89Zl93FEloxaWZfGcifgq8= +github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/pierrec/lz4/v4 v4.1.23 h1:oJE7T90aYBGtFNrI8+KbETnPymobAhzRrR8Mu8n1yfU= +github.com/pierrec/lz4/v4 v4.1.23/go.mod h1:EoQMVJgeeEOMsCqCzqFm2O0cJvljX2nGZjcRIPL34O4= +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/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= +github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= +go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= +go.opentelemetry.io/collector/client v1.51.0 h1:7FaC2gglA7OWol/wMMSpoE1nFY6oewIIyf3nqVzO8m8= +go.opentelemetry.io/collector/client v1.51.0/go.mod h1:lx+VIlIm1/qaUeWs4ozeV/Q9y9rJQGwQo+dnk+We5TQ= +go.opentelemetry.io/collector/component v1.51.0 h1:btNW76MCRmpsk0ARRT5wspDXF9tvdaLd3uBtYXIiQn0= +go.opentelemetry.io/collector/component v1.51.0/go.mod h1:Zlgwh4yTLDhJglOXqiyXZ7paepTvvoijfFjLqOr/Qww= +go.opentelemetry.io/collector/component/componentstatus v0.145.0 h1:EwUZfSaagdpRXnlrb0TqReJXXW2p9HWBU5YiIeXPCAE= +go.opentelemetry.io/collector/component/componentstatus v0.145.0/go.mod h1:OiYb8rT4FtSJPFSGCKYvOaajdueDUTJZncixGrmy5aM= +go.opentelemetry.io/collector/component/componenttest v0.145.0 h1:ryhRrXqQybGMhz7A7t32NC8BXAFcX2o1RetgPM7vw88= +go.opentelemetry.io/collector/component/componenttest v0.145.0/go.mod h1:5uStrhUdZ0Fw3se00CPmVaRtW8o9N8kKiY76OSCWFjQ= +go.opentelemetry.io/collector/config/configauth v1.51.0 h1:89pjoUxbmUGURr8PyaxowuIlISrBkwJUbr/JhCpL4EI= +go.opentelemetry.io/collector/config/configauth v1.51.0/go.mod h1:RXorbqKrG63mBLglhvH+A1Gn9R74JH/agPC31goV33Y= +go.opentelemetry.io/collector/config/configcompression v1.51.0 h1:kqLzehPPinndkt2M5axkzxOKSgHZwVTrcIfuTQ9itpw= +go.opentelemetry.io/collector/config/configcompression v1.51.0/go.mod h1:ZlnKaXFYL3HVMUNWVAo/YOLYoxNZo7h8SrQp3l7GV00= +go.opentelemetry.io/collector/config/confighttp v0.145.0 h1:H7EI4JanJsf1bg5A8pDP7XPSeiLjlqiOvGtqX1yj2JI= +go.opentelemetry.io/collector/config/confighttp v0.145.0/go.mod h1:/kPeMrfsnzdXQwxC6q8sjedesX+FQSupJe79BnFOUWI= +go.opentelemetry.io/collector/config/configmiddleware v1.51.0 h1:AMZP9+LgFoAdfNTkx+qfFPqBiQY3k8yCigjv6HUbGe0= +go.opentelemetry.io/collector/config/configmiddleware v1.51.0/go.mod h1:37G0+KEiJf0ZYw4q2euslxkx1WaKun//KV8vaw1HkRA= +go.opentelemetry.io/collector/config/confignet v1.51.0 h1:gEIPVPbboYi/ESt2WyfZBPjtrM2zPnKJX2shmNUbtok= +go.opentelemetry.io/collector/config/confignet v1.51.0/go.mod h1:4jJWdoe1MmpqxMzxrIILcS5FK2JPocXYZGUvv5ZQVKE= +go.opentelemetry.io/collector/config/configopaque v1.51.0 h1:z8Q72mBMQ6P4me+umu1kCC3sqzX+zQ7OJju5oQcdZv8= +go.opentelemetry.io/collector/config/configopaque v1.51.0/go.mod h1:w77VAty/J8dxrSyq0ObbvQxh+xh0tVg+SQqFQ7SQRzM= +go.opentelemetry.io/collector/config/configoptional v1.51.0 h1:kVD8B3JF0Hd5LrRhHIKXAcHeTbQk9cxa0nD06IgJ+Gs= +go.opentelemetry.io/collector/config/configoptional v1.51.0/go.mod h1:nBG71pzrklmiPIp1XPQiO3RzlbLIolUlFrW30q1UXzM= +go.opentelemetry.io/collector/config/configtls v1.51.0 h1:fkZ3o3i6A7MCQBYCid2ZBYgaE3bYWpr3EognX09C1Tc= +go.opentelemetry.io/collector/config/configtls v1.51.0/go.mod h1:d2yeGb0Bt0WA9cL9SpC1nfhu5Qfiz+PhtQoecs+Kong= +go.opentelemetry.io/collector/confmap v1.51.0 h1:C9YlMNkIgzuauLpUz2F7DLlWwqAmkQKNcKj1XATVWuE= +go.opentelemetry.io/collector/confmap v1.51.0/go.mod h1:uWi4b9lHfvEC2poJ2I2vXwGUREVEQTcdUguOpfqdcHM= +go.opentelemetry.io/collector/confmap/xconfmap v0.145.0 h1:ngbyfh4+SKlA+osgsak3AxUNPxVxaJTmA0Sl7VfJzwY= +go.opentelemetry.io/collector/confmap/xconfmap v0.145.0/go.mod h1:zTSK+c76NAy/tI1R3xfZjdoI04D9EYDnzAHQQwl6AmA= +go.opentelemetry.io/collector/consumer v1.51.0 h1:Ex1x/k9VEEA2DOgt/eSc2Z9KTp0I6xBSruLmrYFfIFY= +go.opentelemetry.io/collector/consumer v1.51.0/go.mod h1:Erk6qdfVj+24QTrGCpurcrF+qdUlHkb4dgMy5wJxLvY= +go.opentelemetry.io/collector/consumer/consumertest v0.145.0 h1:3+uMwuMHoXMAU+Z6mwCRA3AxWeL7SujcAQwqqHJ1gCc= +go.opentelemetry.io/collector/consumer/consumertest v0.145.0/go.mod h1:IFc/FeaIHQClb8KK0aVn0tFDNMc+/MmfQ+aBT1cJNeo= +go.opentelemetry.io/collector/consumer/xconsumer v0.145.0 h1:9w7KKv9lVJoHvMLC6SUJHenU/KySdEgFJXbB4JQOEsk= +go.opentelemetry.io/collector/consumer/xconsumer v0.145.0/go.mod h1:SryDCLP2ZaFeZJtA2CSksJ0XvjH8k3LmlfXvy/kC7Wc= +go.opentelemetry.io/collector/extension v1.51.0 h1:NWYhvGRHHK+g1WdHqVdFuKsDtIfYoudfJ0dC6TbIfWE= +go.opentelemetry.io/collector/extension v1.51.0/go.mod h1:y5Z0djLtw0QZb8CJQv8JpeObx9bfAnw3yeu1yoKhyaA= +go.opentelemetry.io/collector/extension/extensionauth v1.51.0 h1:ox3nzKx8a/6Rf2DiuK6qUDIYbXK4frW0INZoPTFY7Xw= +go.opentelemetry.io/collector/extension/extensionauth v1.51.0/go.mod h1:alIyB3zBUOvIEn/DaAdLMFWtz9Zw4UYt1iHO0lMy5XU= +go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.145.0 h1:irVSyUVTp71InKizZhoTe0oDoj4vAvVsYonybfRVfQc= +go.opentelemetry.io/collector/extension/extensionauth/extensionauthtest v0.145.0/go.mod h1:1jshMRyK6EvdJxlCf2aCiRHVlVJPdNM40isETkx3jX4= +go.opentelemetry.io/collector/extension/extensionmiddleware v0.145.0 h1:2pfnfiDEM2iHEhYj0EbkwhKvNJFfTfAx5zWZeO6PyoQ= +go.opentelemetry.io/collector/extension/extensionmiddleware v0.145.0/go.mod h1:CyKahcem/CnsjFSpWXOCWk0OaB7fraO+bSHar3uAsDY= +go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.145.0 h1:Cir87cjIiRjtMxiF833tTxVuZvD3diXyBpsNlouiLB8= +go.opentelemetry.io/collector/extension/extensionmiddleware/extensionmiddlewaretest v0.145.0/go.mod h1:xqCp8tnkBYhjuL8WYEaC721cAFWJjPz8yaIIQ8+j5os= +go.opentelemetry.io/collector/featuregate v1.51.0 h1:dxJuv/3T84dhNKp7fz5+8srHz1dhquGzDpLW4OZTFBw= +go.opentelemetry.io/collector/featuregate v1.51.0/go.mod h1:/1bclXgP91pISaEeNulRxzzmzMTm4I5Xih2SnI4HRSo= +go.opentelemetry.io/collector/internal/componentalias v0.145.0 h1:A9V5IiETzz8FCtjxjRM5gf7RE3sOtA1h8phmpQjXTZ4= +go.opentelemetry.io/collector/internal/componentalias v0.145.0/go.mod h1:sEKEAwAn45ZiXRk3T/vbkvetw14tIRd0CJIxcEx9SsQ= +go.opentelemetry.io/collector/internal/testutil v0.145.0 h1:H/KL0GH3kGqSMKxZvnQ0B0CulfO9xdTg4DZf28uV7fY= +go.opentelemetry.io/collector/internal/testutil v0.145.0/go.mod h1:YAD9EAkwh/l5asZNbEBEUCqEjoL1OKMjAMoPjPqH76c= +go.opentelemetry.io/collector/pdata v1.51.0 h1:DnDhSEuDXNdzGRB7f6oOfXpbDApwBX3tY+3K69oUrDA= +go.opentelemetry.io/collector/pdata v1.51.0/go.mod h1:GoX1bjKDR++mgFKdT7Hynv9+mdgQ1DDXbjs7/Ww209Q= +go.opentelemetry.io/collector/pdata/pprofile v0.145.0 h1:ASMKpoqokf8HhzjoeMKZf0K6UXLhufVwNXH0sSuUn5w= +go.opentelemetry.io/collector/pdata/pprofile v0.145.0/go.mod h1:a60GC7wQPhLAixWzKbbP51QLwwc+J0Cmp4SurOlhGUk= +go.opentelemetry.io/collector/pdata/testdata v0.145.0 h1:iFsxsCMtE3lnAc/5kZbhZHpRv1OMmM+O5ry46xdQHbg= +go.opentelemetry.io/collector/pdata/testdata v0.145.0/go.mod h1:0y2ERArdzqmYdJHdKLKue+AUubSEGlwK49F+23+Mbic= +go.opentelemetry.io/collector/pipeline v1.51.0 h1:GZBNW+aaOE+zufGzAkXy0OI7n1cqepEa5J+beaOpS2k= +go.opentelemetry.io/collector/pipeline v1.51.0/go.mod h1:xUrAqiebzYbrgxyoXSkk6/Y3oi5Sy3im2iCA51LwUAI= +go.opentelemetry.io/collector/processor v1.51.0 h1:PKpCzkLQmqaW08TOVh/zM0qx07Ihq+DR5J/OBkPiL9o= +go.opentelemetry.io/collector/processor v1.51.0/go.mod h1:rtIPFS+EFRAkG+CSwtjxs2IsIkuZStObvALeueD02XI= +go.opentelemetry.io/collector/processor/processorhelper v0.145.0 h1:vXdv6lHz20Tm3ZEsg0i6jPZJBQgy9kzk/PuqWhHWiiM= +go.opentelemetry.io/collector/processor/processorhelper v0.145.0/go.mod h1:3Ecpe5jHRHGf24EvJHeJ/ekK/a1DLByyq0CSUxjjURg= +go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.145.0 h1:sj71PeiUvjwJpgPCA89DBggglUnMnHnVDj1p5mqopbU= +go.opentelemetry.io/collector/processor/processorhelper/xprocessorhelper v0.145.0/go.mod h1:eziJnPjzFuVntzgDuZTJhckjiavWYSoJG+kID45wJHU= +go.opentelemetry.io/collector/processor/processortest v0.145.0 h1:RDGBmyZnHk7XVK/EdLt/8iPWj+QLStbbVi1nFTNR01s= +go.opentelemetry.io/collector/processor/processortest v0.145.0/go.mod h1:WAvxAzSojkdoZB915Z1lsVHCPDJBb2fepjJBjenrzjg= +go.opentelemetry.io/collector/processor/xprocessor v0.145.0 h1:DaIE7MxRlg0OL1o2P0GQZtmZeExAmVso3qWv8S0RLps= +go.opentelemetry.io/collector/processor/xprocessor v0.145.0/go.mod h1:kUwRyKBU/kjCmXodd+0z7CpvcP0A9G9/QL+MaJt4U2o= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg= +go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= +go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= +go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g= +go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc= +go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18= +go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE= +go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8= +go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew= +go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= +go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= +go.opentelemetry.io/proto/slim/otlp v1.9.0 h1:fPVMv8tP3TrsqlkH1HWYUpbCY9cAIemx184VGkS6vlE= +go.opentelemetry.io/proto/slim/otlp v1.9.0/go.mod h1:xXdeJJ90Gqyll+orzUkY4bOd2HECo5JofeoLpymVqdI= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0 h1:o13nadWDNkH/quoDomDUClnQBpdQQ2Qqv0lQBjIXjE8= +go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.2.0/go.mod h1:Gyb6Xe7FTi/6xBHwMmngGoHqL0w29Y4eW8TGFzpefGA= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0 h1:EiUYvtwu6PMrMHVjcPfnsG3v+ajPkbUeH+IL93+QYyk= +go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.2.0/go.mod h1:mUUHKFiN2SST3AhJ8XhJxEoeVW12oqfXog0Bo8W3Ec4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= +golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b h1:Mv8VFug0MP9e5vUxfBcE3vUkV6CImK3cMNMIDFjmzxU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251222181119-0a764e51fe1b/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ= +google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc= +google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U= +google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= +google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/config.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/config.go new file mode 100644 index 0000000000..21268a7de0 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/config.go @@ -0,0 +1,18 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package lambda // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" + +import ( + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata" +) + +type Config struct { + ResourceAttributes metadata.ResourceAttributesConfig `mapstructure:"resource_attributes"` +} + +func CreateDefaultConfig() Config { + return Config{ + ResourceAttributes: metadata.DefaultResourceAttributesConfig(), + } +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go new file mode 100644 index 0000000000..e9b268ff2a --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go @@ -0,0 +1,71 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/confmap" +) + +// ResourceAttributeConfig provides common config for a particular resource attribute. +type ResourceAttributeConfig struct { + Enabled bool `mapstructure:"enabled"` + + enabledSetByUser bool +} + +func (rac *ResourceAttributeConfig) Unmarshal(parser *confmap.Conf) error { + if parser == nil { + return nil + } + err := parser.Unmarshal(rac) + if err != nil { + return err + } + rac.enabledSetByUser = parser.IsSet("enabled") + return nil +} + +// ResourceAttributesConfig provides config for resourcedetectionprocessor/lambda resource attributes. +type ResourceAttributesConfig struct { + AwsLogGroupNames ResourceAttributeConfig `mapstructure:"aws.log.group.names"` + AwsLogStreamNames ResourceAttributeConfig `mapstructure:"aws.log.stream.names"` + CloudPlatform ResourceAttributeConfig `mapstructure:"cloud.platform"` + CloudProvider ResourceAttributeConfig `mapstructure:"cloud.provider"` + CloudRegion ResourceAttributeConfig `mapstructure:"cloud.region"` + FaasInstance ResourceAttributeConfig `mapstructure:"faas.instance"` + FaasMaxMemory ResourceAttributeConfig `mapstructure:"faas.max_memory"` + FaasName ResourceAttributeConfig `mapstructure:"faas.name"` + FaasVersion ResourceAttributeConfig `mapstructure:"faas.version"` +} + +func DefaultResourceAttributesConfig() ResourceAttributesConfig { + return ResourceAttributesConfig{ + AwsLogGroupNames: ResourceAttributeConfig{ + Enabled: true, + }, + AwsLogStreamNames: ResourceAttributeConfig{ + Enabled: true, + }, + CloudPlatform: ResourceAttributeConfig{ + Enabled: true, + }, + CloudProvider: ResourceAttributeConfig{ + Enabled: true, + }, + CloudRegion: ResourceAttributeConfig{ + Enabled: true, + }, + FaasInstance: ResourceAttributeConfig{ + Enabled: true, + }, + FaasMaxMemory: ResourceAttributeConfig{ + Enabled: true, + }, + FaasName: ResourceAttributeConfig{ + Enabled: true, + }, + FaasVersion: ResourceAttributeConfig{ + Enabled: true, + }, + } +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_resource.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_resource.go new file mode 100644 index 0000000000..c1b38afe47 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_resource.go @@ -0,0 +1,92 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" +) + +// ResourceBuilder is a helper struct to build resources predefined in metadata.yaml. +// The ResourceBuilder is not thread-safe and must not to be used in multiple goroutines. +type ResourceBuilder struct { + config ResourceAttributesConfig + res pcommon.Resource +} + +// NewResourceBuilder creates a new ResourceBuilder. This method should be called on the start of the application. +func NewResourceBuilder(rac ResourceAttributesConfig) *ResourceBuilder { + return &ResourceBuilder{ + config: rac, + res: pcommon.NewResource(), + } +} + +// SetAwsLogGroupNames sets provided value as "aws.log.group.names" attribute. +func (rb *ResourceBuilder) SetAwsLogGroupNames(val []any) { + if rb.config.AwsLogGroupNames.Enabled { + rb.res.Attributes().PutEmptySlice("aws.log.group.names").FromRaw(val) + } +} + +// SetAwsLogStreamNames sets provided value as "aws.log.stream.names" attribute. +func (rb *ResourceBuilder) SetAwsLogStreamNames(val []any) { + if rb.config.AwsLogStreamNames.Enabled { + rb.res.Attributes().PutEmptySlice("aws.log.stream.names").FromRaw(val) + } +} + +// SetCloudPlatform sets provided value as "cloud.platform" attribute. +func (rb *ResourceBuilder) SetCloudPlatform(val string) { + if rb.config.CloudPlatform.Enabled { + rb.res.Attributes().PutStr("cloud.platform", val) + } +} + +// SetCloudProvider sets provided value as "cloud.provider" attribute. +func (rb *ResourceBuilder) SetCloudProvider(val string) { + if rb.config.CloudProvider.Enabled { + rb.res.Attributes().PutStr("cloud.provider", val) + } +} + +// SetCloudRegion sets provided value as "cloud.region" attribute. +func (rb *ResourceBuilder) SetCloudRegion(val string) { + if rb.config.CloudRegion.Enabled { + rb.res.Attributes().PutStr("cloud.region", val) + } +} + +// SetFaasInstance sets provided value as "faas.instance" attribute. +func (rb *ResourceBuilder) SetFaasInstance(val string) { + if rb.config.FaasInstance.Enabled { + rb.res.Attributes().PutStr("faas.instance", val) + } +} + +// SetFaasMaxMemory sets provided value as "faas.max_memory" attribute. +func (rb *ResourceBuilder) SetFaasMaxMemory(val string) { + if rb.config.FaasMaxMemory.Enabled { + rb.res.Attributes().PutStr("faas.max_memory", val) + } +} + +// SetFaasName sets provided value as "faas.name" attribute. +func (rb *ResourceBuilder) SetFaasName(val string) { + if rb.config.FaasName.Enabled { + rb.res.Attributes().PutStr("faas.name", val) + } +} + +// SetFaasVersion sets provided value as "faas.version" attribute. +func (rb *ResourceBuilder) SetFaasVersion(val string) { + if rb.config.FaasVersion.Enabled { + rb.res.Attributes().PutStr("faas.version", val) + } +} + +// Emit returns the built resource and resets the internal builder state. +func (rb *ResourceBuilder) Emit() pcommon.Resource { + r := rb.res + rb.res = pcommon.NewResource() + return r +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go new file mode 100644 index 0000000000..b00fea57c6 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go @@ -0,0 +1,84 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package lambda // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda" + +import ( + "context" + "os" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/processor" + conventions "go.opentelemetry.io/otel/semconv/v1.38.0" + "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata" +) + +const ( + // TypeStr is type of detector. + TypeStr = "lambda" + + // Environment variables that are set when running on AWS Lambda. + // https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime + awsRegionEnvVar = "AWS_REGION" + awsLambdaFunctionNameEnvVar = "AWS_LAMBDA_FUNCTION_NAME" + awsLambdaFunctionVersionEnvVar = "AWS_LAMBDA_FUNCTION_VERSION" + awsLambdaFunctionMemorySizeEnvVar = "AWS_LAMBDA_FUNCTION_MEMORY_SIZE" + awsLambdaLogGroupNameEnvVar = "AWS_LAMBDA_LOG_GROUP_NAME" + awsLambdaLogStreamNameEnvVar = "AWS_LAMBDA_LOG_STREAM_NAME" +) + +var _ internal.Detector = (*detector)(nil) + +type detector struct { + logger *zap.Logger + rb *metadata.ResourceBuilder +} + +func NewDetector(set processor.Settings, dcfg internal.DetectorConfig) (internal.Detector, error) { + cfg := dcfg.(Config) + return &detector{logger: set.Logger, rb: metadata.NewResourceBuilder(cfg.ResourceAttributes)}, nil +} + +func (d *detector) Detect(_ context.Context) (resource pcommon.Resource, schemaURL string, err error) { + functionName, ok := os.LookupEnv(awsLambdaFunctionNameEnvVar) + if !ok || functionName == "" { + d.logger.Debug("Unable to identify AWS Lambda environment", zap.Error(err)) + return pcommon.NewResource(), "", err + } + + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/cloud.md + d.rb.SetCloudProvider(conventions.CloudProviderAWS.Value.AsString()) + d.rb.SetCloudPlatform(conventions.CloudPlatformAWSLambda.Value.AsString()) + if value, ok := os.LookupEnv(awsRegionEnvVar); ok { + d.rb.SetCloudRegion(value) + } + + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/faas.md + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/instrumentation/aws-lambda.md#resource-detector + d.rb.SetFaasName(functionName) + if value, ok := os.LookupEnv(awsLambdaFunctionVersionEnvVar); ok { + d.rb.SetFaasVersion(value) + } + + // Note: The FaaS spec (https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/faas.md) + // recommends setting faas.instance to the full log stream name for AWS Lambda. + if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { + d.rb.SetFaasInstance(value) + } + if value, ok := os.LookupEnv(awsLambdaFunctionMemorySizeEnvVar); ok { + d.rb.SetFaasMaxMemory(value) + } + + // https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/resource/semantic_conventions/cloud_provider/aws/logs.md + if value, ok := os.LookupEnv(awsLambdaLogGroupNameEnvVar); ok { + d.rb.SetAwsLogGroupNames([]any{value}) + } + if value, ok := os.LookupEnv(awsLambdaLogStreamNameEnvVar); ok { + d.rb.SetAwsLogStreamNames([]any{value}) + } + + return d.rb.Emit(), conventions.SchemaURL, nil +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/context.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/context.go new file mode 100644 index 0000000000..a5e0025fb2 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/context.go @@ -0,0 +1,34 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + +import ( + "context" + "errors" + "net/http" +) + +type contextKey int + +const clientContextKey contextKey = iota + +// ContextWithClient returns a new context.Context with the provided *http.Client stored as a value. +func ContextWithClient(ctx context.Context, client *http.Client) context.Context { + return context.WithValue(ctx, clientContextKey, client) +} + +// ClientFromContext attempts to extract an *http.Client from the provided context.Context. +func ClientFromContext(ctx context.Context) (*http.Client, error) { + v := ctx.Value(clientContextKey) + if v == nil { + return nil, errors.New("no http.Client in context") + } + var c *http.Client + var ok bool + if c, ok = v.(*http.Client); !ok { + return nil, errors.New("invalid value found in context") + } + + return c, nil +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/env/env.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/env/env.go new file mode 100644 index 0000000000..8143618c55 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/env/env.go @@ -0,0 +1,99 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package env provides a detector that loads resource information from +// the OTEL_RESOURCE environment variable. A list of labels of the form +// `=,=,...` is accepted. Domain names and +// paths are accepted as label keys. +package env // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/env" + +import ( + "context" + "fmt" + "net/url" + "os" + "regexp" + "strings" + + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/processor" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +) + +// TypeStr is type of detector. +const TypeStr = "env" + +// Environment variable used by "env" to decode a resource. +const envVar = "OTEL_RESOURCE_ATTRIBUTES" + +// Deprecated environment variable used by "env" to decode a resource. +// Specification states to use OTEL_RESOURCE_ATTRIBUTES however to avoid +// breaking existing usage, maintain support for OTEL_RESOURCE +// https://github.com/open-telemetry/opentelemetry-specification/blob/1afab39e5658f807315abf2f3256809293bfd421/specification/resource/sdk.md#specifying-resource-information-via-an-environment-variable +const deprecatedEnvVar = "OTEL_RESOURCE" + +var _ internal.Detector = (*Detector)(nil) + +type Detector struct{} + +func NewDetector(processor.Settings, internal.DetectorConfig) (internal.Detector, error) { + return &Detector{}, nil +} + +func (*Detector) Detect(context.Context) (resource pcommon.Resource, schemaURL string, err error) { + res := pcommon.NewResource() + + labels := strings.TrimSpace(os.Getenv(envVar)) + if labels == "" { + labels = strings.TrimSpace(os.Getenv(deprecatedEnvVar)) + if labels == "" { + return res, "", nil + } + } + + err = initializeAttributeMap(res.Attributes(), labels) + if err != nil { + res.Attributes().Clear() + return res, "", err + } + + return res, "", nil +} + +// labelRegex matches any key=value pair including a trailing comma or the end of the +// string. Captures the trimmed key & value parts, and ignores any superfluous spaces. +var labelRegex = regexp.MustCompile(`\s*([[:ascii:]]{1,256}?)\s*=\s*([[:ascii:]]{0,256}?)\s*(?:,|$)`) + +func initializeAttributeMap(am pcommon.Map, s string) error { + matches := labelRegex.FindAllStringSubmatchIndex(s, -1) + for len(matches) == 0 { + return fmt.Errorf("invalid resource format: %q", s) + } + + prevIndex := 0 + for _, match := range matches { + // if there is any text between matches, raise an error + if prevIndex != match[0] { + return fmt.Errorf("invalid resource format, invalid text: %q", s[prevIndex:match[0]]) + } + + key := s[match[2]:match[3]] + value := s[match[4]:match[5]] + + var err error + if value, err = url.QueryUnescape(value); err != nil { + return fmt.Errorf("invalid resource format in attribute: %q, err: %w", s[match[0]:match[1]], err) + } + am.PutStr(key, value) + + prevIndex = match[1] + } + + // if there is any text after the last match, raise an error + if matches[len(matches)-1][1] != len(s) { + return fmt.Errorf("invalid resource format, invalid text: %q", s[matches[len(matches)-1][1]:]) + } + + return nil +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_feature_gates.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_feature_gates.go new file mode 100644 index 0000000000..3b7c6d7c92 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_feature_gates.go @@ -0,0 +1,24 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/featuregate" +) + +var ProcessorResourcedetectionPropagateerrorsFeatureGate = featuregate.GlobalRegistry().MustRegister( + "processor.resourcedetection.propagateerrors", + featuregate.StageBeta, + featuregate.WithRegisterDescription("When enabled, allows errors returned from resource detectors to propagate in the Start() method and stop the collector."), + featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/issues/37961"), + featuregate.WithRegisterFromVersion("v0.121.0"), +) + +var ProcessorResourcedetectionRemoveGCPFaasIDFeatureGate = featuregate.GlobalRegistry().MustRegister( + "processor.resourcedetection.removeGCPFaasID", + featuregate.StageStable, + featuregate.WithRegisterDescription("Remove faas.id from the GCP detector. Use faas.instance instead."), + featuregate.WithRegisterReferenceURL("https://github.com/open-telemetry/opentelemetry-collector-contrib/pull/26486"), + featuregate.WithRegisterFromVersion("v0.87.0"), + featuregate.WithRegisterToVersion("v0.145.0"), +) diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_status.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_status.go new file mode 100644 index 0000000000..ee0a493131 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/metadata/generated_status.go @@ -0,0 +1,19 @@ +// Code generated by mdatagen. DO NOT EDIT. + +package metadata + +import ( + "go.opentelemetry.io/collector/component" +) + +var ( + Type = component.MustNewType("resourcedetection") + ScopeName = "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" +) + +const ( + ProfilesStability = component.StabilityLevelDevelopment + TracesStability = component.StabilityLevelBeta + MetricsStability = component.StabilityLevelBeta + LogsStability = component.StabilityLevelBeta +) diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/resourcedetection.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/resourcedetection.go new file mode 100644 index 0000000000..198fefaaf4 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/internal/resourcedetection.go @@ -0,0 +1,317 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +// Package internal contains an interface for detecting resource information, +// and a provider to merge the resources returned by a slice of custom detectors. +package internal // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" + +import ( + "context" + "errors" + "fmt" + "net/http" + "sync" + "sync/atomic" + "time" + + backoff "github.com/cenkalti/backoff/v5" + "go.opentelemetry.io/collector/pdata/pcommon" + "go.opentelemetry.io/collector/processor" + "go.uber.org/zap" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal/metadata" +) + +type DetectorType string + +type Detector interface { + Detect(ctx context.Context) (resource pcommon.Resource, schemaURL string, err error) +} + +type DetectorConfig any + +type ResourceDetectorConfig interface { + GetConfigFromType(DetectorType) DetectorConfig +} + +type DetectorFactory func(processor.Settings, DetectorConfig) (Detector, error) + +type ResourceProviderFactory struct { + // detectors holds all possible detector types. + detectors map[DetectorType]DetectorFactory +} + +func NewProviderFactory(detectors map[DetectorType]DetectorFactory) *ResourceProviderFactory { + return &ResourceProviderFactory{detectors: detectors} +} + +func (f *ResourceProviderFactory) CreateResourceProvider( + params processor.Settings, + timeout time.Duration, + detectorConfigs ResourceDetectorConfig, + detectorTypes ...DetectorType, +) (*ResourceProvider, error) { + detectors, err := f.getDetectors(params, detectorConfigs, detectorTypes) + if err != nil { + return nil, err + } + + provider := NewResourceProvider(params.Logger, timeout, detectors...) + return provider, nil +} + +func (f *ResourceProviderFactory) getDetectors(params processor.Settings, detectorConfigs ResourceDetectorConfig, detectorTypes []DetectorType) ([]Detector, error) { + detectors := make([]Detector, 0, len(detectorTypes)) + for _, detectorType := range detectorTypes { + detectorFactory, ok := f.detectors[detectorType] + if !ok { + return nil, fmt.Errorf("invalid detector key: %v", detectorType) + } + + detector, err := detectorFactory(params, detectorConfigs.GetConfigFromType(detectorType)) + if err != nil { + return nil, fmt.Errorf("failed creating detector type %q: %w", detectorType, err) + } + + detectors = append(detectors, detector) + } + + return detectors, nil +} + +type ResourceProvider struct { + logger *zap.Logger + timeout time.Duration + detectors []Detector + detectedResource atomic.Pointer[resourceResult] + + // Refresh loop control + refreshInterval time.Duration + stopCh chan struct{} + wg sync.WaitGroup +} + +type resourceResult struct { + resource pcommon.Resource + schemaURL string + err error +} + +func NewResourceProvider(logger *zap.Logger, timeout time.Duration, detectors ...Detector) *ResourceProvider { + return &ResourceProvider{ + logger: logger, + timeout: timeout, + detectors: detectors, + refreshInterval: 0, // No periodic refresh by default + } +} + +func (p *ResourceProvider) Get(_ context.Context, _ *http.Client) (pcommon.Resource, string, error) { + result := p.detectedResource.Load() + if result != nil { + return result.resource, result.schemaURL, result.err + } + return pcommon.NewResource(), "", nil +} + +// Refresh recomputes the resource, replacing any previous result. +func (p *ResourceProvider) Refresh(ctx context.Context, client *http.Client) error { + ctx, cancel := context.WithTimeout(ctx, client.Timeout) + defer cancel() + + res, schemaURL, err := p.detectResource(ctx) + prev := p.detectedResource.Load() + + // Check if we have a previous successful snapshot + hadPrevSuccess := prev != nil && prev.err == nil && !IsEmptyResource(prev.resource) + + // Keep the last good snapshot if the refresh errored. + // Note: An empty resource with no error is considered a success (e.g., detector determined + // it's not running on that cloud provider), so we accept it rather than keeping stale data. + if hadPrevSuccess && err != nil { + p.logger.Warn("resource refresh failed; keeping previous snapshot", zap.Error(err)) + // Return nil error since we're successfully keeping the cached resource + return nil + } + + // Accept the new snapshot (even if empty, as long as there was no error). + p.detectedResource.Store(&resourceResult{ + resource: res, + schemaURL: schemaURL, + err: err, + }) + + return err +} + +func (p *ResourceProvider) detectResource(ctx context.Context) (pcommon.Resource, string, error) { + res := pcommon.NewResource() + mergedSchemaURL := "" + var joinedErr error + successes := 0 + + p.logger.Info("began detecting resource information") + + resultsChan := make([]chan resourceResult, len(p.detectors)) + for i, detector := range p.detectors { + ch := make(chan resourceResult, 1) + resultsChan[i] = ch + + go func(detector Detector, ch chan resourceResult) { + sleep := backoff.ExponentialBackOff{ + InitialInterval: 1 * time.Second, + RandomizationFactor: 1.5, + Multiplier: 2, + } + sleep.Reset() + + for { + r, schemaURL, err := detector.Detect(ctx) + if err == nil { + ch <- resourceResult{resource: r, schemaURL: schemaURL} + return + } + + p.logger.Warn("failed to detect resource", zap.Error(err)) + + next := sleep.NextBackOff() + if next == backoff.Stop { + ch <- resourceResult{err: err} + return + } + + timer := time.NewTimer(next) + select { + case <-ctx.Done(): + p.logger.Warn("context was cancelled", zap.Error(ctx.Err())) + timer.Stop() + ch <- resourceResult{err: err} + return + case <-timer.C: + // retry + } + } + }(detector, ch) + } + + for _, ch := range resultsChan { + result := <-ch + if result.err != nil { + if metadata.ProcessorResourcedetectionPropagateerrorsFeatureGate.IsEnabled() { + joinedErr = errors.Join(joinedErr, result.err) + } + continue + } + successes++ + mergedSchemaURL = MergeSchemaURL(mergedSchemaURL, result.schemaURL) + MergeResource(res, result.resource, false) + } + + p.logger.Info("detected resource information", zap.Any("resource", res.Attributes().AsRaw())) + + // Determine the error to return based on feature gate setting. + var returnErr error + if metadata.ProcessorResourcedetectionPropagateerrorsFeatureGate.IsEnabled() { + // Feature gate enabled: return joined errors (if any) + if successes == 0 && joinedErr == nil { + returnErr = errors.New("resource detection failed: no detectors succeeded") + } else { + returnErr = joinedErr + } + } + + // If all detectors failed, return empty resource. + if successes == 0 { + if !metadata.ProcessorResourcedetectionPropagateerrorsFeatureGate.IsEnabled() { + p.logger.Warn("resource detection failed but error propagation is disabled") + } + return pcommon.NewResource(), "", returnErr + } + + // Partial or full success: return merged resources. + return res, mergedSchemaURL, returnErr +} + +func MergeSchemaURL(currentSchemaURL, newSchemaURL string) string { + if currentSchemaURL == "" { + return newSchemaURL + } + if newSchemaURL == "" { + return currentSchemaURL + } + if currentSchemaURL == newSchemaURL { + return currentSchemaURL + } + // TODO: handle the case when the schema URLs are different by performing + // schema conversion. For now we simply ignore the new schema URL. + return currentSchemaURL +} + +func MergeResource(to, from pcommon.Resource, overrideTo bool) { + if IsEmptyResource(from) { + return + } + + toAttr := to.Attributes() + fromAttr := from.Attributes() + if toAttr.Len() == 0 { + toAttr.EnsureCapacity(fromAttr.Len()) + fromAttr.CopyTo(toAttr) + return + } + + for k, v := range fromAttr.All() { + if overrideTo { + v.CopyTo(toAttr.PutEmpty(k)) + } else { + if targetVal, found := toAttr.GetOrPutEmpty(k); !found { + v.CopyTo(targetVal) + } + } + } +} + +func IsEmptyResource(res pcommon.Resource) bool { + if res == (pcommon.Resource{}) { + return true + } + return res.Attributes().Len() == 0 +} + +// StartRefreshing begins periodic resource refresh if refreshInterval > 0 +func (p *ResourceProvider) StartRefreshing(refreshInterval time.Duration, client *http.Client) { + p.refreshInterval = refreshInterval + if p.refreshInterval <= 0 { + return + } + + p.stopCh = make(chan struct{}) + p.wg.Add(1) + go p.refreshLoop(client) +} + +// StopRefreshing stops the periodic refresh goroutine +func (p *ResourceProvider) StopRefreshing() { + if p.stopCh != nil { + close(p.stopCh) + p.wg.Wait() + } +} + +func (p *ResourceProvider) refreshLoop(client *http.Client) { + defer p.wg.Done() + ticker := time.NewTicker(p.refreshInterval) + defer ticker.Stop() + + for { + select { + case <-ticker.C: + err := p.Refresh(context.Background(), client) + if err != nil { + p.logger.Warn("resource refresh failed", zap.Error(err)) + } + case <-p.stopCh: + return + } + } +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/resourcedetection_processor.go b/collector/lambdacomponents/processor/resourcedetectionprocessor/resourcedetection_processor.go new file mode 100644 index 0000000000..ec31cddc87 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/resourcedetection_processor.go @@ -0,0 +1,99 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package resourcedetectionprocessor // import "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor" + +import ( + "context" + "time" + + "go.opentelemetry.io/collector/component" + "go.opentelemetry.io/collector/config/confighttp" + "go.opentelemetry.io/collector/pdata/plog" + "go.opentelemetry.io/collector/pdata/pmetric" + "go.opentelemetry.io/collector/pdata/pprofile" + "go.opentelemetry.io/collector/pdata/ptrace" + + "github.com/open-telemetry/opentelemetry-collector-contrib/processor/resourcedetectionprocessor/internal" +) + +type resourceDetectionProcessor struct { + provider *internal.ResourceProvider + override bool + httpClientSettings confighttp.ClientConfig + refreshInterval time.Duration + telemetrySettings component.TelemetrySettings +} + +// Start is invoked during service startup. +func (rdp *resourceDetectionProcessor) Start(ctx context.Context, host component.Host) error { + client, err := rdp.httpClientSettings.ToClient(ctx, host.GetExtensions(), rdp.telemetrySettings) + if err != nil { + return err + } + ctx = internal.ContextWithClient(ctx, client) + + // Perform initial resource detection + err = rdp.provider.Refresh(ctx, client) + if err != nil { + return err + } + + // Start periodic refresh if configured + rdp.provider.StartRefreshing(rdp.refreshInterval, client) + return nil +} + +// Shutdown is invoked during service shutdown. +func (rdp *resourceDetectionProcessor) Shutdown(_ context.Context) error { + rdp.provider.StopRefreshing() + return nil +} + +// processTraces implements the ProcessTracesFunc type. +func (rdp *resourceDetectionProcessor) processTraces(ctx context.Context, td ptrace.Traces) (ptrace.Traces, error) { + res, schemaURL, _ := rdp.provider.Get(ctx, nil) + rs := td.ResourceSpans() + for i := 0; i < rs.Len(); i++ { + rss := rs.At(i) + rss.SetSchemaUrl(internal.MergeSchemaURL(rss.SchemaUrl(), schemaURL)) + internal.MergeResource(rss.Resource(), res, rdp.override) + } + return td, nil +} + +// processMetrics implements the ProcessMetricsFunc type. +func (rdp *resourceDetectionProcessor) processMetrics(ctx context.Context, md pmetric.Metrics) (pmetric.Metrics, error) { + res, schemaURL, _ := rdp.provider.Get(ctx, nil) + rm := md.ResourceMetrics() + for i := 0; i < rm.Len(); i++ { + rss := rm.At(i) + rss.SetSchemaUrl(internal.MergeSchemaURL(rss.SchemaUrl(), schemaURL)) + internal.MergeResource(rss.Resource(), res, rdp.override) + } + return md, nil +} + +// processLogs implements the ProcessLogsFunc type. +func (rdp *resourceDetectionProcessor) processLogs(ctx context.Context, ld plog.Logs) (plog.Logs, error) { + res, schemaURL, _ := rdp.provider.Get(ctx, nil) + rl := ld.ResourceLogs() + for i := 0; i < rl.Len(); i++ { + rss := rl.At(i) + rss.SetSchemaUrl(internal.MergeSchemaURL(rss.SchemaUrl(), schemaURL)) + internal.MergeResource(rss.Resource(), res, rdp.override) + } + return ld, nil +} + +// processProfiles implements the ProcessProfilesFunc type. +func (rdp *resourceDetectionProcessor) processProfiles(ctx context.Context, ld pprofile.Profiles) (pprofile.Profiles, error) { + res, schemaURL, _ := rdp.provider.Get(ctx, nil) + rl := ld.ResourceProfiles() + for i := 0; i < rl.Len(); i++ { + rss := rl.At(i) + rss.SetSchemaUrl(internal.MergeSchemaURL(rss.SchemaUrl(), schemaURL)) + internal.MergeResource(rss.Resource(), res, rdp.override) + } + return ld, nil +} diff --git a/collector/lambdacomponents/processor/resourcedetectionprocessor/sync-from-upstream.sh b/collector/lambdacomponents/processor/resourcedetectionprocessor/sync-from-upstream.sh new file mode 100755 index 0000000000..0b4ce12769 --- /dev/null +++ b/collector/lambdacomponents/processor/resourcedetectionprocessor/sync-from-upstream.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash +# Syncs this minimal fork from upstream opentelemetry-collector-contrib. +# Only env + lambda detectors are kept; all other detector code is not fetched. +# +# Usage: +# ./sync-from-upstream.sh v0.146.0 +# +# Prerequisites: gh CLI authenticated, patch, go + +set -euo pipefail + +VERSION="${1:?Usage: $0 e.g. $0 v0.146.0}" +UPSTREAM="open-telemetry/opentelemetry-collector-contrib" +REF="$VERSION" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +fetch() { + local path="$1" dest="$2" + mkdir -p "$(dirname "$dest")" + echo " fetching $path" + gh api "repos/${UPSTREAM}/contents/${path}?ref=${REF}" --jq '.content' | base64 -d > "$dest" +} + +echo "==> Syncing resourcedetectionprocessor from upstream $VERSION" + +# ── verbatim files (no local changes) ──────────────────────────────────────── +fetch processor/resourcedetectionprocessor/resourcedetection_processor.go \ + "$SCRIPT_DIR/resourcedetection_processor.go" + +fetch processor/resourcedetectionprocessor/internal/resourcedetection.go \ + "$SCRIPT_DIR/internal/resourcedetection.go" + +fetch processor/resourcedetectionprocessor/internal/context.go \ + "$SCRIPT_DIR/internal/context.go" + +fetch processor/resourcedetectionprocessor/internal/metadata/generated_status.go \ + "$SCRIPT_DIR/internal/metadata/generated_status.go" + +fetch processor/resourcedetectionprocessor/internal/metadata/generated_feature_gates.go \ + "$SCRIPT_DIR/internal/metadata/generated_feature_gates.go" + +fetch processor/resourcedetectionprocessor/internal/env/env.go \ + "$SCRIPT_DIR/internal/env/env.go" + +fetch processor/resourcedetectionprocessor/internal/aws/lambda/lambda.go \ + "$SCRIPT_DIR/internal/aws/lambda/lambda.go" + +fetch processor/resourcedetectionprocessor/internal/aws/lambda/config.go \ + "$SCRIPT_DIR/internal/aws/lambda/config.go" + +fetch processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_config.go \ + "$SCRIPT_DIR/internal/aws/lambda/internal/metadata/generated_config.go" + +fetch processor/resourcedetectionprocessor/internal/aws/lambda/internal/metadata/generated_resource.go \ + "$SCRIPT_DIR/internal/aws/lambda/internal/metadata/generated_resource.go" + +# ── patched files (fetch upstream, apply local patch) ──────────────────────── +echo " patching factory.go" +fetch processor/resourcedetectionprocessor/factory.go /tmp/rdp_factory_upstream.go +patch -o "$SCRIPT_DIR/factory.go" /tmp/rdp_factory_upstream.go "$SCRIPT_DIR/factory.patch" \ + || { echo "ERROR: factory.patch failed to apply — see above. Update factory.patch for $VERSION."; exit 1; } + +echo " patching config.go" +fetch processor/resourcedetectionprocessor/config.go /tmp/rdp_config_upstream.go +patch -o "$SCRIPT_DIR/config.go" /tmp/rdp_config_upstream.go "$SCRIPT_DIR/config.patch" \ + || { echo "ERROR: config.patch failed to apply — see above. Update config.patch for $VERSION."; exit 1; } + +# ── update go.mod version annotation ───────────────────────────────────────── +echo " updating go.mod go version annotation" +UPSTREAM_GO_VER=$(gh api "repos/${UPSTREAM}/contents/processor/resourcedetectionprocessor/go.mod?ref=${REF}" \ + --jq '.content' | base64 -d | awk '/^go /{print $2}') +sed -i.bak "s/^go .*/go ${UPSTREAM_GO_VER}/" "$SCRIPT_DIR/go.mod" && rm "$SCRIPT_DIR/go.mod.bak" + +# ── tidy ───────────────────────────────────────────────────────────────────── +echo " go mod tidy (fork)" +(cd "$SCRIPT_DIR" && go mod tidy) + +echo " go mod tidy (lambdacomponents)" +(cd "$SCRIPT_DIR/../.." && go mod tidy) + +echo "" +echo "Done. Review changes with: git diff" +echo "If the patches failed to apply cleanly, regenerate them:" +echo " diff -u /tmp/rdp_factory_upstream.go factory.go > factory.patch" +echo " diff -u /tmp/rdp_config_upstream.go config.go > config.patch"