diff --git a/LICENSE-3rdparty.csv b/LICENSE-3rdparty.csv index cf0add6b..c8ab6fcb 100644 --- a/LICENSE-3rdparty.csv +++ b/LICENSE-3rdparty.csv @@ -114,21 +114,17 @@ import,go.opentelemetry.io/collector/component,Apache-2.0,unknown import,go.opentelemetry.io/collector/consumer,Apache-2.0,unknown import,go.opentelemetry.io/collector/consumer/xconsumer,Apache-2.0,unknown import,go.opentelemetry.io/collector/featuregate,Apache-2.0,unknown -import,go.opentelemetry.io/collector/internal/telemetry,Apache-2.0,unknown import,go.opentelemetry.io/collector/pdata,Apache-2.0,unknown import,go.opentelemetry.io/collector/pdata/pprofile,Apache-2.0,unknown import,go.opentelemetry.io/collector/semconv,Apache-2.0,unknown -import,go.opentelemetry.io/contrib/bridges/otelzap,Apache-2.0,unknown import,go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp,Apache-2.0,unknown import,go.opentelemetry.io/ebpf-profiler,Apache-2.0,unknown import,go.opentelemetry.io/otel,Apache-2.0,Copyright 2009 The Go Authors. -import,go.opentelemetry.io/otel/log,Apache-2.0,Copyright 2009 The Go Authors. import,go.opentelemetry.io/otel/metric,Apache-2.0,Copyright 2009 The Go Authors. -import,go.opentelemetry.io/otel/sdk,Apache-2.0,Copyright 2009 The Go Authors. import,go.opentelemetry.io/otel/trace,Apache-2.0,Copyright 2009 The Go Authors. import,go.uber.org/atomic,MIT,"Copyright (c) 2016 Uber Technologies, Inc." import,go.uber.org/multierr,MIT,"Copyright (c) 2017-2021 Uber Technologies, Inc." -import,go.uber.org/zap,MIT,"Copyright (c) 2016-2017 Uber Technologies, Inc." +import,go.uber.org/zap,MIT,"Copyright (c) 2016-2024 Uber Technologies, Inc." import,golang.org/x/arch,BSD-3-Clause,Copyright 2015 The Go Authors. import,golang.org/x/exp/constraints,BSD-3-Clause,Copyright 2009 The Go Authors. import,golang.org/x/mod/semver,BSD-3-Clause,Copyright 2009 The Go Authors. diff --git a/config/cli_flags.go b/config/cli_flags.go index 8fe2fb30..8d85513c 100644 --- a/config/cli_flags.go +++ b/config/cli_flags.go @@ -46,6 +46,7 @@ const ( DefaultProbabilisticInterval = 1 * time.Minute DefaultArgSendErrorFrames = false DefaultArgAgentURL = "http://localhost:8126" + DefaultSendIdleFrames = false DefaultSymbolQueryInterval = 5 * time.Second DefaultUploadSymbolsDryRun = false @@ -216,6 +217,13 @@ func parseCLIArgs(osArgs []string) (*Arguments, error) { Destination: &args.SendErrorFrames, Sources: cli.EnvVars("DD_HOST_PROFILING_SEND_ERROR_FRAMES"), }, + &cli.BoolFlag{ + Name: "send-idle-frames", + Value: DefaultSendIdleFrames, + Usage: "Unwind and report idle states of the Linux kernel.", + Destination: &args.SendIdleFrames, + Sources: cli.EnvVars("DD_HOST_PROFILING_USE_RUNTIME_ID_IN_SERVICE_ENTITY_KEY"), + }, &cli.StringFlag{ Name: "tracers", Aliases: []string{"t"}, diff --git a/config/config.go b/config/config.go index 51c00f92..8415ff4a 100644 --- a/config/config.go +++ b/config/config.go @@ -59,6 +59,7 @@ type Config struct { SamplesPerSecond uint64 PprofPrefix string SendErrorFrames bool + SendIdleFrames bool HostServiceName string Environment string UploadSymbolQueryInterval time.Duration diff --git a/go.mod b/go.mod index 2774f70f..ea1abaee 100644 --- a/go.mod +++ b/go.mod @@ -21,8 +21,8 @@ require ( github.com/zeebo/xxh3 v1.0.2 go.opentelemetry.io/ebpf-profiler v0.0.0-20241114112653-6d846a2023a0 go.opentelemetry.io/otel/metric v1.38.0 - golang.org/x/sync v0.17.0 - golang.org/x/sys v0.36.0 + golang.org/x/sync v0.18.0 + golang.org/x/sys v0.38.0 k8s.io/api v0.32.3 k8s.io/apimachinery v0.32.3 k8s.io/client-go v0.32.3 @@ -54,7 +54,7 @@ require ( github.com/Microsoft/hcsshim v0.11.7 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 // indirect - github.com/cilium/ebpf v0.19.0 // indirect + github.com/cilium/ebpf v0.20.0 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/containerd/api v1.8.0 // indirect github.com/containerd/continuity v0.4.4 // indirect @@ -95,7 +95,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/compress v1.18.1 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -137,37 +137,33 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/collector/component v1.41.1-0.20250918163459-ba0b327d5fe9 // indirect - go.opentelemetry.io/collector/consumer v1.41.1-0.20250915160638-4b4e557b86cb // indirect - go.opentelemetry.io/collector/consumer/xconsumer v0.135.1-0.20250918163459-ba0b327d5fe9 // indirect - go.opentelemetry.io/collector/featuregate v1.41.1-0.20250915160638-4b4e557b86cb // indirect - go.opentelemetry.io/collector/internal/telemetry v0.135.1-0.20250915160638-4b4e557b86cb // indirect - go.opentelemetry.io/collector/pdata v1.41.1-0.20250918163459-ba0b327d5fe9 // indirect - go.opentelemetry.io/collector/pdata/pprofile v0.135.1-0.20250918163459-ba0b327d5fe9 // indirect + go.opentelemetry.io/auto/sdk v1.2.1 // indirect + go.opentelemetry.io/collector/component v1.46.1-0.20251125233348-7ae5e87eb26c // indirect + go.opentelemetry.io/collector/consumer v1.46.0 // indirect + go.opentelemetry.io/collector/consumer/xconsumer v0.140.1-0.20251125233348-7ae5e87eb26c // indirect + go.opentelemetry.io/collector/featuregate v1.46.0 // indirect + go.opentelemetry.io/collector/pdata v1.46.1-0.20251125233348-7ae5e87eb26c // indirect + go.opentelemetry.io/collector/pdata/pprofile v0.140.1-0.20251125233348-7ae5e87eb26c // indirect go.opentelemetry.io/collector/semconv v0.125.0 // indirect - go.opentelemetry.io/contrib/bridges/otelzap v0.12.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect go.opentelemetry.io/otel v1.38.0 // indirect - go.opentelemetry.io/otel/log v0.14.0 // indirect - go.opentelemetry.io/otel/sdk v1.38.0 // indirect go.opentelemetry.io/otel/trace v1.38.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect - go.uber.org/zap v1.27.0 // indirect - golang.org/x/arch v0.21.0 // indirect - golang.org/x/exp v0.0.0-20250911091902-df9299821621 // indirect - golang.org/x/mod v0.28.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/term v0.33.0 // indirect - golang.org/x/text v0.27.0 // indirect + go.uber.org/zap v1.27.1 // indirect + golang.org/x/arch v0.23.0 // indirect + golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 // indirect + golang.org/x/mod v0.30.0 // indirect + golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 // indirect + golang.org/x/oauth2 v0.32.0 // indirect + golang.org/x/term v0.36.0 // indirect + golang.org/x/text v0.30.0 // indirect golang.org/x/time v0.12.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect - google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 // indirect + google.golang.org/grpc v1.77.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect @@ -184,4 +180,4 @@ require ( // To update the Datadog/opentelemetry-ebpf-profiler dependency on latest commit on datadog branch, change the following line to: // replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler datadog // and run `go mod tidy` -replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250924090340-f5c7be4f1db8 +replace go.opentelemetry.io/ebpf-profiler => github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20251126140100-039c456bd3c8 diff --git a/go.sum b/go.sum index 90dfa3b4..7e5f60bb 100644 --- a/go.sum +++ b/go.sum @@ -42,8 +42,8 @@ github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/ github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM= github.com/DataDog/jsonapi v0.12.0 h1:N4e9RpmUflcV5hzceltSz8XUpM3PMtQr5C9Bhv0g87s= github.com/DataDog/jsonapi v0.12.0/go.mod h1:FUSGF3bwMARlVfXEoFo9R/CVlYYy9BGL4C/Prf6Ke3M= -github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250924090340-f5c7be4f1db8 h1:nD9//aAtguUe/eQiBZE7Eht9YcmuomkdSPTtGPhL1PI= -github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20250924090340-f5c7be4f1db8/go.mod h1:979ZsArUaDUVrCkyAbg1ZfU7yClJeHpB5vOvCjemnCE= +github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20251126140100-039c456bd3c8 h1:s3UjVlZTDk3yRKL+5HpQyiCH7H5NN5GSpS/uqmF21EE= +github.com/DataDog/opentelemetry-ebpf-profiler v0.0.0-20251126140100-039c456bd3c8/go.mod h1:YVE6J8xC0NqpiX66ljeNhoqisaVEFuZQ0tGgJLy81Rg= github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.27.0 h1:5US5SqqhfkZkg/E64uvn7YmeTwnudJHtlPEH/LOT99w= github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes v0.27.0/go.mod h1:VRo4D6rj92AExpVBlq3Gcuol9Nm1bber12KyxRjKGWw= github.com/DataDog/sketches-go v1.4.7 h1:eHs5/0i2Sdf20Zkj0udVFWuCrXGRFig2Dcfm5rtcTxc= @@ -65,8 +65,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575 h1:kHaBemcxl8o/pQ5VM1c8PVE1PubbNx3mjUr09OqWGCs= github.com/cihub/seelog v0.0.0-20170130134532-f561c5e57575/go.mod h1:9d6lWj8KzO/fd/NrVaLscBKmPigpZpn5YawRPw+e3Yo= -github.com/cilium/ebpf v0.19.0 h1:Ro/rE64RmFBeA9FGjcTc+KmCeY6jXmryu6FfnzPRIao= -github.com/cilium/ebpf v0.19.0/go.mod h1:fLCgMo3l8tZmAdM3B2XqdFzXBpwkcSTroaVqN08OWVY= +github.com/cilium/ebpf v0.20.0 h1:atwWj9d3NffHyPZzVlx3hmw1on5CLe9eljR8VuHTwhM= +github.com/cilium/ebpf v0.20.0/go.mod h1:pzLjFymM+uZPLk/IXZUL63xdx5VXEo+enTzxkZXdycw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= @@ -218,8 +218,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= -github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co= +github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0= github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM= github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -364,32 +364,30 @@ github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= -go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/collector/component v1.41.1-0.20250918163459-ba0b327d5fe9 h1:Qg3h/BGsDcEC09xQZuJxKfzFdAHkfE84I6az471g2Uc= -go.opentelemetry.io/collector/component v1.41.1-0.20250918163459-ba0b327d5fe9/go.mod h1:ZfY4ID+vu78OTv5SVDVsPgR2L9GYMFOberd6fv60So0= +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/component v1.46.1-0.20251125233348-7ae5e87eb26c h1:yMl4KXNjeWla304VsUdJJnglcfxhT5Lokd20purJMlA= +go.opentelemetry.io/collector/component v1.46.1-0.20251125233348-7ae5e87eb26c/go.mod h1:HlGBJu2lef+3yVWVfodF+gNYe+L/7ADnE5uaZ7SH+LI= go.opentelemetry.io/collector/component/componentstatus v0.125.0 h1:zlxGQZYd9kknRZSjRpOYW5SBjl0a5zYFYRPbreobXoU= go.opentelemetry.io/collector/component/componentstatus v0.125.0/go.mod h1:bHXc2W8bqqo9adOvCgvhcO7pYzJOSpyV4cuQ1wiIl04= -go.opentelemetry.io/collector/component/componenttest v0.135.1-0.20250915160638-4b4e557b86cb h1:pDjG+z5DOyMzuvMcY9kABGzlSXTmnU1GRU397TpVT/E= -go.opentelemetry.io/collector/component/componenttest v0.135.1-0.20250915160638-4b4e557b86cb/go.mod h1:e87SQdPhbb32WIMriVU6ukxvHQuLkt4hYfgswHWUT8I= -go.opentelemetry.io/collector/consumer v1.41.1-0.20250915160638-4b4e557b86cb h1:fmEZR1b1DNjQb7F2VUMa3Ps7ElPNwaEY0My6gjidbq4= -go.opentelemetry.io/collector/consumer v1.41.1-0.20250915160638-4b4e557b86cb/go.mod h1:8m2rGvIWH7Flq/1G1jNFAT9jgTkZqPTsxvBdmx0jZCc= -go.opentelemetry.io/collector/consumer/consumertest v0.135.1-0.20250918163459-ba0b327d5fe9 h1:cO82EFpLXBuufQxu1bvkOb2JmmGhiQ71Hdb1DTfonWU= -go.opentelemetry.io/collector/consumer/consumertest v0.135.1-0.20250918163459-ba0b327d5fe9/go.mod h1:R075BFRd5FJCpsB6s7I5yDlus34wudput7g5qGHalkg= -go.opentelemetry.io/collector/consumer/xconsumer v0.135.1-0.20250918163459-ba0b327d5fe9 h1:DdGnMrzM46GiyYOUOfKvk+wK1+D7B7/oLLRwsjz1jU0= -go.opentelemetry.io/collector/consumer/xconsumer v0.135.1-0.20250918163459-ba0b327d5fe9/go.mod h1:uy4N8NaY+Y930+Y0pRXVp5yK4AAuvBbRzy/GiojzNQk= -go.opentelemetry.io/collector/featuregate v1.41.1-0.20250915160638-4b4e557b86cb h1:Vdc8IWzESC+ydDj2UJG5DbH5V8tR0MmWLF7z4wjtTzM= -go.opentelemetry.io/collector/featuregate v1.41.1-0.20250915160638-4b4e557b86cb/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= -go.opentelemetry.io/collector/internal/telemetry v0.135.1-0.20250915160638-4b4e557b86cb h1:a94187kiFqs4V7OsesguqIcAU73f732A8ZI34tZxtxE= -go.opentelemetry.io/collector/internal/telemetry v0.135.1-0.20250915160638-4b4e557b86cb/go.mod h1:kuqgnegYKBZfTjD/ddhLWJsxmnu3U9znDMD1q6G5xLE= -go.opentelemetry.io/collector/pdata v1.41.1-0.20250918163459-ba0b327d5fe9 h1:/EIOroiWlfCmaCOGQ0LW1UY/esYolw1ndqW2w6HY3Jw= -go.opentelemetry.io/collector/pdata v1.41.1-0.20250918163459-ba0b327d5fe9/go.mod h1:ve6olPOUQwh0jAAD53krLHWKUXIqdHD3iqQdN1Bq3AM= -go.opentelemetry.io/collector/pdata/pprofile v0.135.1-0.20250918163459-ba0b327d5fe9 h1:PwnAClwonIy0LTzlgh6VEc5BGK0f/b0TzwYkRdaEiGk= -go.opentelemetry.io/collector/pdata/pprofile v0.135.1-0.20250918163459-ba0b327d5fe9/go.mod h1:tml0SCva/oqn7l+i8x6stbLUxiYUG7518AwZdnXfQKc= -go.opentelemetry.io/collector/pdata/testdata v0.135.1-0.20250915160638-4b4e557b86cb h1:GK0WsHgL7F1iAHiuE8dzrAwDqdVxZ/9qQh1e0VuLsDg= -go.opentelemetry.io/collector/pdata/testdata v0.135.1-0.20250915160638-4b4e557b86cb/go.mod h1:ivhcBTa+s1eGkhrzQUhI9eSgJIMVssBbwiCs+ncaU/E= -go.opentelemetry.io/collector/pipeline v1.41.1-0.20250915160638-4b4e557b86cb h1:aezh6JaFsY5/K1/O8NOcMAoDTBbtX+Z6Bd7U9V5zlKo= -go.opentelemetry.io/collector/pipeline v1.41.1-0.20250915160638-4b4e557b86cb/go.mod h1:xUrAqiebzYbrgxyoXSkk6/Y3oi5Sy3im2iCA51LwUAI= +go.opentelemetry.io/collector/component/componenttest v0.140.0 h1:/g7yETZ7Flq4v9qSmN9jux0LecMPJDwr8HtvhOgN6H4= +go.opentelemetry.io/collector/component/componenttest v0.140.0/go.mod h1:40PZd6rjqHH5UCqxB6nAvnHtDTwZaSWf1En1u1mbA8k= +go.opentelemetry.io/collector/consumer v1.46.0 h1:yG5zCCgbB2d0KobuYNZWdg8fy/HV2cA/ls0fYzVKBQ4= +go.opentelemetry.io/collector/consumer v1.46.0/go.mod h1:3hjV46vdz8zExuTKlxRge3VdeVUr0PJETqIMewKThNc= +go.opentelemetry.io/collector/consumer/consumertest v0.140.1-0.20251125233348-7ae5e87eb26c h1:soFwSL38rzwQ5UdVS52UFmpd2S1o0GAY2BGShdzx0Rc= +go.opentelemetry.io/collector/consumer/consumertest v0.140.1-0.20251125233348-7ae5e87eb26c/go.mod h1:LvDaKM5A7hUg7LWZBqk69sE0q5GrdM8BmLqX6kCP3WQ= +go.opentelemetry.io/collector/consumer/xconsumer v0.140.1-0.20251125233348-7ae5e87eb26c h1:K2vWjB5btOvspkF/ZWZ9md/eIS0Xh3JnHEs1QvfYd4Q= +go.opentelemetry.io/collector/consumer/xconsumer v0.140.1-0.20251125233348-7ae5e87eb26c/go.mod h1:CtwSgAXVisCEJ+ElKeDa0yDo/Oie7l1vWAx1elFyWZc= +go.opentelemetry.io/collector/featuregate v1.46.0 h1:z3JlymFdWW6aDo9cYAJ6bCqT+OI2DlurJ9P8HqfuKWQ= +go.opentelemetry.io/collector/featuregate v1.46.0/go.mod h1:d0tiRzVYrytB6LkcYgz2ESFTv7OktRPQe0QEQcPt1L4= +go.opentelemetry.io/collector/pdata v1.46.1-0.20251125233348-7ae5e87eb26c h1:9ImjRD72/LrNYAPHPueMsfHoEBh51FwRLVCPXYH+oAw= +go.opentelemetry.io/collector/pdata v1.46.1-0.20251125233348-7ae5e87eb26c/go.mod h1:AqZXTFkj01IxuiHZ1/I7UcGqaljvF5xiUXNYGxRqVp8= +go.opentelemetry.io/collector/pdata/pprofile v0.140.1-0.20251125233348-7ae5e87eb26c h1:4Ht3sx2w/wwv9omLiz+ZDCvGHRgINMS0RATwPs2nvIA= +go.opentelemetry.io/collector/pdata/pprofile v0.140.1-0.20251125233348-7ae5e87eb26c/go.mod h1:01EwjIBpIcmJva7IoXPmHPmACGzsGxFi9xhZhY7W4q8= +go.opentelemetry.io/collector/pdata/testdata v0.125.0 h1:due1Hl0EEVRVwfCkiamRy5E8lS6yalv0lo8Zl/SJtGw= +go.opentelemetry.io/collector/pdata/testdata v0.125.0/go.mod h1:1GpEWlgdMrd+fWsBk37ZC2YmOP5YU3gFQ4rWuCu9g24= +go.opentelemetry.io/collector/pipeline v1.46.0 h1:VFID9aOmX5eeZSj29lgMdX7qg5nLKiXnkKOJXIAu47c= +go.opentelemetry.io/collector/pipeline v1.46.0/go.mod h1:xUrAqiebzYbrgxyoXSkk6/Y3oi5Sy3im2iCA51LwUAI= go.opentelemetry.io/collector/processor v1.31.0 h1:+u7sBUpnCBsHYoALp4hfr9VEjLHHYa4uKENGITe0K9Q= go.opentelemetry.io/collector/processor v1.31.0/go.mod h1:5hDYJ7/hTdfd2tF2Rj5Hs6+mfyFz2O7CaPzVvW1qHQc= go.opentelemetry.io/collector/processor/processorhelper v0.125.0 h1:QRpX7oFW88DAZhy+Q93npklRoaQr8ue0GKpeup7C/Fk= @@ -400,8 +398,6 @@ go.opentelemetry.io/collector/processor/xprocessor v0.125.0 h1:VWYPMW1VmDq6xB7M5 go.opentelemetry.io/collector/processor/xprocessor v0.125.0/go.mod h1:bCxUyFVlksANg8wjYZqWVsRB33lkLQ294rTrju/IZiM= go.opentelemetry.io/collector/semconv v0.125.0 h1:SyRP617YGvNSWRSKMy7Lbk9RaJSR+qFAAfyxJOeZe4s= go.opentelemetry.io/collector/semconv v0.125.0/go.mod h1:te6VQ4zZJO5Lp8dM2XIhDxDiL45mwX0YAQQWRQ0Qr9U= -go.opentelemetry.io/contrib/bridges/otelzap v0.12.0 h1:FGre0nZh5BSw7G73VpT3xs38HchsfPsa2aZtMp0NPOs= -go.opentelemetry.io/contrib/bridges/otelzap v0.12.0/go.mod h1:X2PYPViI2wTPIMIOBjG17KNybTzsrATnvPJ02kkz7LM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8= @@ -410,10 +406,6 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU= -go.opentelemetry.io/otel/log v0.14.0 h1:2rzJ+pOAZ8qmZ3DDHg73NEKzSZkhkGIua9gXtxNGgrM= -go.opentelemetry.io/otel/log v0.14.0/go.mod h1:5jRG92fEAgx0SU/vFPxmJvhIuDU9E1SUnEQrMlJpOno= -go.opentelemetry.io/otel/log/logtest v0.14.0 h1:BGTqNeluJDK2uIHAY8lRqxjVAYfqgcaTbVk1n3MWe5A= -go.opentelemetry.io/otel/log/logtest v0.14.0/go.mod h1:IuguGt8XVP4XA4d2oEEDMVDBBCesMg8/tSGWDjuKfoA= go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA= go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI= go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E= @@ -424,12 +416,12 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -go.opentelemetry.io/proto/slim/otlp v1.8.0 h1:afcLwp2XOeCbGrjufT1qWyruFt+6C9g5SOuymrSPUXQ= -go.opentelemetry.io/proto/slim/otlp v1.8.0/go.mod h1:Yaa5fjYm1SMCq0hG0x/87wV1MP9H5xDuG/1+AhvBcsI= -go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0 h1:Uc+elixz922LHx5colXGi1ORbsW8DTIGM+gg+D9V7HE= -go.opentelemetry.io/proto/slim/otlp/collector/profiles/v1development v0.1.0/go.mod h1:VyU6dTWBWv6h9w/+DYgSZAPMabWbPTFTuxp25sM8+s0= -go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0 h1:i8YpvWGm/Uq1koL//bnbJ/26eV3OrKWm09+rDYo7keU= -go.opentelemetry.io/proto/slim/otlp/profiles/v1development v0.1.0/go.mod h1:pQ70xHY/ZVxNUBPn+qUWPl8nwai87eWdqL3M37lNi9A= +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/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -437,26 +429,26 @@ 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.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/arch v0.21.0 h1:iTC9o7+wP6cPWpDWkivCvQFGAHDQ59SrSxsLPcnkArw= -golang.org/x/arch v0.21.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg= +golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU= -golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk= +golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39 h1:DHNhtq3sNNzrvduZZIiFyXWOL9IWaDPHqTnLJp+rCBY= +golang.org/x/exp v0.0.0-20251125195548-87e1e737ad39/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= -golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -470,19 +462,19 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82 h1:6/3JGEh1C88g7m+qzzTbl3A0FtsLguXieqofVLU/JAo= +golang.org/x/net v0.46.1-0.20251013234738-63d1a5100f82/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.32.0 h1:jsCblLleRMDrxMN29H3z/k1KliIvpLgCkE6R8FXXNgY= +golang.org/x/oauth2 v0.32.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= -golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -505,15 +497,15 @@ golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= +golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -525,8 +517,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= -golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -544,17 +536,17 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa h1:ePqxpG3LVx+feAUOx8YmR5T7rc0rdzK8DyxM8cQ9zq0= google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:CnZenrTdRJb7jc+jOm0Rkywq+9wh0QC4U8tyiRbEPPM= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= -google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8 h1:mepRgnBZa07I4TRuomDE4sTIYieg/osKmzIf4USdWS4= +google.golang.org/genproto/googleapis/api v0.0.0-20251022142026-3a174f9686a8/go.mod h1:fDMmzKV90WSg1NbozdqrE64fkuTv6mlq2zxo9ad+3yo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8 h1:M1rk8KBnUsBDg1oPGHNCxG4vc1f49epmTO7xscSajMk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251022142026-3a174f9686a8/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= -google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.77.0 h1:wVVY6/8cGA6vvffn+wWK5ToddbgdU3d8MNENr4evgXM= +google.golang.org/grpc v1.77.0/go.mod h1:z0BY1iVj0q8E1uSQCjL9cppRj+gnZjzDnzV0dHhrNig= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -567,8 +559,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/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= diff --git a/pclntab/pclntab.go b/pclntab/pclntab.go index e6b8ba66..538d1efc 100644 --- a/pclntab/pclntab.go +++ b/pclntab/pclntab.go @@ -163,8 +163,8 @@ func getUint8(data []byte, offset int) int { return int(*(*uint8)(unsafe.Pointer(&data[offset]))) } -// HeaderSize returns the minimal pclntab header size. -func HeaderSize() int { +// pclntabHeaderSize returns the minimal pclntab header size. +func pclntabHeaderSize() int { return int(unsafe.Sizeof(pclntabHeader{})) } @@ -187,21 +187,19 @@ func goFuncOffset(v HeaderVersion) (uint32, error) { return 40 * ptrSize, nil } -func FindModuleData(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.SymbolMap) (data []byte, address uint64, returnedErr error) { +func FindModuleData(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, runtimeFirstModuleDataSymbolValue libpf.SymbolValue) (data []byte, address uint64, returnedErr error) { // First try to locate module data by looking for runtime.firstmoduledata symbol. - if symtab != nil { - if symAddr, err := symtab.LookupSymbolAddress("runtime.firstmoduledata"); err == nil { - addr := uint64(symAddr) - section := sectionContaining(ef, addr) - if section == nil { - return nil, 0, errors.New("could not find section containing runtime.firstmoduledata") - } - data, err := section.Data(maxBytesGoPclntab) - if err != nil { - return nil, 0, fmt.Errorf("could not read section containing runtime.firstmoduledata: %w", err) - } - return data[addr-section.Addr:], addr, nil + if runtimeFirstModuleDataSymbolValue != 0 { + addr := uint64(runtimeFirstModuleDataSymbolValue) + section := sectionContaining(ef, addr) + if section == nil { + return nil, 0, errors.New("could not find section containing runtime.firstmoduledata") } + data, err := section.Data(maxBytesGoPclntab) + if err != nil { + return nil, 0, fmt.Errorf("could not read section containing runtime.firstmoduledata: %w", err) + } + return data[addr-section.Addr:], addr, nil } // If runtime.firstmoduledata is missing, heuristically search for gopclntab address in .noptrdata section. @@ -278,18 +276,8 @@ func findGoFuncEnd(data []byte, version HeaderVersion) int { return findGoFuncEnd120(data) } -func findGoFuncVal(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.SymbolMap) (uint64, error) { - // First try to locate goFunc with go:func.* symbol. - if symtab != nil { - if goFuncSym, err := symtab.LookupSymbol("go:func.*"); err == nil { - return uint64(goFuncSym.Address), nil - } - if goFuncSym, err := symtab.LookupSymbol("go.func.*"); err == nil { - return uint64(goFuncSym.Address), nil - } - } - - moduleData, _, err := FindModuleData(ef, goPCLnTabInfo, symtab) +func findGoFuncVal(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, runtimeFirstModuleDataSymbolValue libpf.SymbolValue) (uint64, error) { + moduleData, _, err := FindModuleData(ef, goPCLnTabInfo, runtimeFirstModuleDataSymbolValue) if err != nil { return 0, fmt.Errorf("could not find module data: %w", err) } @@ -305,10 +293,15 @@ func findGoFuncVal(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.S return goFuncVal, nil } -func FindGoFunc(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, symtab *libpf.SymbolMap) (data []byte, goFuncVal uint64, err error) { - goFuncVal, err = findGoFuncVal(ef, goPCLnTabInfo, symtab) - if err != nil { - return nil, 0, fmt.Errorf("could not find go func: %w", err) +func FindGoFunc(ef *pfelf.File, goPCLnTabInfo *GoPCLnTabInfo, runtimeFirstModuleDataSymbolValue, goFuncSymbolValue libpf.SymbolValue) (data []byte, goFuncVal uint64, err error) { + if goFuncSymbolValue == 0 { + goFuncVal, err = findGoFuncVal(ef, goPCLnTabInfo, runtimeFirstModuleDataSymbolValue) + if err != nil { + return nil, 0, fmt.Errorf("could not find go func value: %w", err) + } + } else { + // Symbol go:func.* or go.func.* is present, use it to get the goFunc value. + goFuncVal = uint64(goFuncSymbolValue) } sec := sectionContaining(ef, goFuncVal) if sec == nil { @@ -352,12 +345,17 @@ func SearchGoPclntab(ef *pfelf.File) (data []byte, address uint64, err error) { continue } + // Skip segments that are too small anyway. + if p.Filesz < uint64(pclntabHeaderSize()) { + continue + } + data, err = p.Data(maxBytesGoPclntab) if err != nil { return nil, 0, err } - for i := 1; i < len(data)-16; i += 8 { + for i := 1; i < len(data)-pclntabHeaderSize(); i += 8 { // Search for something looking like a valid pclntabHeader header // Ignore the first byte on bytes.Index (differs on magicGo1_XXX) n := bytes.Index(data[i:], signature) @@ -439,12 +437,11 @@ func (g *GoPCLnTabInfo) computePCLnTabSize() int { return alignUp(int(g.Offsets.FuncTabOffset)+funcDataSize, ptrSize) } -func (g *GoPCLnTabInfo) trimGoFunc(goFuncData []byte, goFuncAddr uint64, symtab *libpf.SymbolMap) ([]byte, error) { - if symtab != nil { - // symbol runtime.gcbits.* follows goFunc, try to use it to determine the end of goFunc. - nextSymAddr, err := symtab.LookupSymbolAddress("runtime.gcbits.*") - if err == nil && uint64(nextSymAddr) > goFuncAddr { - dist := uint64(nextSymAddr) - goFuncAddr +func (g *GoPCLnTabInfo) trimGoFunc(goFuncData []byte, goFuncAddr uint64, runtimeGcbitsSymbolValue libpf.SymbolValue) ([]byte, error) { + if runtimeGcbitsSymbolValue != 0 { + // symbol runtime.gcbits.* follows goFunc, use it to determine the end of goFunc. + if uint64(runtimeGcbitsSymbolValue) > goFuncAddr { + dist := uint64(runtimeGcbitsSymbolValue) - goFuncAddr if dist < uint64(len(goFuncData)) { return goFuncData[:dist], nil } @@ -470,7 +467,7 @@ func parseGoPCLnTab(data []byte) (*GoPCLnTabInfo, error) { var version HeaderVersion var offsets TableOffsets var funcSize, funcNpcdataOffset int - hdrSize := uintptr(HeaderSize()) + hdrSize := uintptr(pclntabHeaderSize()) dataLen := uintptr(len(data)) if dataLen < hdrSize { @@ -597,7 +594,6 @@ func findGoPCLnTab(ef *pfelf.File, additionalChecks bool) (goPCLnTabInfo *GoPCLn var data []byte var goPCLnTabAddr uint64 - var symtab *libpf.SymbolMap goPCLnTabEndKnown := true if s := ef.Section(".gopclntab"); s != nil { @@ -611,8 +607,16 @@ func findGoPCLnTab(ef *pfelf.File, additionalChecks bool) (goPCLnTabInfo *GoPCLn } goPCLnTabAddr = s.Addr } else if s := ef.Section(".go.buildinfo"); s != nil { - symtab, err = ef.ReadSymbols() - if err != nil { + var start, end libpf.SymbolValue + _ = ef.VisitSymbols(func(sym libpf.Symbol) bool { + if start == 0 && sym.Name == "runtime.pclntab" { + start = sym.Address + } else if end == 0 && sym.Name == "runtime.epclntab" { + end = sym.Address + } + return start == 0 || end == 0 + }) + if start == 0 || end == 0 { // It seems the Go binary was stripped, use the heuristic approach to get find gopclntab. // Note that `SearchGoPclntab` returns a slice starting from gopcltab header to the end of segment // containing gopclntab. Therefore this slice might contain additional data after gopclntab. @@ -627,20 +631,11 @@ func findGoPCLnTab(ef *pfelf.File, additionalChecks bool) (goPCLnTabInfo *GoPCLn } goPCLnTabEndKnown = false } else { - var start, end libpf.SymbolValue - start, err = symtab.LookupSymbolAddress("runtime.pclntab") - if err != nil { - return nil, fmt.Errorf("failed to load .gopclntab via symbols: %w", err) - } - end, err = symtab.LookupSymbolAddress("runtime.epclntab") - if err != nil { - return nil, fmt.Errorf("failed to load .gopclntab via symbols: %w", err) - } if start >= end { return nil, fmt.Errorf("invalid .gopclntab symbols: %v-%v", start, end) } - data = make([]byte, end-start) - if _, err = ef.ReadVirtualMemory(data, int64(start)); err != nil { + data, err = ef.VirtualMemory(int64(start), int(end-start), maxBytesGoPclntab) + if err != nil { return nil, fmt.Errorf("failed to load .gopclntab via symbols: %w", err) } goPCLnTabAddr = uint64(start) @@ -677,13 +672,25 @@ func findGoPCLnTab(ef *pfelf.File, additionalChecks bool) (goPCLnTabInfo *GoPCLn // Only search for goFunc if the version is 1.18 or later and heuristic search is enabled. if goPCLnTabInfo.Version >= ver118 { - if symtab == nil { - symtab, _ = ef.ReadSymbols() - } + var runtimeFirstModuleDataSymbolValue, goFuncSymbolValue, runtimeGcbitsSymbolValue libpf.SymbolValue + // Retrieve the address of some symbols that can be used to find the goFunc start/end. + // Do it once here to avoid calling VisitSymbols multiple times for each symbol. + _ = ef.VisitSymbols(func(sym libpf.Symbol) bool { + switch { + case runtimeFirstModuleDataSymbolValue == 0 && sym.Name == "runtime.firstmoduledata": + runtimeFirstModuleDataSymbolValue = sym.Address + // Depending on the Go version, the symbol name may be "go:func.*" or "go.func.*". + case goFuncSymbolValue == 0 && (sym.Name == "go:func.*" || sym.Name == "go.func.*"): + goFuncSymbolValue = sym.Address + case runtimeGcbitsSymbolValue == 0 && sym.Name == "runtime.gcbits.*": + runtimeGcbitsSymbolValue = sym.Address + } + return runtimeFirstModuleDataSymbolValue == 0 || goFuncSymbolValue == 0 || runtimeGcbitsSymbolValue == 0 + }) - goFuncData, goFuncAddr, err := FindGoFunc(ef, goPCLnTabInfo, symtab) + goFuncData, goFuncAddr, err := FindGoFunc(ef, goPCLnTabInfo, runtimeFirstModuleDataSymbolValue, goFuncSymbolValue) if err == nil { - goFuncData, err = goPCLnTabInfo.trimGoFunc(goFuncData, goFuncAddr, symtab) + goFuncData, err = goPCLnTabInfo.trimGoFunc(goFuncData, goFuncAddr, runtimeGcbitsSymbolValue) if err == nil { goPCLnTabInfo.GoFuncAddr = goFuncAddr goPCLnTabInfo.GoFuncData = goFuncData diff --git a/reporter/datadog_reporter.go b/reporter/datadog_reporter.go index 221a06e5..e3537839 100644 --- a/reporter/datadog_reporter.go +++ b/reporter/datadog_reporter.go @@ -159,9 +159,10 @@ func (r *DatadogReporter) ReportTraceEvent(trace *libpf.Trace, meta *samples.Tra key := rsamples.TraceAndMetaKey{ Hash: trace.Hash, - Comm: meta.Comm, + Comm: meta.Comm.String(), Pid: meta.PID, Tid: meta.TID, + CPU: int64(meta.CPU), } eventsTree := r.traceEvents.WLock() @@ -200,9 +201,9 @@ func (r *DatadogReporter) ReportTraceEvent(trace *libpf.Trace, meta *samples.Tra return nil } - var customLabels []map[string]string + var customLabels []map[libpf.String]libpf.String if r.config.CollectContext { - customLabels = []map[string]string{trace.CustomLabels} + customLabels = []map[libpf.String]libpf.String{trace.CustomLabels} } perOriginEvents[key] = &rsamples.TraceEvents{ @@ -502,6 +503,7 @@ func createTags(userTags Tags, runtimeTag, version string, splitByServiceEnabled tags := append(Tags{}, userTags...) customContextTagKey := "ddprof.custom_ctx" + tags = append(tags, MakeTag(customContextTagKey, pprof.CPUIDLabel)) if !splitByServiceEnabled { tags = append(tags, MakeTag(customContextTagKey, "container_id"), @@ -567,7 +569,7 @@ func (r *DatadogReporter) addProcessMetadata(trace *libpf.Trace, meta *samples.T if err != nil { // Process might have exited since the trace was collected or process is a kernel thread. log.Debugf("Failed to get process metadata for PID %d: %v", pid, err) - execPath = meta.ExecutablePath + execPath = meta.ExecutablePath.String() } // Trim the "(deleted)" suffix if it exists. // This can happen when the executable has been deleted or replaced while the process is running. @@ -578,14 +580,13 @@ func (r *DatadogReporter) addProcessMetadata(trace *libpf.Trace, meta *samples.T processName = string(name) } else { r.processAlreadyExitedCount++ - processName = meta.ProcessName + processName = meta.ProcessName.String() } var service string - var ok bool for _, envVarName := range ServiceNameEnvVars { - service, ok = meta.EnvVars[envVarName] - if ok { + if s, ok := meta.EnvVars[libpf.Intern(envVarName)]; ok { + service = s.String() break } } @@ -596,7 +597,7 @@ func (r *DatadogReporter) addProcessMetadata(trace *libpf.Trace, meta *samples.T // This can occur when a container is started, during startup the process is runc // (without the final container environment) that then execs into the final binary // with the container environment. - if !ok && meta.ExecutablePath != execPath { + if service == "" && meta.ExecutablePath.String() != execPath { service = getServiceName(pid) } @@ -629,8 +630,8 @@ func (r *DatadogReporter) addProcessMetadata(trace *libpf.Trace, meta *samples.T case processName != "": service = processName inferredService = true - case meta.Comm != "": - service = meta.Comm + case meta.Comm != libpf.NullString: + service = meta.Comm.String() inferredService = true default: service = unknownServiceStr @@ -638,13 +639,13 @@ func (r *DatadogReporter) addProcessMetadata(trace *libpf.Trace, meta *samples.T } var containerMetadata containermetadata.ContainerMetadata - if meta.ContainerID != "" && r.config.EnableSplitByService { + if meta.ContainerID != libpf.NullString && r.config.EnableSplitByService { // Use containerID when found by the eBPF profiler and not other container metadata is needed // (ie. split by service is enabled). // eBPF profiler only supports cgroup v2 and even with cgroup v2, depending on Kubernetes settings, // containerID might not be available in /proc//cgroup. containerMetadata = containermetadata.ContainerMetadata{ - EntityID: "ci-" + meta.ContainerID, + EntityID: "ci-" + meta.ContainerID.String(), } } else { containerMetadata, err = r.containerMetadataProvider.GetContainerMetadata(pid) diff --git a/reporter/pprof/profile_builder.go b/reporter/pprof/profile_builder.go index bdb9a8fc..a41470d8 100644 --- a/reporter/pprof/profile_builder.go +++ b/reporter/pprof/profile_builder.go @@ -8,6 +8,7 @@ package pprof import ( "fmt" "path" + "strconv" "time" lru "github.com/elastic/go-freelru" @@ -17,7 +18,10 @@ import ( samples "github.com/DataDog/dd-otel-host-profiler/reporter/samples" ) -const unknownStr = "UNKNOWN" +const ( + unknownStr = "UNKNOWN" + CPUIDLabel = "cpu.logical_number" +) type Config struct { Start time.Time @@ -32,7 +36,7 @@ type Config struct { type ProfileBuilder struct { profile *pprofile.Profile funcMap map[funcInfo]*pprofile.Function - mappings map[uniqueMapping]*pprofile.Mapping + mappings map[libpf.FrameMapping]*pprofile.Mapping processes *lru.SyncedLRU[libpf.PID, samples.ProcessMetadata] timeline bool processLevelContextAsLabels bool @@ -45,19 +49,11 @@ type ProfileStats struct { TotalSampleCount int } -// uniqueMapping defines an unique mapping in a process. -type uniqueMapping struct { - // mapping start in the ELF virtual address space - Start libpf.Address - // mapping file - File libpf.FrameMappingFile -} - func NewProfileBuilder(cfg *Config) *ProfileBuilder { // funcMap is a temporary helper that will build the Function array // in profile and make sure information is deduplicated. funcMap := make(map[funcInfo]*pprofile.Function) - mappings := make(map[uniqueMapping]*pprofile.Mapping) + mappings := make(map[libpf.FrameMapping]*pprofile.Mapping) samplingPeriod := 1000000000 / int64(cfg.SamplesPerSecond) profile := &pprofile.Profile{ @@ -225,24 +221,20 @@ func (b *ProfileBuilder) createPProfLocation(address uint64) *pprofile.Location } func (b *ProfileBuilder) createPprofMappingForFrame(frame *libpf.Frame) *pprofile.Mapping { - if !frame.MappingFile.Valid() { + if !frame.Mapping.Valid() { return nil } - if mapping, exists := b.mappings[uniqueMapping{Start: frame.MappingStart, File: frame.MappingFile}]; exists { + if mapping, exists := b.mappings[frame.Mapping]; exists { return mapping } - mf := frame.MappingFile.Value() - fileName := unknownStr - // Not sure if it's possible to have a null string here, but just in case. - if mf.FileName != libpf.NullString { - fileName = mf.FileName.String() - } + m := frame.Mapping.Value() + mf := m.File.Value() buildID := samples.GetBuildID(mf.GnuBuildID, mf.GoBuildID, mf.FileID) - mapping := b.createPprofMapping(fileName, buildID, frame.MappingStart, frame.MappingFileOffset) - b.mappings[uniqueMapping{Start: frame.MappingStart, File: frame.MappingFile}] = mapping + mapping := b.createPprofMapping(mf.FileName.String(), buildID, m.Start, m.FileOffset) + b.mappings[frame.Mapping] = mapping return mapping } @@ -279,6 +271,8 @@ func addTraceLabels(labels map[string][]string, i samples.TraceAndMetaKey, proce labels["process name"] = append(labels["process name"], processName) } + labels[CPUIDLabel] = append(labels[CPUIDLabel], strconv.Itoa(int(i.CPU))) + containerMetadata := processMeta.ContainerMetadata if containerMetadata.PodName != "" { labels["pod_name"] = append(labels["pod_name"], containerMetadata.PodName) @@ -340,13 +334,13 @@ func hasCustomLabels(traceInfo *samples.TraceEvents) bool { return false } -func addCustomLabels(labels map[string][]string, customLabels map[string]string) map[string][]string { +func addCustomLabels(labels map[string][]string, customLabels map[libpf.String]libpf.String) map[string][]string { labelsCopy := make(map[string][]string) for key, value := range labels { labelsCopy[key] = append(labelsCopy[key], value...) } for key, value := range customLabels { - labelsCopy[key] = append(labelsCopy[key], value) + labelsCopy[key.String()] = append(labelsCopy[key.String()], value.String()) } return labelsCopy } diff --git a/reporter/samples/samples.go b/reporter/samples/samples.go index 97d66fcf..c35d29e6 100644 --- a/reporter/samples/samples.go +++ b/reporter/samples/samples.go @@ -32,6 +32,7 @@ type TraceAndMetaKey struct { Comm string Pid libpf.PID Tid libpf.PID + CPU int64 } // TraceEvents from ebpf-profiler/reporter/samples cannot be used here because @@ -43,7 +44,7 @@ type TraceAndMetaKey struct { type TraceEvents struct { samples.TraceEvents - CustomLabels []map[string]string + CustomLabels []map[libpf.String]libpf.String } type ProcessContext struct { diff --git a/reporter/symbol/elf_wrapper.go b/reporter/symbol/elf_wrapper.go index ba10e231..53446345 100644 --- a/reporter/symbol/elf_wrapper.go +++ b/reporter/symbol/elf_wrapper.go @@ -11,10 +11,13 @@ import ( "errors" "fmt" "os" + "path" "path/filepath" "slices" + "strconv" log "github.com/sirupsen/logrus" + "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/libpf/pfelf" "go.opentelemetry.io/ebpf-profiler/process" ) @@ -43,6 +46,14 @@ type FileHelper interface { ExtractAsFile(string) (string, error) } +type ProcessFileHelper struct { + pid libpf.PID +} + +func (p *ProcessFileHelper) ExtractAsFile(filePath string) (string, error) { + return path.Join("/proc", strconv.Itoa(int(p.pid)), "root", filePath), nil +} + type elfWrapper struct { elfFile *pfelf.File filePath string @@ -77,7 +88,7 @@ func newElfWrapperFromVDSO(m *process.Mapping, pr process.Process) (ef *elfWrapp if err != nil { return nil, fmt.Errorf("failed to create elf file from vdso memory for PID %d: %w", pr.PID(), err) } - return &elfWrapper{elfFile: elfFile, data: data, helper: pr}, nil + return &elfWrapper{elfFile: elfFile, data: data, helper: &ProcessFileHelper{pid: pr.PID()}}, nil } func newElfWrapperFromMapping(m *process.Mapping, pr process.Process) (ef *elfWrapper, err error) { @@ -110,7 +121,7 @@ func newElfWrapperFromMapping(m *process.Mapping, pr process.Process) (ef *elfWr return nil, fmt.Errorf("failed to cast mapping file %s to *os.File for PID %d", m.Path.String(), pr.PID()) } - return newElfWrapper(elfFile, m.Path.String(), f, pr, nil) + return newElfWrapper(elfFile, m.Path.String(), f, &ProcessFileHelper{pid: pr.PID()}, nil) } func newElfWrapperFromFile(filePath string, helper FileHelper) (ef *elfWrapper, err error) { diff --git a/reporter/symbol_uploader_test.go b/reporter/symbol_uploader_test.go index 85984198..65995139 100644 --- a/reporter/symbol_uploader_test.go +++ b/reporter/symbol_uploader_test.go @@ -11,6 +11,7 @@ import ( "debug/elf" "encoding/json" "errors" + "fmt" "io" "mime" "mime/multipart" @@ -21,7 +22,6 @@ import ( "path/filepath" "reflect" "runtime" - "strconv" "strings" "testing" @@ -84,14 +84,22 @@ func (d *dummyProcess) OpenELF(name string) (*pfelf.File, error) { return pfelf.Open(name) } -func (d *dummyProcess) ExtractAsFile(name string) (string, error) { - return path.Join("/proc", strconv.Itoa(int(d.pid)), "root", name), nil -} - func (d *dummyProcess) Close() error { return nil } +func (d *dummyProcess) GetExe() (libpf.String, error) { + str, err := os.Readlink(fmt.Sprintf("/proc/%d/exe", d.pid)) + if err != nil { + return libpf.NullString, err + } + return libpf.Intern(str), nil +} + +func (d *dummyProcess) GetProcessMeta(_ process.MetaConfig) process.ProcessMeta { + return process.ProcessMeta{} +} + func newExecutableMetadata(t *testing.T, filePath, goBuildID string) *reporter.ExecutableMetadata { fileID, err := libpf.FileIDFromExecutableFile(filePath) require.NoError(t, err) @@ -241,10 +249,49 @@ func checkRequest(t *testing.T, req *http.Request, expectedSymbolSource symbol.S case symbol.SourceSymbolTable: require.NotNil(t, findSymbol(elfFile, "main.main")) case symbol.SourceDebugInfo: - require.True(t, pfelf.HasDWARFData(elfFile)) + require.True(t, hasDWARFData(elfFile)) } } +func hasDWARFData(elfFile *elf.File) bool { + hasBuildID := false + hasDebugStr := false + for _, section := range elfFile.Sections { + // NOBITS indicates that the section is actually empty, regardless of the size in the + // section header. + if section.Type == elf.SHT_NOBITS { + continue + } + + if section.Name == ".note.gnu.build-id" { + hasBuildID = true + } + + if section.Name == ".debug_str" || section.Name == ".zdebug_str" || + section.Name == ".debug_str.dwo" { + hasDebugStr = section.Size > 0 + } + + // Some files have suspicious near-empty, partially stripped sections; consider them as not + // having DWARF data. + // The simplest binary gcc 10 can generate ("return 0") has >= 48 bytes for each section. + // Let's not worry about executables that may not verify this, as they would not be of + // interest to us. + if section.Size < 32 { + continue + } + + if section.Name == ".debug_info" || section.Name == ".zdebug_info" { + return true + } + } + + // Some alternate debug files only have a .debug_str section. For these we want to return true. + // Use the absence of program headers and presence of a Build ID as heuristic to identify + // alternate debug files. + return len(elfFile.Progs) == 0 && hasBuildID && hasDebugStr +} + func TestGoPCLnTabExtraction(t *testing.T) { t.Parallel() srcFile := "../testdata/helloworld.go" diff --git a/runner/runner.go b/runner/runner.go index 9da20f29..3794b175 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -26,9 +26,7 @@ import ( "go.opentelemetry.io/ebpf-profiler/host" "go.opentelemetry.io/ebpf-profiler/libpf" "go.opentelemetry.io/ebpf-profiler/metrics" - otelreporter "go.opentelemetry.io/ebpf-profiler/reporter" "go.opentelemetry.io/ebpf-profiler/times" - "go.opentelemetry.io/ebpf-profiler/tracehandler" "go.opentelemetry.io/ebpf-profiler/tracer" tracertypes "go.opentelemetry.io/ebpf-profiler/tracer/types" "go.opentelemetry.io/otel/metric/noop" @@ -59,8 +57,7 @@ const ( defaultProcessesCacheSize = 16384 ) -func startTraceHandling(ctx context.Context, rep otelreporter.TraceReporter, - intervals *times.Times, trc *tracer.Tracer, cacheSize uint32) error { +func startTraceHandling(ctx context.Context, trc *tracer.Tracer) error { // Spawn monitors for the various result maps traceCh := make(chan *host.Trace) @@ -68,10 +65,21 @@ func startTraceHandling(ctx context.Context, rep otelreporter.TraceReporter, return fmt.Errorf("failed to start map monitors: %w", err) } - _, err := tracehandler.Start(ctx, rep, trc.TraceProcessor(), - traceCh, intervals, cacheSize) + go func() { + // Poll the output channels + for { + select { + case trace := <-traceCh: + if trace != nil { + trc.HandleTrace(trace) + } + case <-ctx.Done(): + return + } + } + }() - return err + return nil } func appendEndpoint(symbolEndpoints []reporter.SymbolEndpoint, site, apiKey, appKey string) []reporter.SymbolEndpoint { @@ -165,9 +173,6 @@ func Run(mainCtx context.Context, c *config.Config) ExitCode { return failure("Failed to probe eBPF syscall: %v", err) } - // disable trace handler cache because it consumes too much memory for almost no CPU benefit - traceHandlerCacheSize := uint32(0) - intervals := times.New(c.ReporterInterval, c.MonitorInterval, c.ProbabilisticInterval) @@ -295,9 +300,11 @@ func Run(mainCtx context.Context, c *config.Config) ExitCode { // Load the eBPF code and map definitions trc, err := tracer.NewTracer(mainCtx, &tracer.Config{ ExecutableReporter: rep, + TraceReporter: rep, Intervals: intervals, IncludeTracers: includeTracers, FilterErrorFrames: !c.SendErrorFrames, + FilterIdleFrames: !c.SendIdleFrames, SamplesPerSecond: int(c.SamplesPerSecond), MapScaleFactor: int(c.MapScaleFactor), KernelVersionCheck: !c.NoKernelVersionCheck, @@ -341,7 +348,7 @@ func Run(mainCtx context.Context, c *config.Config) ExitCode { // change this log line update also the system test. log.Printf("Attached sched monitor") - if err := startTraceHandling(mainCtx, rep, intervals, trc, traceHandlerCacheSize); err != nil { + if err := startTraceHandling(mainCtx, trc); err != nil { return failure("Failed to start trace handling: %v", err) }