diff options
Diffstat (limited to 'vendor/go.opentelemetry.io/otel')
82 files changed, 1556 insertions, 1060 deletions
| diff --git a/vendor/go.opentelemetry.io/otel/.gitignore b/vendor/go.opentelemetry.io/otel/.gitignore index 895c7664b..ae8577ef3 100644 --- a/vendor/go.opentelemetry.io/otel/.gitignore +++ b/vendor/go.opentelemetry.io/otel/.gitignore @@ -12,11 +12,3 @@ go.work  go.work.sum  gen/ - -/example/dice/dice -/example/namedtracer/namedtracer -/example/otel-collector/otel-collector -/example/opencensus/opencensus -/example/passthrough/passthrough -/example/prometheus/prometheus -/example/zipkin/zipkin diff --git a/vendor/go.opentelemetry.io/otel/.golangci.yml b/vendor/go.opentelemetry.io/otel/.golangci.yml index d9abe194d..ce3f40b60 100644 --- a/vendor/go.opentelemetry.io/otel/.golangci.yml +++ b/vendor/go.opentelemetry.io/otel/.golangci.yml @@ -22,13 +22,16 @@ linters:      - govet      - ineffassign      - misspell +    - perfsprint      - revive      - staticcheck      - tenv +    - testifylint      - typecheck      - unconvert      - unused      - unparam +    - usestdlibvars  issues:    # Maximum issues count per one linter. @@ -60,16 +63,17 @@ issues:        text: "calls to (.+) only in main[(][)] or init[(][)] functions"        linters:          - revive -    # It's okay to not run gosec in a test. +    # It's okay to not run gosec and perfsprint in a test.      - path: _test\.go        linters:          - gosec -    # Igonoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand) +        - perfsprint +    # Ignoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)      # as we commonly use it in tests and examples.      - text: "G404:"        linters:          - gosec -    # Igonoring gosec G402: TLS MinVersion too low +    # Ignoring gosec G402: TLS MinVersion too low      # as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well.      - text: "G402: TLS MinVersion too low."        linters: @@ -94,6 +98,13 @@ linters-settings:            - pkg: "crypto/md5"            - pkg: "crypto/sha1"            - pkg: "crypto/**/pkix" +      auto/sdk: +        files: +          - "!internal/global/trace.go" +          - "~internal/global/trace_test.go" +        deny: +          - pkg: "go.opentelemetry.io/auto/sdk" +            desc: Do not use SDK from automatic instrumentation.        otlp-internal:          files:            - "!**/exporters/otlp/internal/**/*.go" @@ -126,8 +137,6 @@ linters-settings:            - "**/metric/**/*.go"            - "**/bridge/*.go"            - "**/bridge/**/*.go" -          - "**/example/*.go" -          - "**/example/**/*.go"            - "**/trace/*.go"            - "**/trace/**/*.go"            - "**/log/*.go" @@ -155,6 +164,12 @@ linters-settings:      locale: US      ignore-words:        - cancelled +  perfsprint: +    err-error: true +    errorf: true +    int-conversion: true +    sprintf1: true +    strconcat: true    revive:      # Sets the default failure confidence.      # This means that linting errors with less than 0.8 confidence will be ignored. @@ -302,3 +317,9 @@ linters-settings:        # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value        - name: waitgroup-by-value          disabled: false +  testifylint: +    enable-all: true +    disable: +      - float-compare +      - go-require +      - require-error diff --git a/vendor/go.opentelemetry.io/otel/CHANGELOG.md b/vendor/go.opentelemetry.io/otel/CHANGELOG.md index 6107c17b8..599d59cd1 100644 --- a/vendor/go.opentelemetry.io/otel/CHANGELOG.md +++ b/vendor/go.opentelemetry.io/otel/CHANGELOG.md @@ -11,6 +11,141 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm  <!-- Released section -->  <!-- Don't change this section unless doing release --> +## [1.34.0/0.56.0/0.10.0] 2025-01-17 + +### Changed + +- Remove the notices from `Logger` to make the whole Logs API user-facing in `go.opentelemetry.io/otel/log`. (#6167) + +### Fixed + +- Relax minimum Go version to 1.22.0 in various modules. (#6073) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` client is corrected from `otlphttpgrpc` to `otlptracegrpc`. (#6143) +- The `Type` name logged for the `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlphttpgrpc` client is corrected from `otlphttphttp` to `otlptracehttp`. (#6143) + +## [1.33.0/0.55.0/0.9.0/0.0.12] 2024-12-12 + +### Added + +- Add `Reset` method to `SpanRecorder` in `go.opentelemetry.io/otel/sdk/trace/tracetest`. (#5994) +- Add `EnabledInstrument` interface in `go.opentelemetry.io/otel/sdk/metric/internal/x`. +  This is an experimental interface that is implemented by synchronous instruments provided by `go.opentelemetry.io/otel/sdk/metric`. +  Users can use it to avoid performing computationally expensive operations when recording measurements. +  It does not fall within the scope of the OpenTelemetry Go versioning and stability [policy](./VERSIONING.md) and it may be changed in backwards incompatible ways or removed in feature releases. (#6016) + +### Changed + +- The default global API now supports full auto-instrumentation from the `go.opentelemetry.io/auto` package. +  See that package for more information. (#5920) +- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5929) +- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5929) +- Propagate non-retryable error messages to client in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5929) +- Performance improvements for attribute value `AsStringSlice`, `AsFloat64Slice`, `AsInt64Slice`, `AsBoolSlice`. (#6011) +- Change `EnabledParameters` to have a `Severity` field instead of a getter and setter in `go.opentelemetry.io/otel/log`. (#6009) + +### Fixed + +- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#5954) +- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5954) +- Fix inconsistent request body closing in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5954) +- Fix invalid exemplar keys in `go.opentelemetry.io/otel/exporters/prometheus`. (#5995) +- Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/trace`. (#5997) +- Fix attribute value truncation in `go.opentelemetry.io/otel/sdk/log`. (#6032) + +## [1.32.0/0.54.0/0.8.0/0.0.11] 2024-11-08 + +### Added + +- Add `go.opentelemetry.io/otel/sdk/metric/exemplar.AlwaysOffFilter`, which can be used to disable exemplar recording. (#5850) +- Add `go.opentelemetry.io/otel/sdk/metric.WithExemplarFilter`, which can be used to configure the exemplar filter used by the metrics SDK. (#5850) +- Add `ExemplarReservoirProviderSelector` and `DefaultExemplarReservoirProviderSelector` to `go.opentelemetry.io/otel/sdk/metric`, which defines the exemplar reservoir to use based on the aggregation of the metric. (#5861) +- Add `ExemplarReservoirProviderSelector` to `go.opentelemetry.io/otel/sdk/metric.Stream` to allow using views to configure the exemplar reservoir to use for a metric. (#5861) +- Add `ReservoirProvider`, `HistogramReservoirProvider` and `FixedSizeReservoirProvider` to `go.opentelemetry.io/otel/sdk/metric/exemplar` to make it convenient to use providers of Reservoirs. (#5861) +- The `go.opentelemetry.io/otel/semconv/v1.27.0` package. +  The package contains semantic conventions from the `v1.27.0` version of the OpenTelemetry Semantic Conventions. (#5894) +- Add `Attributes attribute.Set` field to `Scope` in `go.opentelemetry.io/otel/sdk/instrumentation`. (#5903) +- Add `Attributes attribute.Set` field to `ScopeRecords` in `go.opentelemetry.io/otel/log/logtest`. (#5927) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` adds instrumentation scope attributes. (#5934) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` adds instrumentation scope attributes. (#5934) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` adds instrumentation scope attributes. (#5935) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp` adds instrumentation scope attributes. (#5935) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc` adds instrumentation scope attributes. (#5933) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp` adds instrumentation scope attributes. (#5933) +- `go.opentelemetry.io/otel/exporters/prometheus` adds instrumentation scope attributes in `otel_scope_info` metric as labels. (#5932) + +### Changed + +- Support scope attributes and make them as identifying for `Tracer` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/trace`. (#5924) +- Support scope attributes and make them as identifying for `Meter` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/metric`. (#5926) +- Support scope attributes and make them as identifying for `Logger` in `go.opentelemetry.io/otel` and `go.opentelemetry.io/otel/sdk/log`. (#5925) +- Make schema URL and scope attributes as identifying for `Tracer` in `go.opentelemetry.io/otel/bridge/opentracing`. (#5931) +- Clear unneeded slice elements to allow GC to collect the objects in `go.opentelemetry.io/otel/sdk/metric` and `go.opentelemetry.io/otel/sdk/trace`. (#5804) + +### Fixed + +- Global MeterProvider registration unwraps global instrument Observers, the undocumented Unwrap() methods are now private. (#5881) +- `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5892) +- `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5911) +- `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc` now keeps the metadata already present in the context when `WithHeaders` is used. (#5915) +- Fix `go.opentelemetry.io/otel/exporters/prometheus` trying to add exemplars to Gauge metrics, which is unsupported. (#5912) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`. (#5944) +- Fix `WithEndpointURL` to always use a secure connection when an https URL is passed in `go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`. (#5944) +- Fix incorrect metrics generated from callbacks when multiple readers are used in `go.opentelemetry.io/otel/sdk/metric`. (#5900) + +### Removed + +- Remove all examples under `go.opentelemetry.io/otel/example` as they are moved to [Contrib repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples). (#5930) + +## [1.31.0/0.53.0/0.7.0/0.0.10] 2024-10-11 + +### Added + +- Add `go.opentelemetry.io/otel/sdk/metric/exemplar` package which includes `Exemplar`, `Filter`, `TraceBasedFilter`, `AlwaysOnFilter`, `HistogramReservoir`, `FixedSizeReservoir`, `Reservoir`, `Value` and `ValueType` types. These will be used for configuring the exemplar reservoir for the metrics sdk. (#5747, #5862) +- Add `WithExportBufferSize` option to log batch processor.(#5877) + +### Changed + +- Enable exemplars by default in `go.opentelemetry.io/otel/sdk/metric`. Exemplars can be disabled by setting `OTEL_METRICS_EXEMPLAR_FILTER=always_off` (#5778) +- `Logger.Enabled` in `go.opentelemetry.io/otel/log` now accepts a newly introduced `EnabledParameters` type instead of `Record`. (#5791) +- `FilterProcessor.Enabled` in `go.opentelemetry.io/otel/sdk/log/internal/x` now accepts `EnabledParameters` instead of `Record`. (#5791) +- The `Record` type in `go.opentelemetry.io/otel/log` is no longer comparable. (#5847) +- Performance improvements for the trace SDK `SetAttributes` method in `Span`. (#5864) +- Reduce memory allocations for the `Event` and `Link` lists in `Span`. (#5858) +- Performance improvements for the trace SDK `AddEvent`, `AddLink`, `RecordError` and `End` methods in `Span`. (#5874) + +### Deprecated + +- Deprecate all examples under `go.opentelemetry.io/otel/example` as they are moved to [Contrib repository](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples). (#5854) + +### Fixed + +- The race condition for multiple `FixedSize` exemplar reservoirs identified in #5814 is resolved. (#5819) +- Fix log records duplication in case of heterogeneous resource attributes by correctly mapping each log record to it's resource and scope. (#5803) +- Fix timer channel drain to avoid hanging on Go 1.23. (#5868) +- Fix delegation for global meter providers, and panic when calling otel.SetMeterProvider. (#5827) +- Change the `reflect.TypeOf` to use a nil pointer to not allocate on the heap unless necessary. (#5827) + +## [1.30.0/0.52.0/0.6.0/0.0.9] 2024-09-09 + +### Added + +- Support `OTEL_EXPORTER_OTLP_LOGS_INSECURE` and `OTEL_EXPORTER_OTLP_INSECURE` environments in `go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#5739) +- The `WithResource` option for `NewMeterProvider` now merges the provided resources with the ones from environment variables. (#5773) +- The `WithResource` option for `NewLoggerProvider` now merges the provided resources with the ones from environment variables. (#5773) +- Add UTF-8 support to `go.opentelemetry.io/otel/exporters/prometheus`. (#5755) + +### Fixed + +- Fix memory leak in the global `MeterProvider` when identical instruments are repeatedly created. (#5754) +- Fix panic on instruments creation when setting meter provider. (#5758) +- Fix an issue where `SetMeterProvider` in `go.opentelemetry.io/otel` might miss the delegation for instruments and registries. (#5780) + +### Removed + +- Drop support for [Go 1.21]. (#5736, #5740, #5800) +  ## [1.29.0/0.51.0/0.5.0] 2024-08-23  This release is the last to support [Go 1.21]. @@ -1895,7 +2030,7 @@ with major version 0.  - Setting error status while recording error with Span from oteltest package. (#1729)  - The concept of a remote and local Span stored in a context is unified to just the current Span.    Because of this `"go.opentelemetry.io/otel/trace".RemoteSpanContextFromContext` is removed as it is no longer needed. -  Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContex` can be used to return the current Span. +  Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContext` can be used to return the current Span.    If needed, that Span's `SpanContext.IsRemote()` can then be used to determine if it is remote or not. (#1731)  - The `HasRemoteParent` field of the `"go.opentelemetry.io/otel/sdk/trace".SamplingParameters` is removed.    This field is redundant to the information returned from the `Remote` method of the `SpanContext` held in the `ParentContext` field. (#1749) @@ -2469,7 +2604,7 @@ This release migrates the default OpenTelemetry SDK into its own Go module, deco  - Prometheus exporter will not apply stale updates or forget inactive metrics. (#903)  - Add test for api.standard `HTTPClientAttributesFromHTTPRequest`. (#905)  - Bump github.com/golangci/golangci-lint from 1.27.0 to 1.28.1 in /tools. (#901, #913) -- Update otel-colector example to use the v0.5.0 collector. (#915) +- Update otel-collector example to use the v0.5.0 collector. (#915)  - The `grpctrace` instrumentation uses a span name conforming to the OpenTelemetry semantic conventions (does not contain a leading slash (`/`)). (#922)  - The `grpctrace` instrumentation includes an `rpc.method` attribute now set to the gRPC method name. (#900, #922)  - The `grpctrace` instrumentation `rpc.service` attribute now contains the package name if one exists. @@ -3062,7 +3197,12 @@ It contains api and sdk for trace and meter.  - CircleCI build CI manifest files.  - CODEOWNERS file to track owners of this project. -[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.29.0...HEAD +[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.34.0...HEAD +[1.34.0/0.56.0/0.10.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.34.0 +[1.33.0/0.55.0/0.9.0/0.0.12]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.33.0 +[1.32.0/0.54.0/0.8.0/0.0.11]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.32.0 +[1.31.0/0.53.0/0.7.0/0.0.10]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.31.0 +[1.30.0/0.52.0/0.6.0/0.0.9]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.30.0  [1.29.0/0.51.0/0.5.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.29.0  [1.28.0/0.50.0/0.4.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.28.0  [1.27.0/0.49.0/0.3.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.27.0 diff --git a/vendor/go.opentelemetry.io/otel/CODEOWNERS b/vendor/go.opentelemetry.io/otel/CODEOWNERS index 5904bb707..945a07d2b 100644 --- a/vendor/go.opentelemetry.io/otel/CODEOWNERS +++ b/vendor/go.opentelemetry.io/otel/CODEOWNERS @@ -12,6 +12,6 @@  #  https://help.github.com/en/articles/about-code-owners  # -* @MrAlias @XSAM @dashpole @MadVikingGod @pellared @hanyuancheung @dmathieu +* @MrAlias @XSAM @dashpole @pellared @dmathieu -CODEOWNERS @MrAlias @MadVikingGod @pellared @dashpole @XSAM @dmathieu +CODEOWNERS @MrAlias @pellared @dashpole @XSAM @dmathieu diff --git a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md index b7402576f..22a2e9dbd 100644 --- a/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md +++ b/vendor/go.opentelemetry.io/otel/CONTRIBUTING.md @@ -578,7 +578,10 @@ See also:  The tests should never leak goroutines.  Use the term `ConcurrentSafe` in the test name when it aims to verify the -absence of race conditions. +absence of race conditions. The top-level tests with this term will be run +many times in the `test-concurrent-safe` CI job to increase the chance of +catching concurrency issues. This does not apply to subtests when this term +is not in their root name.  ### Internal packages @@ -626,13 +629,14 @@ should be canceled.  ## Approvers and Maintainers -### Approvers +### Triagers + +- [Cheng-Zhen Yang](https://github.com/scorpionknifes), Independent -- [Chester Cheung](https://github.com/hanyuancheung), Tencent +### Approvers  ### Maintainers -- [Aaron Clawson](https://github.com/MadVikingGod), LightStep  - [Damien Mathieu](https://github.com/dmathieu), Elastic  - [David Ashpole](https://github.com/dashpole), Google  - [Robert Pająk](https://github.com/pellared), Splunk @@ -641,11 +645,13 @@ should be canceled.  ### Emeritus -- [Liz Fong-Jones](https://github.com/lizthegrey), Honeycomb -- [Gustavo Silva Paiva](https://github.com/paivagustavo), LightStep -- [Josh MacDonald](https://github.com/jmacd), LightStep -- [Anthony Mirabella](https://github.com/Aneurysm9), AWS -- [Evan Torrie](https://github.com/evantorrie), Yahoo +- [Aaron Clawson](https://github.com/MadVikingGod) +- [Anthony Mirabella](https://github.com/Aneurysm9) +- [Chester Cheung](https://github.com/hanyuancheung) +- [Evan Torrie](https://github.com/evantorrie) +- [Gustavo Silva Paiva](https://github.com/paivagustavo) +- [Josh MacDonald](https://github.com/jmacd) +- [Liz Fong-Jones](https://github.com/lizthegrey)  ### Become an Approver or a Maintainer diff --git a/vendor/go.opentelemetry.io/otel/Makefile b/vendor/go.opentelemetry.io/otel/Makefile index 070b1e57d..a7f6d8cc6 100644 --- a/vendor/go.opentelemetry.io/otel/Makefile +++ b/vendor/go.opentelemetry.io/otel/Makefile @@ -14,8 +14,8 @@ TIMEOUT = 60  .DEFAULT_GOAL := precommit  .PHONY: precommit ci -precommit: generate license-check misspell go-mod-tidy golangci-lint-fix verify-readmes verify-mods test-default -ci: generate license-check lint vanity-import-check verify-readmes verify-mods build test-default check-clean-work-tree test-coverage +precommit: generate toolchain-check license-check misspell go-mod-tidy golangci-lint-fix verify-readmes verify-mods test-default +ci: generate toolchain-check license-check lint vanity-import-check verify-readmes verify-mods build test-default check-clean-work-tree test-coverage  # Tools @@ -54,9 +54,6 @@ $(TOOLS)/stringer: PACKAGE=golang.org/x/tools/cmd/stringer  PORTO = $(TOOLS)/porto  $(TOOLS)/porto: PACKAGE=github.com/jcchavezs/porto/cmd/porto -GOJQ = $(TOOLS)/gojq -$(TOOLS)/gojq: PACKAGE=github.com/itchyny/gojq/cmd/gojq -  GOTMPL = $(TOOLS)/gotmpl  $(GOTMPL): PACKAGE=go.opentelemetry.io/build-tools/gotmpl @@ -67,7 +64,7 @@ GOVULNCHECK = $(TOOLS)/govulncheck  $(TOOLS)/govulncheck: PACKAGE=golang.org/x/vuln/cmd/govulncheck  .PHONY: tools -tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(GOJQ) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE) +tools: $(CROSSLINK) $(GOLANGCI_LINT) $(MISSPELL) $(GOCOVMERGE) $(STRINGER) $(PORTO) $(SEMCONVGEN) $(MULTIMOD) $(SEMCONVKIT) $(GOTMPL) $(GORELEASE)  # Virtualized python tools via docker @@ -145,12 +142,14 @@ build-tests/%:  # Tests -TEST_TARGETS := test-default test-bench test-short test-verbose test-race +TEST_TARGETS := test-default test-bench test-short test-verbose test-race test-concurrent-safe  .PHONY: $(TEST_TARGETS) test  test-default test-race: ARGS=-race  test-bench:   ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=.  test-short:   ARGS=-short  test-verbose: ARGS=-v -race +test-concurrent-safe: ARGS=-run=ConcurrentSafe -count=100 -race +test-concurrent-safe: TIMEOUT=120  $(TEST_TARGETS): test  test: $(OTEL_GO_MOD_DIRS:%=test/%)  test/%: DIR=$* @@ -236,6 +235,16 @@ govulncheck/%: $(GOVULNCHECK)  codespell: $(CODESPELL)  	@$(DOCKERPY) $(CODESPELL) +.PHONY: toolchain-check +toolchain-check: +	@toolchainRes=$$(for f in $(ALL_GO_MOD_DIRS); do \ +	           awk '/^toolchain/ { found=1; next } END { if (found) print FILENAME }' $$f/go.mod; \ +	done); \ +	if [ -n "$${toolchainRes}" ]; then \ +			echo "toolchain checking failed:"; echo "$${toolchainRes}"; \ +			exit 1; \ +	fi +  .PHONY: license-check  license-check:  	@licRes=$$(for f in $$(find . -type f \( -iname '*.go' -o -iname '*.sh' \) ! -path '**/third_party/*' ! -path './.git/*' ) ; do \ @@ -261,7 +270,7 @@ SEMCONVPKG ?= "semconv/"  semconv-generate: $(SEMCONVGEN) $(SEMCONVKIT)  	[ "$(TAG)" ] || ( echo "TAG unset: missing opentelemetry semantic-conventions tag"; exit 1 )  	[ "$(OTEL_SEMCONV_REPO)" ] || ( echo "OTEL_SEMCONV_REPO unset: missing path to opentelemetry semantic-conventions repo"; exit 1 ) -	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)" +	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=attribute_group -p conventionType=trace -f attribute_group.go -z "$(SEMCONVPKG)/capitalizations.txt" -t "$(SEMCONVPKG)/template.j2" -s "$(TAG)"  	$(SEMCONVGEN) -i "$(OTEL_SEMCONV_REPO)/model/." --only=metric  -f metric.go -t "$(SEMCONVPKG)/metric_template.j2" -s "$(TAG)"  	$(SEMCONVKIT) -output "$(SEMCONVPKG)/$(TAG)" -tag "$(TAG)" diff --git a/vendor/go.opentelemetry.io/otel/README.md b/vendor/go.opentelemetry.io/otel/README.md index 657df3471..d9a192076 100644 --- a/vendor/go.opentelemetry.io/otel/README.md +++ b/vendor/go.opentelemetry.io/otel/README.md @@ -1,6 +1,6 @@  # OpenTelemetry-Go -[](https://github.com/open-telemetry/opentelemetry-go/actions?query=workflow%3Aci+branch%3Amain) +[](https://github.com/open-telemetry/opentelemetry-go/actions/workflows/ci.yml)  [](https://app.codecov.io/gh/open-telemetry/opentelemetry-go?branch=main)  [](https://pkg.go.dev/go.opentelemetry.io/otel)  [](https://goreportcard.com/report/go.opentelemetry.io/otel) @@ -51,25 +51,18 @@ Currently, this project supports the following environments.  |----------|------------|--------------|  | Ubuntu   | 1.23       | amd64        |  | Ubuntu   | 1.22       | amd64        | -| Ubuntu   | 1.21       | amd64        |  | Ubuntu   | 1.23       | 386          |  | Ubuntu   | 1.22       | 386          | -| Ubuntu   | 1.21       | 386          |  | Linux    | 1.23       | arm64        |  | Linux    | 1.22       | arm64        | -| Linux    | 1.21       | arm64        |  | macOS 13 | 1.23       | amd64        |  | macOS 13 | 1.22       | amd64        | -| macOS 13 | 1.21       | amd64        |  | macOS    | 1.23       | arm64        |  | macOS    | 1.22       | arm64        | -| macOS    | 1.21       | arm64        |  | Windows  | 1.23       | amd64        |  | Windows  | 1.22       | amd64        | -| Windows  | 1.21       | amd64        |  | Windows  | 1.23       | 386          |  | Windows  | 1.22       | 386          | -| Windows  | 1.21       | 386          |  While this project should work for other systems, no compatibility guarantees  are made for those systems currently. @@ -96,8 +89,8 @@ If you need to extend the telemetry an instrumentation library provides or want  to build your own instrumentation for your application directly you will need  to use the  [Go otel](https://pkg.go.dev/go.opentelemetry.io/otel) -package. The included [examples](./example/) are a good way to see some -practical uses of this process. +package. The [examples](https://github.com/open-telemetry/opentelemetry-go-contrib/tree/main/examples) +are a good way to see some practical uses of this process.  ### Export diff --git a/vendor/go.opentelemetry.io/otel/RELEASING.md b/vendor/go.opentelemetry.io/otel/RELEASING.md index 59992984d..4ebef4f9d 100644 --- a/vendor/go.opentelemetry.io/otel/RELEASING.md +++ b/vendor/go.opentelemetry.io/otel/RELEASING.md @@ -111,17 +111,6 @@ It is critical you make sure the version you push upstream is correct.  Finally create a Release for the new `<new tag>` on GitHub.  The release body should include all the release notes from the Changelog for this release. -## Verify Examples - -After releasing verify that examples build outside of the repository. - -``` -./verify_examples.sh -``` - -The script copies examples into a different directory removes any `replace` declarations in `go.mod` and builds them. -This ensures they build with the published release, not the local copy. -  ## Post-Release  ### Contrib Repository @@ -141,6 +130,6 @@ Importantly, bump any package versions referenced to be the latest one you just  Bump the dependencies in the following Go services: -- [`accountingservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accountingservice) -- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkoutservice) -- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/productcatalogservice) +- [`accounting`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/accounting) +- [`checkoutservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/checkout) +- [`productcatalogservice`](https://github.com/open-telemetry/opentelemetry-demo/tree/main/src/product-catalog) diff --git a/vendor/go.opentelemetry.io/otel/VERSIONING.md b/vendor/go.opentelemetry.io/otel/VERSIONING.md index 412f1e362..b8cb605c1 100644 --- a/vendor/go.opentelemetry.io/otel/VERSIONING.md +++ b/vendor/go.opentelemetry.io/otel/VERSIONING.md @@ -26,7 +26,7 @@ is designed so the following goals can be achieved.        go.opentelemetry.io/otel/v2 v2.0.1`) and in the package import path        (e.g., `import "go.opentelemetry.io/otel/v2/trace"`). This includes the        paths used in `go get` commands (e.g., `go get -      go.opentelemetry.io/otel/v2@v2.0.1`.  Note there is both a `/v2` and a +      go.opentelemetry.io/otel/v2@v2.0.1`).  Note there is both a `/v2` and a        `@v2.0.1` in that example. One way to think about it is that the module        name now includes the `/v2`, so include `/v2` whenever you are using the        module name). diff --git a/vendor/go.opentelemetry.io/otel/attribute/set.go b/vendor/go.opentelemetry.io/otel/attribute/set.go index bff9c7fdb..6cbefcead 100644 --- a/vendor/go.opentelemetry.io/otel/attribute/set.go +++ b/vendor/go.opentelemetry.io/otel/attribute/set.go @@ -347,45 +347,25 @@ func computeDistinct(kvs []KeyValue) Distinct {  func computeDistinctFixed(kvs []KeyValue) interface{} {  	switch len(kvs) {  	case 1: -		ptr := new([1]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [1]KeyValue(kvs)  	case 2: -		ptr := new([2]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [2]KeyValue(kvs)  	case 3: -		ptr := new([3]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [3]KeyValue(kvs)  	case 4: -		ptr := new([4]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [4]KeyValue(kvs)  	case 5: -		ptr := new([5]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [5]KeyValue(kvs)  	case 6: -		ptr := new([6]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [6]KeyValue(kvs)  	case 7: -		ptr := new([7]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [7]KeyValue(kvs)  	case 8: -		ptr := new([8]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [8]KeyValue(kvs)  	case 9: -		ptr := new([9]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [9]KeyValue(kvs)  	case 10: -		ptr := new([10]KeyValue) -		copy((*ptr)[:], kvs) -		return *ptr +		return [10]KeyValue(kvs)  	default:  		return nil  	} diff --git a/vendor/go.opentelemetry.io/otel/baggage/baggage.go b/vendor/go.opentelemetry.io/otel/baggage/baggage.go index b3569e95e..0e1fe2422 100644 --- a/vendor/go.opentelemetry.io/otel/baggage/baggage.go +++ b/vendor/go.opentelemetry.io/otel/baggage/baggage.go @@ -50,7 +50,7 @@ type Property struct {  // component boundaries may impose their own restrictions on Property key.  // For example, the W3C Baggage specification restricts the Property keys to strings that  // satisfy the token definition from RFC7230, Section 3.2.6. -// For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key. +// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.  func NewKeyProperty(key string) (Property, error) {  	if !validateBaggageName(key) {  		return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) @@ -90,7 +90,7 @@ func NewKeyValueProperty(key, value string) (Property, error) {  // component boundaries may impose their own restrictions on Property key.  // For example, the W3C Baggage specification restricts the Property keys to strings that  // satisfy the token definition from RFC7230, Section 3.2.6. -// For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key. +// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key.  func NewKeyValuePropertyRaw(key, value string) (Property, error) {  	if !validateBaggageName(key) {  		return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, key) @@ -287,7 +287,7 @@ func NewMember(key, value string, props ...Property) (Member, error) {  // component boundaries may impose their own restrictions on baggage key.  // For example, the W3C Baggage specification restricts the baggage keys to strings that  // satisfy the token definition from RFC7230, Section 3.2.6. -// For maximum compatibility, alpha-numeric value are strongly recommended to be used as baggage key. +// For maximum compatibility, alphanumeric value are strongly recommended to be used as baggage key.  func NewMemberRaw(key, value string, props ...Property) (Member, error) {  	m := Member{  		key:        key, @@ -355,7 +355,7 @@ func parseMember(member string) (Member, error) {  }  // replaceInvalidUTF8Sequences replaces invalid UTF-8 sequences with '�'. -func replaceInvalidUTF8Sequences(cap int, unescapeVal string) string { +func replaceInvalidUTF8Sequences(c int, unescapeVal string) string {  	if utf8.ValidString(unescapeVal) {  		return unescapeVal  	} @@ -363,7 +363,7 @@ func replaceInvalidUTF8Sequences(cap int, unescapeVal string) string {  	// https://github.com/w3c/baggage/blob/8c215efbeebd3fa4b1aceb937a747e56444f22f3/baggage/HTTP_HEADER_FORMAT.md?plain=1#L69  	var b strings.Builder -	b.Grow(cap) +	b.Grow(c)  	for i := 0; i < len(unescapeVal); {  		r, size := utf8.DecodeRuneInString(unescapeVal[i:])  		if r == utf8.RuneError && size == 1 { diff --git a/vendor/go.opentelemetry.io/otel/codes/codes.go b/vendor/go.opentelemetry.io/otel/codes/codes.go index 2acbac354..49a35b122 100644 --- a/vendor/go.opentelemetry.io/otel/codes/codes.go +++ b/vendor/go.opentelemetry.io/otel/codes/codes.go @@ -5,6 +5,7 @@ package codes // import "go.opentelemetry.io/otel/codes"  import (  	"encoding/json" +	"errors"  	"fmt"  	"strconv"  ) @@ -63,7 +64,7 @@ func (c *Code) UnmarshalJSON(b []byte) error {  		return nil  	}  	if c == nil { -		return fmt.Errorf("nil receiver passed to UnmarshalJSON") +		return errors.New("nil receiver passed to UnmarshalJSON")  	}  	var x interface{} diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/instrumentation.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/instrumentation.go index f6dd3decc..2e7690e43 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/instrumentation.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/instrumentation.go @@ -13,7 +13,8 @@ func InstrumentationScope(il instrumentation.Scope) *commonpb.InstrumentationSco  		return nil  	}  	return &commonpb.InstrumentationScope{ -		Name:    il.Name, -		Version: il.Version, +		Name:       il.Name, +		Version:    il.Version, +		Attributes: Iterator(il.Attributes.Iter()),  	}  } diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go index 81157a71c..bf27ef022 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform/span.go @@ -97,8 +97,8 @@ func span(sd tracesdk.ReadOnlySpan) *tracepb.Span {  		SpanId:                 sid[:],  		TraceState:             sd.SpanContext().TraceState().String(),  		Status:                 status(sd.Status().Code, sd.Status().Description), -		StartTimeUnixNano:      uint64(sd.StartTime().UnixNano()), -		EndTimeUnixNano:        uint64(sd.EndTime().UnixNano()), +		StartTimeUnixNano:      uint64(max(0, sd.StartTime().UnixNano())), // nolint:gosec // Overflow checked. +		EndTimeUnixNano:        uint64(max(0, sd.EndTime().UnixNano())),   // nolint:gosec // Overflow checked.  		Links:                  links(sd.Links()),  		Kind:                   spanKind(sd.SpanKind()),  		Name:                   sd.Name(), @@ -178,7 +178,7 @@ func buildSpanFlags(sc trace.SpanContext) uint32 {  		flags |= tracepb.SpanFlags_SPAN_FLAGS_CONTEXT_IS_REMOTE_MASK  	} -	return uint32(flags) +	return uint32(flags) // nolint:gosec // Flags is a bitmask and can't be negative  }  // spanEvents transforms span Events to an OTLP span events. @@ -192,7 +192,7 @@ func spanEvents(es []tracesdk.Event) []*tracepb.Span_Event {  	for i := 0; i < len(es); i++ {  		events[i] = &tracepb.Span_Event{  			Name:                   es[i].Name, -			TimeUnixNano:           uint64(es[i].Time.UnixNano()), +			TimeUnixNano:           uint64(max(0, es[i].Time.UnixNano())), // nolint:gosec // Overflow checked.  			Attributes:             KeyValues(es[i].Attributes),  			DroppedAttributesCount: clampUint32(es[i].DroppedAttributeCount),  		} diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go index 3993df927..8409b5f8f 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/client.go @@ -229,7 +229,12 @@ func (c *client) exportContext(parent context.Context) (context.Context, context  	}  	if c.metadata.Len() > 0 { -		ctx = metadata.NewOutgoingContext(ctx, c.metadata) +		md := c.metadata +		if outMD, ok := metadata.FromOutgoingContext(ctx); ok { +			md = metadata.Join(md, outMD) +		} + +		ctx = metadata.NewOutgoingContext(ctx, md)  	}  	// Unify the client stopCtx with the parent. @@ -289,7 +294,7 @@ func (c *client) MarshalLog() interface{} {  		Type     string  		Endpoint string  	}{ -		Type:     "otlphttpgrpc", +		Type:     "otlptracegrpc",  		Endpoint: c.endpoint,  	}  } diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go index 8f84a7996..0a317d926 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig/options.go @@ -98,7 +98,7 @@ func cleanPath(urlPath string, defaultPath string) string {  		return defaultPath  	}  	if !path.IsAbs(tmp) { -		tmp = fmt.Sprintf("/%s", tmp) +		tmp = "/" + tmp  	}  	return tmp  } @@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {  	if cfg.ServiceConfig != "" {  		cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))  	} -	// Priroritize GRPCCredentials over Insecure (passing both is an error). +	// Prioritize GRPCCredentials over Insecure (passing both is an error).  	if cfg.Traces.GRPCCredentials != nil {  		cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))  	} else if cfg.Traces.Insecure { @@ -278,9 +278,7 @@ func WithEndpointURL(v string) GenericOption {  		cfg.Traces.Endpoint = u.Host  		cfg.Traces.URLPath = u.Path -		if u.Scheme != "https" { -			cfg.Traces.Insecure = true -		} +		cfg.Traces.Insecure = u.Scheme != "https"  		return cfg  	}) diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go index bb2f3ffd1..16c006b2c 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/client.go @@ -166,8 +166,7 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc  			}()  		} -		switch sc := resp.StatusCode; { -		case sc >= 200 && sc <= 299: +		if sc := resp.StatusCode; sc >= 200 && sc <= 299 {  			// Success, do not retry.  			// Read the partial success message, if any.  			var respData bytes.Buffer @@ -194,34 +193,33 @@ func (d *client) UploadTraces(ctx context.Context, protoSpans []*tracepb.Resourc  				}  			}  			return nil - -		case sc == http.StatusTooManyRequests, -			sc == http.StatusBadGateway, -			sc == http.StatusServiceUnavailable, -			sc == http.StatusGatewayTimeout: -			// Retry-able failures. -			rErr := newResponseError(resp.Header, nil) - -			// server may return a message with the response -			// body, so we read it to include in the error -			// message to be returned. It will help in -			// debugging the actual issue. -			var respData bytes.Buffer -			if _, err := io.Copy(&respData, resp.Body); err != nil { -				_ = resp.Body.Close() -				return err -			} - -			// overwrite the error message with the response body -			// if it is not empty -			if respStr := strings.TrimSpace(respData.String()); respStr != "" { -				// Include response for context. -				e := errors.New(respStr) -				rErr = newResponseError(resp.Header, e) -			} -			return rErr +		} +		// Error cases. + +		// server may return a message with the response +		// body, so we read it to include in the error +		// message to be returned. It will help in +		// debugging the actual issue. +		var respData bytes.Buffer +		if _, err := io.Copy(&respData, resp.Body); err != nil { +			return err +		} +		respStr := strings.TrimSpace(respData.String()) +		if len(respStr) == 0 { +			respStr = "(empty)" +		} +		bodyErr := fmt.Errorf("body: %s", respStr) + +		switch resp.StatusCode { +		case http.StatusTooManyRequests, +			http.StatusBadGateway, +			http.StatusServiceUnavailable, +			http.StatusGatewayTimeout: +			// Retryable failure. +			return newResponseError(resp.Header, bodyErr)  		default: -			return fmt.Errorf("failed to send to %s: %s", request.URL, resp.Status) +			// Non-retryable failure. +			return fmt.Errorf("failed to send to %s: %s (%w)", request.URL, resp.Status, bodyErr)  		}  	})  } @@ -278,7 +276,7 @@ func (d *client) MarshalLog() interface{} {  		Endpoint string  		Insecure bool  	}{ -		Type:     "otlphttphttp", +		Type:     "otlptracehttp",  		Endpoint: d.cfg.Endpoint,  		Insecure: d.cfg.Insecure,  	} @@ -328,7 +326,7 @@ func newResponseError(header http.Header, wrapped error) error {  func (e retryableError) Error() string {  	if e.err != nil { -		return fmt.Sprintf("retry-able request failure: %s", e.err.Error()) +		return "retry-able request failure: " + e.err.Error()  	}  	return "retry-able request failure" diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go index 43534cbfb..9fea75ad1 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/doc.go @@ -22,7 +22,7 @@ target URL to which the exporter sends telemetry.  The value must contain a scheme ("http" or "https") and host.  The value may additionally contain a port and a path.  The value should not contain a query string or fragment. -The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WitnInsecure], and [WithURLPath] options. +The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithURLPath] options.  OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS (default: none) -  key-value pairs used as headers associated with HTTP requests. diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go index 2ebbc752f..6a9c4d3a6 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig/options.go @@ -98,7 +98,7 @@ func cleanPath(urlPath string, defaultPath string) string {  		return defaultPath  	}  	if !path.IsAbs(tmp) { -		tmp = fmt.Sprintf("/%s", tmp) +		tmp = "/" + tmp  	}  	return tmp  } @@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {  	if cfg.ServiceConfig != "" {  		cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))  	} -	// Priroritize GRPCCredentials over Insecure (passing both is an error). +	// Prioritize GRPCCredentials over Insecure (passing both is an error).  	if cfg.Traces.GRPCCredentials != nil {  		cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))  	} else if cfg.Traces.Insecure { @@ -278,9 +278,7 @@ func WithEndpointURL(v string) GenericOption {  		cfg.Traces.Endpoint = u.Host  		cfg.Traces.URLPath = u.Path -		if u.Scheme != "https" { -			cfg.Traces.Insecure = true -		} +		cfg.Traces.Insecure = u.Scheme != "https"  		return cfg  	}) diff --git a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go index 780992528..f156ee667 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go +++ b/vendor/go.opentelemetry.io/otel/exporters/otlp/otlptrace/version.go @@ -5,5 +5,5 @@ package otlptrace // import "go.opentelemetry.io/otel/exporters/otlp/otlptrace"  // Version is the current release version of the OpenTelemetry OTLP trace exporter in use.  func Version() string { -	return "1.29.0" +	return "1.34.0"  } diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go index a10ab7f1d..660675dd6 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go +++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/config.go @@ -7,6 +7,7 @@ import (  	"strings"  	"github.com/prometheus/client_golang/prometheus" +	"github.com/prometheus/common/model"  	"go.opentelemetry.io/otel/attribute"  	"go.opentelemetry.io/otel/sdk/metric" @@ -131,7 +132,10 @@ func WithoutScopeInfo() Option {  // have special behavior based on their name.  func WithNamespace(ns string) Option {  	return optionFunc(func(cfg config) config { -		ns = sanitizeName(ns) +		if model.NameValidationScheme != model.UTF8Validation { +			// Only sanitize if prometheus does not support UTF-8. +			ns = model.EscapeName(ns, model.NameEscapingScheme) +		}  		if !strings.HasSuffix(ns, "_") {  			// namespace and metric names should be separated with an underscore,  			// adds a trailing underscore if there is not one already. diff --git a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go index d2e387e60..50c95a16f 100644 --- a/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go +++ b/vendor/go.opentelemetry.io/otel/exporters/prometheus/exporter.go @@ -11,11 +11,10 @@ import (  	"slices"  	"strings"  	"sync" -	"unicode" -	"unicode/utf8"  	"github.com/prometheus/client_golang/prometheus"  	dto "github.com/prometheus/client_model/go" +	"github.com/prometheus/common/model"  	"google.golang.org/protobuf/proto"  	"go.opentelemetry.io/otel" @@ -34,15 +33,14 @@ const (  	scopeInfoMetricName  = "otel_scope_info"  	scopeInfoDescription = "Instrumentation Scope metadata" +	scopeNameLabel    = "otel_scope_name" +	scopeVersionLabel = "otel_scope_version" +  	traceIDExemplarKey = "trace_id"  	spanIDExemplarKey  = "span_id"  ) -var ( -	scopeInfoKeys = [2]string{"otel_scope_name", "otel_scope_version"} - -	errScopeInvalid = errors.New("invalid scope") -) +var errScopeInvalid = errors.New("invalid scope")  // Exporter is a Prometheus Exporter that embeds the OTel metric.Reader  // interface for easy instantiation with a MeterProvider. @@ -188,7 +186,11 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {  	}  	for _, scopeMetrics := range metrics.ScopeMetrics { -		var keys, values [2]string +		n := len(c.resourceKeyVals.keys) + 2 // resource attrs + scope name + scope version +		kv := keyVals{ +			keys: make([]string, 0, n), +			vals: make([]string, 0, n), +		}  		if !c.disableScopeInfo {  			scopeInfo, err := c.scopeInfo(scopeMetrics.Scope) @@ -203,10 +205,13 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {  			ch <- scopeInfo -			keys = scopeInfoKeys -			values = [2]string{scopeMetrics.Scope.Name, scopeMetrics.Scope.Version} +			kv.keys = append(kv.keys, scopeNameLabel, scopeVersionLabel) +			kv.vals = append(kv.vals, scopeMetrics.Scope.Name, scopeMetrics.Scope.Version)  		} +		kv.keys = append(kv.keys, c.resourceKeyVals.keys...) +		kv.vals = append(kv.vals, c.resourceKeyVals.vals...) +  		for _, m := range scopeMetrics.Metrics {  			typ := c.metricType(m)  			if typ == nil { @@ -225,25 +230,27 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {  			switch v := m.Data.(type) {  			case metricdata.Histogram[int64]: -				addHistogramMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addHistogramMetric(ch, v, m, name, kv)  			case metricdata.Histogram[float64]: -				addHistogramMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addHistogramMetric(ch, v, m, name, kv)  			case metricdata.Sum[int64]: -				addSumMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addSumMetric(ch, v, m, name, kv)  			case metricdata.Sum[float64]: -				addSumMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addSumMetric(ch, v, m, name, kv)  			case metricdata.Gauge[int64]: -				addGaugeMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addGaugeMetric(ch, v, m, name, kv)  			case metricdata.Gauge[float64]: -				addGaugeMetric(ch, v, m, keys, values, name, c.resourceKeyVals) +				addGaugeMetric(ch, v, m, name, kv)  			}  		}  	}  } -func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) { +func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogram metricdata.Histogram[N], m metricdata.Metrics, name string, kv keyVals) {  	for _, dp := range histogram.DataPoints { -		keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV) +		keys, values := getAttrs(dp.Attributes) +		keys = append(keys, kv.keys...) +		values = append(values, kv.vals...)  		desc := prometheus.NewDesc(name, m.Description, keys, nil)  		buckets := make(map[float64]uint64, len(dp.Bounds)) @@ -263,14 +270,16 @@ func addHistogramMetric[N int64 | float64](ch chan<- prometheus.Metric, histogra  	}  } -func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) { +func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata.Sum[N], m metricdata.Metrics, name string, kv keyVals) {  	valueType := prometheus.CounterValue  	if !sum.IsMonotonic {  		valueType = prometheus.GaugeValue  	}  	for _, dp := range sum.DataPoints { -		keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV) +		keys, values := getAttrs(dp.Attributes) +		keys = append(keys, kv.keys...) +		values = append(values, kv.vals...)  		desc := prometheus.NewDesc(name, m.Description, keys, nil)  		m, err := prometheus.NewConstMetric(desc, valueType, float64(dp.Value), values...) @@ -278,14 +287,20 @@ func addSumMetric[N int64 | float64](ch chan<- prometheus.Metric, sum metricdata  			otel.Handle(err)  			continue  		} -		m = addExemplars(m, dp.Exemplars) +		// GaugeValues don't support Exemplars at this time +		// https://github.com/prometheus/client_golang/blob/aef8aedb4b6e1fb8ac1c90790645169125594096/prometheus/metric.go#L199 +		if valueType != prometheus.GaugeValue { +			m = addExemplars(m, dp.Exemplars) +		}  		ch <- m  	}  } -func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, ks, vs [2]string, name string, resourceKV keyVals) { +func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metricdata.Gauge[N], m metricdata.Metrics, name string, kv keyVals) {  	for _, dp := range gauge.DataPoints { -		keys, values := getAttrs(dp.Attributes, ks, vs, resourceKV) +		keys, values := getAttrs(dp.Attributes) +		keys = append(keys, kv.keys...) +		values = append(values, kv.vals...)  		desc := prometheus.NewDesc(name, m.Description, keys, nil)  		m, err := prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(dp.Value), values...) @@ -297,61 +312,58 @@ func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metric  	}  } -// getAttrs parses the attribute.Set to two lists of matching Prometheus-style -// keys and values. It sanitizes invalid characters and handles duplicate keys -// (due to sanitization) by sorting and concatenating the values following the spec. -func getAttrs(attrs attribute.Set, ks, vs [2]string, resourceKV keyVals) ([]string, []string) { -	keysMap := make(map[string][]string) -	itr := attrs.Iter() -	for itr.Next() { -		kv := itr.Attribute() -		key := strings.Map(sanitizeRune, string(kv.Key)) -		if _, ok := keysMap[key]; !ok { -			keysMap[key] = []string{kv.Value.Emit()} -		} else { -			// if the sanitized key is a duplicate, append to the list of keys -			keysMap[key] = append(keysMap[key], kv.Value.Emit()) -		} -	} - +// getAttrs converts the attribute.Set to two lists of matching Prometheus-style +// keys and values. +func getAttrs(attrs attribute.Set) ([]string, []string) {  	keys := make([]string, 0, attrs.Len())  	values := make([]string, 0, attrs.Len()) -	for key, vals := range keysMap { -		keys = append(keys, key) -		slices.Sort(vals) -		values = append(values, strings.Join(vals, ";")) -	} - -	if ks[0] != "" { -		keys = append(keys, ks[:]...) -		values = append(values, vs[:]...) -	} +	itr := attrs.Iter() -	for idx := range resourceKV.keys { -		keys = append(keys, resourceKV.keys[idx]) -		values = append(values, resourceKV.vals[idx]) +	if model.NameValidationScheme == model.UTF8Validation { +		// Do not perform sanitization if prometheus supports UTF-8. +		for itr.Next() { +			kv := itr.Attribute() +			keys = append(keys, string(kv.Key)) +			values = append(values, kv.Value.Emit()) +		} +	} else { +		// It sanitizes invalid characters and handles duplicate keys +		// (due to sanitization) by sorting and concatenating the values following the spec. +		keysMap := make(map[string][]string) +		for itr.Next() { +			kv := itr.Attribute() +			key := model.EscapeName(string(kv.Key), model.NameEscapingScheme) +			if _, ok := keysMap[key]; !ok { +				keysMap[key] = []string{kv.Value.Emit()} +			} else { +				// if the sanitized key is a duplicate, append to the list of keys +				keysMap[key] = append(keysMap[key], kv.Value.Emit()) +			} +		} +		for key, vals := range keysMap { +			keys = append(keys, key) +			slices.Sort(vals) +			values = append(values, strings.Join(vals, ";")) +		}  	} -  	return keys, values  }  func createInfoMetric(name, description string, res *resource.Resource) (prometheus.Metric, error) { -	keys, values := getAttrs(*res.Set(), [2]string{}, [2]string{}, keyVals{}) +	keys, values := getAttrs(*res.Set())  	desc := prometheus.NewDesc(name, description, keys, nil)  	return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...)  }  func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, error) { -	keys := scopeInfoKeys[:] -	desc := prometheus.NewDesc(scopeInfoMetricName, scopeInfoDescription, keys, nil) -	return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), scope.Name, scope.Version) -} +	attrs := make([]attribute.KeyValue, 0, scope.Attributes.Len()+2) // resource attrs + scope name + scope version +	attrs = append(attrs, scope.Attributes.ToSlice()...) +	attrs = append(attrs, attribute.String(scopeNameLabel, scope.Name)) +	attrs = append(attrs, attribute.String(scopeVersionLabel, scope.Version)) -func sanitizeRune(r rune) rune { -	if unicode.IsLetter(r) || unicode.IsDigit(r) || r == ':' || r == '_' { -		return r -	} -	return '_' +	keys, values := getAttrs(attribute.NewSet(attrs...)) +	desc := prometheus.NewDesc(scopeInfoMetricName, scopeInfoDescription, keys, nil) +	return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), values...)  }  var unitSuffixes = map[string]string{ @@ -392,7 +404,11 @@ var unitSuffixes = map[string]string{  // getName returns the sanitized name, prefixed with the namespace and suffixed with unit.  func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string { -	name := sanitizeName(m.Name) +	name := m.Name +	if model.NameValidationScheme != model.UTF8Validation { +		// Only sanitize if prometheus does not support UTF-8. +		name = model.EscapeName(name, model.NameEscapingScheme) +	}  	addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER  	if addCounterSuffix {  		// Remove the _total suffix here, as we will re-add the total suffix @@ -411,59 +427,6 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {  	return name  } -func sanitizeName(n string) string { -	// This algorithm is based on strings.Map from Go 1.19. -	const replacement = '_' - -	valid := func(i int, r rune) bool { -		// Taken from -		// https://github.com/prometheus/common/blob/dfbc25bd00225c70aca0d94c3c4bb7744f28ace0/model/metric.go#L92-L102 -		if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || r == '_' || r == ':' || (r >= '0' && r <= '9' && i > 0) { -			return true -		} -		return false -	} - -	// This output buffer b is initialized on demand, the first time a -	// character needs to be replaced. -	var b strings.Builder -	for i, c := range n { -		if valid(i, c) { -			continue -		} - -		if i == 0 && c >= '0' && c <= '9' { -			// Prefix leading number with replacement character. -			b.Grow(len(n) + 1) -			_ = b.WriteByte(byte(replacement)) -			break -		} -		b.Grow(len(n)) -		_, _ = b.WriteString(n[:i]) -		_ = b.WriteByte(byte(replacement)) -		width := utf8.RuneLen(c) -		n = n[i+width:] -		break -	} - -	// Fast path for unchanged input. -	if b.Cap() == 0 { // b.Grow was not called above. -		return n -	} - -	for _, c := range n { -		// Due to inlining, it is more performant to invoke WriteByte rather then -		// WriteRune. -		if valid(1, c) { // We are guaranteed to not be at the start. -			_ = b.WriteByte(byte(c)) -		} else { -			_ = b.WriteByte(byte(replacement)) -		} -	} - -	return b.String() -} -  func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {  	switch v := m.Data.(type) {  	case metricdata.Histogram[int64], metricdata.Histogram[float64]: @@ -489,7 +452,7 @@ func (c *collector) createResourceAttributes(res *resource.Resource) {  	defer c.mu.Unlock()  	resourceAttrs, _ := res.Set().Filter(c.resourceAttributesFilter) -	resourceKeys, resourceValues := getAttrs(resourceAttrs, [2]string{}, [2]string{}, keyVals{}) +	resourceKeys, resourceValues := getAttrs(resourceAttrs)  	c.resourceKeyVals = keyVals{keys: resourceKeys, vals: resourceValues}  } @@ -584,7 +547,8 @@ func addExemplars[N int64 | float64](m prometheus.Metric, exemplars []metricdata  func attributesToLabels(attrs []attribute.KeyValue) prometheus.Labels {  	labels := make(map[string]string)  	for _, attr := range attrs { -		labels[string(attr.Key)] = attr.Value.Emit() +		key := model.EscapeName(string(attr.Key), model.NameEscapingScheme) +		labels[key] = attr.Value.Emit()  	}  	return labels  } diff --git a/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go b/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go index 822d84794..691d96c75 100644 --- a/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go +++ b/vendor/go.opentelemetry.io/otel/internal/attribute/attribute.go @@ -49,12 +49,11 @@ func AsBoolSlice(v interface{}) []bool {  	if rv.Type().Kind() != reflect.Array {  		return nil  	} -	var zero bool -	correctLen := rv.Len() -	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) -	cpy := reflect.New(correctType) -	_ = reflect.Copy(cpy.Elem(), rv) -	return cpy.Elem().Slice(0, correctLen).Interface().([]bool) +	cpy := make([]bool, rv.Len()) +	if len(cpy) > 0 { +		_ = reflect.Copy(reflect.ValueOf(cpy), rv) +	} +	return cpy  }  // AsInt64Slice converts an int64 array into a slice into with same elements as array. @@ -63,12 +62,11 @@ func AsInt64Slice(v interface{}) []int64 {  	if rv.Type().Kind() != reflect.Array {  		return nil  	} -	var zero int64 -	correctLen := rv.Len() -	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) -	cpy := reflect.New(correctType) -	_ = reflect.Copy(cpy.Elem(), rv) -	return cpy.Elem().Slice(0, correctLen).Interface().([]int64) +	cpy := make([]int64, rv.Len()) +	if len(cpy) > 0 { +		_ = reflect.Copy(reflect.ValueOf(cpy), rv) +	} +	return cpy  }  // AsFloat64Slice converts a float64 array into a slice into with same elements as array. @@ -77,12 +75,11 @@ func AsFloat64Slice(v interface{}) []float64 {  	if rv.Type().Kind() != reflect.Array {  		return nil  	} -	var zero float64 -	correctLen := rv.Len() -	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) -	cpy := reflect.New(correctType) -	_ = reflect.Copy(cpy.Elem(), rv) -	return cpy.Elem().Slice(0, correctLen).Interface().([]float64) +	cpy := make([]float64, rv.Len()) +	if len(cpy) > 0 { +		_ = reflect.Copy(reflect.ValueOf(cpy), rv) +	} +	return cpy  }  // AsStringSlice converts a string array into a slice into with same elements as array. @@ -91,10 +88,9 @@ func AsStringSlice(v interface{}) []string {  	if rv.Type().Kind() != reflect.Array {  		return nil  	} -	var zero string -	correctLen := rv.Len() -	correctType := reflect.ArrayOf(correctLen, reflect.TypeOf(zero)) -	cpy := reflect.New(correctType) -	_ = reflect.Copy(cpy.Elem(), rv) -	return cpy.Elem().Slice(0, correctLen).Interface().([]string) +	cpy := make([]string, rv.Len()) +	if len(cpy) > 0 { +		_ = reflect.Copy(reflect.ValueOf(cpy), rv) +	} +	return cpy  } diff --git a/vendor/go.opentelemetry.io/otel/internal/global/instruments.go b/vendor/go.opentelemetry.io/otel/internal/global/instruments.go index 3a0cc42f6..ae92a4251 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/instruments.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/instruments.go @@ -13,7 +13,7 @@ import (  // unwrapper unwraps to return the underlying instrument implementation.  type unwrapper interface { -	Unwrap() metric.Observable +	unwrap() metric.Observable  }  type afCounter struct { @@ -40,7 +40,7 @@ func (i *afCounter) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *afCounter) Unwrap() metric.Observable { +func (i *afCounter) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Float64ObservableCounter)  	} @@ -71,7 +71,7 @@ func (i *afUpDownCounter) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *afUpDownCounter) Unwrap() metric.Observable { +func (i *afUpDownCounter) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Float64ObservableUpDownCounter)  	} @@ -102,7 +102,7 @@ func (i *afGauge) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *afGauge) Unwrap() metric.Observable { +func (i *afGauge) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Float64ObservableGauge)  	} @@ -133,7 +133,7 @@ func (i *aiCounter) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *aiCounter) Unwrap() metric.Observable { +func (i *aiCounter) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Int64ObservableCounter)  	} @@ -164,7 +164,7 @@ func (i *aiUpDownCounter) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *aiUpDownCounter) Unwrap() metric.Observable { +func (i *aiUpDownCounter) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Int64ObservableUpDownCounter)  	} @@ -195,7 +195,7 @@ func (i *aiGauge) setDelegate(m metric.Meter) {  	i.delegate.Store(ctr)  } -func (i *aiGauge) Unwrap() metric.Observable { +func (i *aiGauge) unwrap() metric.Observable {  	if ctr := i.delegate.Load(); ctr != nil {  		return ctr.(metric.Int64ObservableGauge)  	} diff --git a/vendor/go.opentelemetry.io/otel/internal/global/meter.go b/vendor/go.opentelemetry.io/otel/internal/global/meter.go index cfd1df9bf..a6acd8dca 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/meter.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/meter.go @@ -5,8 +5,9 @@ package global // import "go.opentelemetry.io/otel/internal/global"  import (  	"container/list" +	"context" +	"reflect"  	"sync" -	"sync/atomic"  	"go.opentelemetry.io/otel/metric"  	"go.opentelemetry.io/otel/metric/embedded" @@ -66,6 +67,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me  		name:    name,  		version: c.InstrumentationVersion(),  		schema:  c.SchemaURL(), +		attrs:   c.InstrumentationAttributes(),  	}  	if p.meters == nil { @@ -76,7 +78,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me  		return val  	} -	t := &meter{name: name, opts: opts} +	t := &meter{name: name, opts: opts, instruments: make(map[instID]delegatedInstrument)}  	p.meters[key] = t  	return t  } @@ -92,17 +94,29 @@ type meter struct {  	opts []metric.MeterOption  	mtx         sync.Mutex -	instruments []delegatedInstrument +	instruments map[instID]delegatedInstrument  	registry list.List -	delegate atomic.Value // metric.Meter +	delegate metric.Meter  }  type delegatedInstrument interface {  	setDelegate(metric.Meter)  } +// instID are the identifying properties of a instrument. +type instID struct { +	// name is the name of the stream. +	name string +	// description is the description of the stream. +	description string +	// kind defines the functional group of the instrument. +	kind reflect.Type +	// unit is the unit of the stream. +	unit string +} +  // setDelegate configures m to delegate all Meter functionality to Meters  // created by provider.  // @@ -110,12 +124,12 @@ type delegatedInstrument interface {  //  // It is guaranteed by the caller that this happens only once.  func (m *meter) setDelegate(provider metric.MeterProvider) { -	meter := provider.Meter(m.name, m.opts...) -	m.delegate.Store(meter) -  	m.mtx.Lock()  	defer m.mtx.Unlock() +	meter := provider.Meter(m.name, m.opts...) +	m.delegate = meter +  	for _, inst := range m.instruments {  		inst.setDelegate(meter)  	} @@ -133,169 +147,336 @@ func (m *meter) setDelegate(provider metric.MeterProvider) {  }  func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64Counter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64Counter(name, options...) +	} + +	cfg := metric.NewInt64CounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*siCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64Counter), nil +	}  	i := &siCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64UpDownCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64UpDownCounter(name, options...) +	} + +	cfg := metric.NewInt64UpDownCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*siUpDownCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64UpDownCounter), nil +	}  	i := &siUpDownCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOption) (metric.Int64Histogram, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64Histogram(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64Histogram(name, options...) +	} + +	cfg := metric.NewInt64HistogramConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*siHistogram)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64Histogram), nil +	}  	i := &siHistogram{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64Gauge(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64Gauge(name, options...) +	} + +	cfg := metric.NewInt64GaugeConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*siGauge)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64Gauge), nil +	}  	i := &siGauge{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64ObservableCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64ObservableCounter(name, options...) +	} + +	cfg := metric.NewInt64ObservableCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*aiCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64ObservableCounter), nil +	}  	i := &aiCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64ObservableUpDownCounter(name string, options ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64ObservableUpDownCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64ObservableUpDownCounter(name, options...) +	} + +	cfg := metric.NewInt64ObservableUpDownCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*aiUpDownCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64ObservableUpDownCounter), nil +	}  	i := &aiUpDownCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Int64ObservableGauge(name string, options ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Int64ObservableGauge(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Int64ObservableGauge(name, options...) +	} + +	cfg := metric.NewInt64ObservableGaugeConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*aiGauge)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Int64ObservableGauge), nil +	}  	i := &aiGauge{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64Counter(name string, options ...metric.Float64CounterOption) (metric.Float64Counter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64Counter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64Counter(name, options...) +	} + +	cfg := metric.NewFloat64CounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*sfCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64Counter), nil +	}  	i := &sfCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64UpDownCounter(name string, options ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64UpDownCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64UpDownCounter(name, options...) +	} + +	cfg := metric.NewFloat64UpDownCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*sfUpDownCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64UpDownCounter), nil +	}  	i := &sfUpDownCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64Histogram(name string, options ...metric.Float64HistogramOption) (metric.Float64Histogram, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64Histogram(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64Histogram(name, options...) +	} + +	cfg := metric.NewFloat64HistogramConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*sfHistogram)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64Histogram), nil +	}  	i := &sfHistogram{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64Gauge(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64Gauge(name, options...) +	} + +	cfg := metric.NewFloat64GaugeConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*sfGauge)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64Gauge), nil +	}  	i := &sfGauge{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64ObservableCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64ObservableCounter(name, options...) +	} + +	cfg := metric.NewFloat64ObservableCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*afCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64ObservableCounter), nil +	}  	i := &afCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64ObservableUpDownCounter(name string, options ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64ObservableUpDownCounter(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64ObservableUpDownCounter(name, options...) +	} + +	cfg := metric.NewFloat64ObservableUpDownCounterConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*afUpDownCounter)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64ObservableUpDownCounter), nil +	}  	i := &afUpDownCounter{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  func (m *meter) Float64ObservableGauge(name string, options ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		return del.Float64ObservableGauge(name, options...) -	}  	m.mtx.Lock()  	defer m.mtx.Unlock() + +	if m.delegate != nil { +		return m.delegate.Float64ObservableGauge(name, options...) +	} + +	cfg := metric.NewFloat64ObservableGaugeConfig(options...) +	id := instID{ +		name:        name, +		kind:        reflect.TypeOf((*afGauge)(nil)), +		description: cfg.Description(), +		unit:        cfg.Unit(), +	} +	if f, ok := m.instruments[id]; ok { +		return f.(metric.Float64ObservableGauge), nil +	}  	i := &afGauge{name: name, opts: options} -	m.instruments = append(m.instruments, i) +	m.instruments[id] = i  	return i, nil  }  // RegisterCallback captures the function that will be called during Collect.  func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) (metric.Registration, error) { -	if del, ok := m.delegate.Load().(metric.Meter); ok { -		insts = unwrapInstruments(insts) -		return del.RegisterCallback(f, insts...) -	} -  	m.mtx.Lock()  	defer m.mtx.Unlock() +	if m.delegate != nil { +		return m.delegate.RegisterCallback(unwrapCallback(f), unwrapInstruments(insts)...) +	} +  	reg := ®istration{instruments: insts, function: f}  	e := m.registry.PushBack(reg)  	reg.unreg = func() error { @@ -307,15 +488,11 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)  	return reg, nil  } -type wrapped interface { -	unwrap() metric.Observable -} -  func unwrapInstruments(instruments []metric.Observable) []metric.Observable {  	out := make([]metric.Observable, 0, len(instruments))  	for _, inst := range instruments { -		if in, ok := inst.(wrapped); ok { +		if in, ok := inst.(unwrapper); ok {  			out = append(out, in.unwrap())  		} else {  			out = append(out, inst) @@ -335,9 +512,61 @@ type registration struct {  	unregMu sync.Mutex  } -func (c *registration) setDelegate(m metric.Meter) { -	insts := unwrapInstruments(c.instruments) +type unwrapObs struct { +	embedded.Observer +	obs metric.Observer +} +// unwrapFloat64Observable returns an expected metric.Float64Observable after +// unwrapping the global object. +func unwrapFloat64Observable(inst metric.Float64Observable) metric.Float64Observable { +	if unwrapped, ok := inst.(unwrapper); ok { +		if floatObs, ok := unwrapped.unwrap().(metric.Float64Observable); ok { +			// Note: if the unwrapped object does not +			// unwrap as an observable for either of the +			// predicates here, it means an internal bug in +			// this package.  We avoid logging an error in +			// this case, because the SDK has to try its +			// own type conversion on the object.  The SDK +			// will see this and be forced to respond with +			// its own error. +			// +			// This code uses a double-nested if statement +			// to avoid creating a branch that is +			// impossible to cover. +			inst = floatObs +		} +	} +	return inst +} + +// unwrapInt64Observable returns an expected metric.Int64Observable after +// unwrapping the global object. +func unwrapInt64Observable(inst metric.Int64Observable) metric.Int64Observable { +	if unwrapped, ok := inst.(unwrapper); ok { +		if unint, ok := unwrapped.unwrap().(metric.Int64Observable); ok { +			// See the comment in unwrapFloat64Observable(). +			inst = unint +		} +	} +	return inst +} + +func (uo *unwrapObs) ObserveFloat64(inst metric.Float64Observable, value float64, opts ...metric.ObserveOption) { +	uo.obs.ObserveFloat64(unwrapFloat64Observable(inst), value, opts...) +} + +func (uo *unwrapObs) ObserveInt64(inst metric.Int64Observable, value int64, opts ...metric.ObserveOption) { +	uo.obs.ObserveInt64(unwrapInt64Observable(inst), value, opts...) +} + +func unwrapCallback(f metric.Callback) metric.Callback { +	return func(ctx context.Context, obs metric.Observer) error { +		return f(ctx, &unwrapObs{obs: obs}) +	} +} + +func (c *registration) setDelegate(m metric.Meter) {  	c.unregMu.Lock()  	defer c.unregMu.Unlock() @@ -346,9 +575,10 @@ func (c *registration) setDelegate(m metric.Meter) {  		return  	} -	reg, err := m.RegisterCallback(c.function, insts...) +	reg, err := m.RegisterCallback(unwrapCallback(c.function), unwrapInstruments(c.instruments)...)  	if err != nil {  		GetErrorHandler().Handle(err) +		return  	}  	c.unreg = reg.Unregister diff --git a/vendor/go.opentelemetry.io/otel/internal/global/trace.go b/vendor/go.opentelemetry.io/otel/internal/global/trace.go index e31f442b4..8982aa0dc 100644 --- a/vendor/go.opentelemetry.io/otel/internal/global/trace.go +++ b/vendor/go.opentelemetry.io/otel/internal/global/trace.go @@ -25,6 +25,7 @@ import (  	"sync"  	"sync/atomic" +	"go.opentelemetry.io/auto/sdk"  	"go.opentelemetry.io/otel/attribute"  	"go.opentelemetry.io/otel/codes"  	"go.opentelemetry.io/otel/trace" @@ -87,6 +88,7 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T  		name:    name,  		version: c.InstrumentationVersion(),  		schema:  c.SchemaURL(), +		attrs:   c.InstrumentationAttributes(),  	}  	if p.tracers == nil { @@ -102,7 +104,12 @@ func (p *tracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T  	return t  } -type il struct{ name, version, schema string } +type il struct { +	name    string +	version string +	schema  string +	attrs   attribute.Set +}  // tracer is a placeholder for a trace.Tracer.  // @@ -139,6 +146,30 @@ func (t *tracer) Start(ctx context.Context, name string, opts ...trace.SpanStart  		return delegate.(trace.Tracer).Start(ctx, name, opts...)  	} +	return t.newSpan(ctx, autoInstEnabled, name, opts) +} + +// autoInstEnabled determines if the auto-instrumentation SDK span is returned +// from the tracer when not backed by a delegate and auto-instrumentation has +// attached to this process. +// +// The auto-instrumentation is expected to overwrite this value to true when it +// attaches. By default, this will point to false and mean a tracer will return +// a nonRecordingSpan by default. +var autoInstEnabled = new(bool) + +func (t *tracer) newSpan(ctx context.Context, autoSpan *bool, name string, opts []trace.SpanStartOption) (context.Context, trace.Span) { +	// autoInstEnabled is passed to newSpan via the autoSpan parameter. This is +	// so the auto-instrumentation can define a uprobe for (*t).newSpan and be +	// provided with the address of the bool autoInstEnabled points to. It +	// needs to be a parameter so that pointer can be reliably determined, it +	// should not be read from the global. + +	if *autoSpan { +		tracer := sdk.TracerProvider().Tracer(t.name, t.opts...) +		return tracer.Start(ctx, name, opts...) +	} +  	s := nonRecordingSpan{sc: trace.SpanContextFromContext(ctx), tracer: t}  	ctx = trace.ContextWithSpan(ctx, s)  	return ctx, s diff --git a/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go b/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go index 9b1da2c02..b2fe3e41d 100644 --- a/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go +++ b/vendor/go.opentelemetry.io/otel/internal/rawhelpers.go @@ -20,7 +20,8 @@ func RawToBool(r uint64) bool {  }  func Int64ToRaw(i int64) uint64 { -	return uint64(i) +	// Assumes original was a valid int64 (overflow not checked). +	return uint64(i) // nolint: gosec  }  func RawToInt64(r uint64) int64 { diff --git a/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go b/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go index cf23db778..f8435d8f2 100644 --- a/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go +++ b/vendor/go.opentelemetry.io/otel/metric/asyncfloat64.go @@ -213,7 +213,7 @@ type Float64Observer interface {  }  // Float64Callback is a function registered with a Meter that makes -// observations for a Float64Observerable instrument it is registered with. +// observations for a Float64Observable instrument it is registered with.  // Calls to the Float64Observer record measurement values for the  // Float64Observable.  // diff --git a/vendor/go.opentelemetry.io/otel/metric/asyncint64.go b/vendor/go.opentelemetry.io/otel/metric/asyncint64.go index c82ba5324..e079aaef1 100644 --- a/vendor/go.opentelemetry.io/otel/metric/asyncint64.go +++ b/vendor/go.opentelemetry.io/otel/metric/asyncint64.go @@ -212,7 +212,7 @@ type Int64Observer interface {  }  // Int64Callback is a function registered with a Meter that makes observations -// for an Int64Observerable instrument it is registered with. Calls to the +// for an Int64Observable instrument it is registered with. Calls to the  // Int64Observer record measurement values for the Int64Observable.  //  // The function needs to complete in a finite amount of time and the deadline diff --git a/vendor/go.opentelemetry.io/otel/metric/instrument.go b/vendor/go.opentelemetry.io/otel/metric/instrument.go index ea52e4023..a535782e1 100644 --- a/vendor/go.opentelemetry.io/otel/metric/instrument.go +++ b/vendor/go.opentelemetry.io/otel/metric/instrument.go @@ -351,7 +351,7 @@ func WithAttributeSet(attributes attribute.Set) MeasurementOption {  //  //	cp := make([]attribute.KeyValue, len(attributes))  //	copy(cp, attributes) -//	WithAttributes(attribute.NewSet(cp...)) +//	WithAttributeSet(attribute.NewSet(cp...))  //  // [attribute.NewSet] may modify the passed attributes so this will make a copy  // of attributes before creating a set in order to ensure this function is diff --git a/vendor/go.opentelemetry.io/otel/renovate.json b/vendor/go.opentelemetry.io/otel/renovate.json index 8c5ac55ca..4f80c898a 100644 --- a/vendor/go.opentelemetry.io/otel/renovate.json +++ b/vendor/go.opentelemetry.io/otel/renovate.json @@ -15,10 +15,12 @@        "enabled": true      },      { -      "matchFileNames": ["internal/tools/**"], -      "matchManagers": ["gomod"], -      "matchDepTypes": ["indirect"], -      "enabled": false +      "matchPackageNames": ["google.golang.org/genproto/googleapis/**"], +      "groupName": "googleapis" +    }, +    { +      "matchPackageNames": ["golang.org/x/**"], +      "groupName": "golang.org/x"      }    ]  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go b/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go index 728115045..34852a47b 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go +++ b/vendor/go.opentelemetry.io/otel/sdk/instrumentation/scope.go @@ -3,6 +3,8 @@  package instrumentation // import "go.opentelemetry.io/otel/sdk/instrumentation" +import "go.opentelemetry.io/otel/attribute" +  // Scope represents the instrumentation scope.  type Scope struct {  	// Name is the name of the instrumentation scope. This should be the @@ -12,4 +14,6 @@ type Scope struct {  	Version string  	// SchemaURL of the telemetry emitted by the scope.  	SchemaURL string +	// Attributes of the telemetry emitted by the scope. +	Attributes attribute.Set  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go index bbe7bf671..203cd9d65 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/config.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/config.go @@ -5,17 +5,22 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"  import (  	"context" -	"fmt" +	"errors" +	"os" +	"strings"  	"sync" +	"go.opentelemetry.io/otel" +	"go.opentelemetry.io/otel/sdk/metric/exemplar"  	"go.opentelemetry.io/otel/sdk/resource"  )  // config contains configuration options for a MeterProvider.  type config struct { -	res     *resource.Resource -	readers []Reader -	views   []View +	res            *resource.Resource +	readers        []Reader +	views          []View +	exemplarFilter exemplar.Filter  }  // readerSignals returns a force-flush and shutdown function for a @@ -39,25 +44,13 @@ func (c config) readerSignals() (forceFlush, shutdown func(context.Context) erro  // value.  func unify(funcs []func(context.Context) error) func(context.Context) error {  	return func(ctx context.Context) error { -		var errs []error +		var err error  		for _, f := range funcs { -			if err := f(ctx); err != nil { -				errs = append(errs, err) +			if e := f(ctx); e != nil { +				err = errors.Join(err, e)  			}  		} -		return unifyErrors(errs) -	} -} - -// unifyErrors combines multiple errors into a single error. -func unifyErrors(errs []error) error { -	switch len(errs) { -	case 0: -		return nil -	case 1: -		return errs[0] -	default: -		return fmt.Errorf("%v", errs) +		return err  	}  } @@ -75,7 +68,13 @@ func unifyShutdown(funcs []func(context.Context) error) func(context.Context) er  // newConfig returns a config configured with options.  func newConfig(options []Option) config { -	conf := config{res: resource.Default()} +	conf := config{ +		res:            resource.Default(), +		exemplarFilter: exemplar.TraceBasedFilter, +	} +	for _, o := range meterProviderOptionsFromEnv() { +		conf = o.apply(conf) +	}  	for _, o := range options {  		conf = o.apply(conf)  	} @@ -103,7 +102,11 @@ func (o optionFunc) apply(conf config) config {  // go.opentelemetry.io/otel/sdk/resource package will be used.  func WithResource(res *resource.Resource) Option {  	return optionFunc(func(conf config) config { -		conf.res = res +		var err error +		conf.res, err = resource.Merge(resource.Environment(), res) +		if err != nil { +			otel.Handle(err) +		}  		return conf  	})  } @@ -135,3 +138,35 @@ func WithView(views ...View) Option {  		return cfg  	})  } + +// WithExemplarFilter configures the exemplar filter. +// +// The exemplar filter determines which measurements are offered to the +// exemplar reservoir, but the exemplar reservoir makes the final decision of +// whether to store an exemplar. +// +// By default, the [exemplar.SampledFilter] +// is used. Exemplars can be entirely disabled by providing the +// [exemplar.AlwaysOffFilter]. +func WithExemplarFilter(filter exemplar.Filter) Option { +	return optionFunc(func(cfg config) config { +		cfg.exemplarFilter = filter +		return cfg +	}) +} + +func meterProviderOptionsFromEnv() []Option { +	var opts []Option +	// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar +	const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER" + +	switch strings.ToLower(strings.TrimSpace(os.Getenv(filterEnvKey))) { +	case "always_on": +		opts = append(opts, WithExemplarFilter(exemplar.AlwaysOnFilter)) +	case "always_off": +		opts = append(opts, WithExemplarFilter(exemplar.AlwaysOffFilter)) +	case "trace_based": +		opts = append(opts, WithExemplarFilter(exemplar.TraceBasedFilter)) +	} +	return opts +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go index 82619da78..0335b8ae4 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar.go @@ -4,51 +4,49 @@  package metric // import "go.opentelemetry.io/otel/sdk/metric"  import ( -	"os"  	"runtime" -	"slices" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar" -	"go.opentelemetry.io/otel/sdk/metric/internal/x" +	"go.opentelemetry.io/otel/attribute" +	"go.opentelemetry.io/otel/sdk/metric/exemplar" +	"go.opentelemetry.io/otel/sdk/metric/internal/aggregate"  ) -// reservoirFunc returns the appropriately configured exemplar reservoir -// creation func based on the passed InstrumentKind and user defined -// environment variables. -// -// Note: This will only return non-nil values when the experimental exemplar -// feature is enabled and the OTEL_METRICS_EXEMPLAR_FILTER environment variable -// is not set to always_off. -func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredReservoir[N] { -	if !x.Exemplars.Enabled() { -		return nil -	} -	// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/configuration/sdk-environment-variables.md#exemplar -	const filterEnvKey = "OTEL_METRICS_EXEMPLAR_FILTER" +// ExemplarReservoirProviderSelector selects the +// [exemplar.ReservoirProvider] to use +// based on the [Aggregation] of the metric. +type ExemplarReservoirProviderSelector func(Aggregation) exemplar.ReservoirProvider -	var filter exemplar.Filter - -	switch os.Getenv(filterEnvKey) { -	case "always_on": -		filter = exemplar.AlwaysOnFilter -	case "always_off": -		return exemplar.Drop -	case "trace_based": -		fallthrough -	default: -		filter = exemplar.SampledFilter +// reservoirFunc returns the appropriately configured exemplar reservoir +// creation func based on the passed InstrumentKind and filter configuration. +func reservoirFunc[N int64 | float64](provider exemplar.ReservoirProvider, filter exemplar.Filter) func(attribute.Set) aggregate.FilteredExemplarReservoir[N] { +	return func(attrs attribute.Set) aggregate.FilteredExemplarReservoir[N] { +		return aggregate.NewFilteredExemplarReservoir[N](filter, provider(attrs))  	} +} +// DefaultExemplarReservoirProviderSelector returns the default +// [exemplar.ReservoirProvider] for the +// provided [Aggregation]. +// +// For explicit bucket histograms with more than 1 bucket, it uses the +// [exemplar.HistogramReservoirProvider]. +// For exponential histograms, it uses the +// [exemplar.FixedSizeReservoirProvider] +// with a size of min(20, max_buckets). +// For all other aggregations, it uses the +// [exemplar.FixedSizeReservoirProvider] +// with a size equal to the number of CPUs. +// +// Exemplar default reservoirs MAY change in a minor version bump. No +// guarantees are made on the shape or statistical properties of returned +// exemplars. +func DefaultExemplarReservoirProviderSelector(agg Aggregation) exemplar.ReservoirProvider {  	// https://github.com/open-telemetry/opentelemetry-specification/blob/d4b241f451674e8f611bb589477680341006ad2b/specification/metrics/sdk.md#exemplar-defaults  	// Explicit bucket histogram aggregation with more than 1 bucket will  	// use AlignedHistogramBucketExemplarReservoir.  	a, ok := agg.(AggregationExplicitBucketHistogram)  	if ok && len(a.Boundaries) > 0 { -		cp := slices.Clone(a.Boundaries) -		return func() exemplar.FilteredReservoir[N] { -			bounds := cp -			return exemplar.NewFilteredReservoir[N](filter, exemplar.Histogram(bounds)) -		} +		return exemplar.HistogramReservoirProvider(a.Boundaries)  	}  	var n int @@ -75,7 +73,5 @@ func reservoirFunc[N int64 | float64](agg Aggregation) func() exemplar.FilteredR  		}  	} -	return func() exemplar.FilteredReservoir[N] { -		return exemplar.NewFilteredReservoir[N](filter, exemplar.FixedSize(n)) -	} +	return exemplar.FixedSizeReservoirProvider(n)  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md new file mode 100644 index 000000000..d1025f5eb --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/README.md @@ -0,0 +1,3 @@ +# Metric SDK Exemplars + +[](https://pkg.go.dev/go.opentelemetry.io/otel/sdk/metric/exemplar) diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/doc.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go index 5394f48e0..9f2389376 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/doc.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/doc.go @@ -3,4 +3,4 @@  // Package exemplar provides an implementation of the OpenTelemetry exemplar  // reservoir to be used in metric collection pipelines. -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go index fcaa6a469..1ab694678 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/exemplar.go @@ -1,7 +1,7 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import (  	"time" diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go index 152a069a0..b595e2ace 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filter.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/filter.go @@ -1,7 +1,7 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import (  	"context" @@ -16,10 +16,10 @@ import (  // Reservoir in making a sampling decision.  type Filter func(context.Context) bool -// SampledFilter is a [Filter] that will only offer measurements +// TraceBasedFilter is a [Filter] that will only offer measurements  // if the passed context associated with the measurement contains a sampled  // [go.opentelemetry.io/otel/trace.SpanContext]. -func SampledFilter(ctx context.Context) bool { +func TraceBasedFilter(ctx context.Context) bool {  	return trace.SpanContextFromContext(ctx).IsSampled()  } @@ -27,3 +27,8 @@ func SampledFilter(ctx context.Context) bool {  func AlwaysOnFilter(ctx context.Context) bool {  	return true  } + +// AlwaysOffFilter is a [Filter] that never offers measurements. +func AlwaysOffFilter(ctx context.Context) bool { +	return false +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go index 199a2608f..d4aab0aad 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/rand.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/fixed_size_reservoir.go @@ -1,31 +1,69 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import (  	"context"  	"math"  	"math/rand" -	"sync"  	"time"  	"go.opentelemetry.io/otel/attribute"  ) -var ( +// FixedSizeReservoirProvider returns a provider of [FixedSizeReservoir]. +func FixedSizeReservoirProvider(k int) ReservoirProvider { +	return func(_ attribute.Set) Reservoir { +		return NewFixedSizeReservoir(k) +	} +} + +// NewFixedSizeReservoir returns a [FixedSizeReservoir] that samples at most +// k exemplars. If there are k or less measurements made, the Reservoir will +// sample each one. If there are more than k, the Reservoir will then randomly +// sample all additional measurement with a decreasing probability. +func NewFixedSizeReservoir(k int) *FixedSizeReservoir { +	return newFixedSizeReservoir(newStorage(k)) +} + +var _ Reservoir = &FixedSizeReservoir{} + +// FixedSizeReservoir is a [Reservoir] that samples at most k exemplars. If +// there are k or less measurements made, the Reservoir will sample each one. +// If there are more than k, the Reservoir will then randomly sample all +// additional measurement with a decreasing probability. +type FixedSizeReservoir struct { +	*storage + +	// count is the number of measurement seen. +	count int64 +	// next is the next count that will store a measurement at a random index +	// once the reservoir has been filled. +	next int64 +	// w is the largest random number in a distribution that is used to compute +	// the next next. +	w float64 +  	// rng is used to make sampling decisions.  	//  	// Do not use crypto/rand. There is no reason for the decrease in performance  	// given this is not a security sensitive decision. -	rng = rand.New(rand.NewSource(time.Now().UnixNano())) -	// Ensure concurrent safe accecess to rng and its underlying source. -	rngMu sync.Mutex -) +	rng *rand.Rand +} -// random returns, as a float64, a uniform pseudo-random number in the open -// interval (0.0,1.0). -func random() float64 { +func newFixedSizeReservoir(s *storage) *FixedSizeReservoir { +	r := &FixedSizeReservoir{ +		storage: s, +		rng:     rand.New(rand.NewSource(time.Now().UnixNano())), +	} +	r.reset() +	return r +} + +// randomFloat64 returns, as a float64, a uniform pseudo-random number in the +// open interval (0.0,1.0). +func (r *FixedSizeReservoir) randomFloat64() float64 {  	// TODO: This does not return a uniform number. rng.Float64 returns a  	// uniformly random int in [0,2^53) that is divided by 2^53. Meaning it  	// returns multiples of 2^-53, and not all floating point numbers between 0 @@ -43,40 +81,25 @@ func random() float64 {  	//  	// There are likely many other methods to explore here as well. -	rngMu.Lock() -	defer rngMu.Unlock() - -	f := rng.Float64() +	f := r.rng.Float64()  	for f == 0 { -		f = rng.Float64() +		f = r.rng.Float64()  	}  	return f  } -// FixedSize returns a [Reservoir] that samples at most k exemplars. If there -// are k or less measurements made, the Reservoir will sample each one. If -// there are more than k, the Reservoir will then randomly sample all -// additional measurement with a decreasing probability. -func FixedSize(k int) Reservoir { -	r := &randRes{storage: newStorage(k)} -	r.reset() -	return r -} - -type randRes struct { -	*storage - -	// count is the number of measurement seen. -	count int64 -	// next is the next count that will store a measurement at a random index -	// once the reservoir has been filled. -	next int64 -	// w is the largest random number in a distribution that is used to compute -	// the next next. -	w float64 -} - -func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) { +// Offer accepts the parameters associated with a measurement. The +// parameters will be stored as an exemplar if the Reservoir decides to +// sample the measurement. +// +// The passed ctx needs to contain any baggage or span that were active +// when the measurement was made. This information may be used by the +// Reservoir in making a sampling decision. +// +// The time t is the time when the measurement was made. The v and a +// parameters are the value and dropped (filtered) attributes of the +// measurement respectively. +func (r *FixedSizeReservoir) Offer(ctx context.Context, t time.Time, n Value, a []attribute.KeyValue) {  	// The following algorithm is "Algorithm L" from Li, Kim-Hung (4 December  	// 1994). "Reservoir-Sampling Algorithms of Time Complexity  	// O(n(1+log(N/n)))". ACM Transactions on Mathematical Software. 20 (4): @@ -123,7 +146,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute  	} else {  		if r.count == r.next {  			// Overwrite a random existing measurement with the one offered. -			idx := int(rng.Int63n(int64(cap(r.store)))) +			idx := int(r.rng.Int63n(int64(cap(r.store))))  			r.store[idx] = newMeasurement(ctx, t, n, a)  			r.advance()  		} @@ -132,7 +155,7 @@ func (r *randRes) Offer(ctx context.Context, t time.Time, n Value, a []attribute  }  // reset resets r to the initial state. -func (r *randRes) reset() { +func (r *FixedSizeReservoir) reset() {  	// This resets the number of exemplars known.  	r.count = 0  	// Random index inserts should only happen after the storage is full. @@ -147,14 +170,14 @@ func (r *randRes) reset() {  	// This maps the uniform random number in (0,1) to a geometric distribution  	// over the same interval. The mean of the distribution is inversely  	// proportional to the storage capacity. -	r.w = math.Exp(math.Log(random()) / float64(cap(r.store))) +	r.w = math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store)))  	r.advance()  }  // advance updates the count at which the offered measurement will overwrite an  // existing exemplar. -func (r *randRes) advance() { +func (r *FixedSizeReservoir) advance() {  	// Calculate the next value in the random number series.  	//  	// The current value of r.w is based on the max of a distribution of random @@ -167,7 +190,7 @@ func (r *randRes) advance() {  	// therefore the next r.w will be based on the same distribution (i.e.  	// `max(u_1,u_2,...,u_k)`). Therefore, we can sample the next r.w by  	// computing the next random number `u` and take r.w as `w * u^(1/k)`. -	r.w *= math.Exp(math.Log(random()) / float64(cap(r.store))) +	r.w *= math.Exp(math.Log(r.randomFloat64()) / float64(cap(r.store)))  	// Use the new random number in the series to calculate the count of the  	// next measurement that will be stored.  	// @@ -178,10 +201,13 @@ func (r *randRes) advance() {  	//  	// Important to note, the new r.next will always be at least 1 more than  	// the last r.next. -	r.next += int64(math.Log(random())/math.Log(1-r.w)) + 1 +	r.next += int64(math.Log(r.randomFloat64())/math.Log(1-r.w)) + 1  } -func (r *randRes) Collect(dest *[]Exemplar) { +// Collect returns all the held exemplars. +// +// The Reservoir state is preserved after this call. +func (r *FixedSizeReservoir) Collect(dest *[]Exemplar) {  	r.storage.Collect(dest)  	// Call reset here even though it will reset r.count and restart the random  	// number series. This will persist any old exemplars as long as no new diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go new file mode 100644 index 000000000..3b76cf305 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/histogram_reservoir.go @@ -0,0 +1,70 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar" + +import ( +	"context" +	"slices" +	"sort" +	"time" + +	"go.opentelemetry.io/otel/attribute" +) + +// HistogramReservoirProvider is a provider of [HistogramReservoir]. +func HistogramReservoirProvider(bounds []float64) ReservoirProvider { +	cp := slices.Clone(bounds) +	slices.Sort(cp) +	return func(_ attribute.Set) Reservoir { +		return NewHistogramReservoir(cp) +	} +} + +// NewHistogramReservoir returns a [HistogramReservoir] that samples the last +// measurement that falls within a histogram bucket. The histogram bucket +// upper-boundaries are define by bounds. +// +// The passed bounds must be sorted before calling this function. +func NewHistogramReservoir(bounds []float64) *HistogramReservoir { +	return &HistogramReservoir{ +		bounds:  bounds, +		storage: newStorage(len(bounds) + 1), +	} +} + +var _ Reservoir = &HistogramReservoir{} + +// HistogramReservoir is a [Reservoir] that samples the last measurement that +// falls within a histogram bucket. The histogram bucket upper-boundaries are +// define by bounds. +type HistogramReservoir struct { +	*storage + +	// bounds are bucket bounds in ascending order. +	bounds []float64 +} + +// Offer accepts the parameters associated with a measurement. The +// parameters will be stored as an exemplar if the Reservoir decides to +// sample the measurement. +// +// The passed ctx needs to contain any baggage or span that were active +// when the measurement was made. This information may be used by the +// Reservoir in making a sampling decision. +// +// The time t is the time when the measurement was made. The v and a +// parameters are the value and dropped (filtered) attributes of the +// measurement respectively. +func (r *HistogramReservoir) Offer(ctx context.Context, t time.Time, v Value, a []attribute.KeyValue) { +	var x float64 +	switch v.Type() { +	case Int64ValueType: +		x = float64(v.Int64()) +	case Float64ValueType: +		x = v.Float64() +	default: +		panic("unknown value type") +	} +	r.store[sort.SearchFloat64s(r.bounds, x)] = newMeasurement(ctx, t, v, a) +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go index 80fa59554..ba5cd1a6b 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/reservoir.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/reservoir.go @@ -1,7 +1,7 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import (  	"context" @@ -30,3 +30,11 @@ type Reservoir interface {  	// The Reservoir state is preserved after this call.  	Collect(dest *[]Exemplar)  } + +// ReservoirProvider creates new [Reservoir]s. +// +// The attributes provided are attributes which are kept by the aggregation, and +// are exclusive with attributes passed to Offer. The combination of these +// attributes and the attributes passed to Offer is the complete set of +// attributes a measurement was made with. +type ReservoirProvider func(attr attribute.Set) Reservoir diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/storage.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go index 10b2976f7..0e2e26dfb 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/storage.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/storage.go @@ -1,7 +1,7 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import (  	"context" @@ -35,7 +35,7 @@ func (r *storage) Collect(dest *[]Exemplar) {  			continue  		} -		m.Exemplar(&(*dest)[n]) +		m.exemplar(&(*dest)[n])  		n++  	}  	*dest = (*dest)[:n] @@ -66,8 +66,8 @@ func newMeasurement(ctx context.Context, ts time.Time, v Value, droppedAttr []at  	}  } -// Exemplar returns m as an [Exemplar]. -func (m measurement) Exemplar(dest *Exemplar) { +// exemplar returns m as an [Exemplar]. +func (m measurement) exemplar(dest *Exemplar) {  	dest.FilteredAttributes = m.FilteredAttributes  	dest.Time = m.Time  	dest.Value = m.Value diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/value.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go index 1957d6b1e..590b089a8 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/value.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exemplar/value.go @@ -1,7 +1,7 @@  // Copyright The OpenTelemetry Authors  // SPDX-License-Identifier: Apache-2.0 -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +package exemplar // import "go.opentelemetry.io/otel/sdk/metric/exemplar"  import "math" @@ -28,7 +28,8 @@ type Value struct {  func NewValue[N int64 | float64](value N) Value {  	switch v := any(value).(type) {  	case int64: -		return Value{t: Int64ValueType, val: uint64(v)} +		// This can be later converted back to int64 (overflow not checked). +		return Value{t: Int64ValueType, val: uint64(v)} // nolint:gosec  	case float64:  		return Value{t: Float64ValueType, val: math.Float64bits(v)}  	} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/exporter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/exporter.go index 1a3cccb67..1969cb42c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/exporter.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/exporter.go @@ -5,14 +5,14 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"  import (  	"context" -	"fmt" +	"errors"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  )  // ErrExporterShutdown is returned if Export or Shutdown are called after an  // Exporter has been Shutdown. -var ErrExporterShutdown = fmt.Errorf("exporter is shutdown") +var ErrExporterShutdown = errors.New("exporter is shutdown")  // Exporter handles the delivery of metric data to external receivers. This is  // the final component in the metric push pipeline. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go index b52a330b3..c33e1a28c 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/instrument.go @@ -16,6 +16,7 @@ import (  	"go.opentelemetry.io/otel/metric/embedded"  	"go.opentelemetry.io/otel/sdk/instrumentation"  	"go.opentelemetry.io/otel/sdk/metric/internal/aggregate" +	"go.opentelemetry.io/otel/sdk/metric/internal/x"  )  var zeroScope instrumentation.Scope @@ -144,6 +145,12 @@ type Stream struct {  	// Use NewAllowKeysFilter from "go.opentelemetry.io/otel/attribute" to  	// provide an allow-list of attribute keys here.  	AttributeFilter attribute.Filter +	// ExemplarReservoirProvider selects the +	// [go.opentelemetry.io/otel/sdk/metric/exemplar.ReservoirProvider] based +	// on the [Aggregation]. +	// +	// If unspecified, [DefaultExemplarReservoirProviderSelector] is used. +	ExemplarReservoirProviderSelector ExemplarReservoirProviderSelector  }  // instID are the identifying properties of a instrument. @@ -184,6 +191,7 @@ var (  	_ metric.Int64UpDownCounter = (*int64Inst)(nil)  	_ metric.Int64Histogram     = (*int64Inst)(nil)  	_ metric.Int64Gauge         = (*int64Inst)(nil) +	_ x.EnabledInstrument       = (*int64Inst)(nil)  )  func (i *int64Inst) Add(ctx context.Context, val int64, opts ...metric.AddOption) { @@ -196,6 +204,10 @@ func (i *int64Inst) Record(ctx context.Context, val int64, opts ...metric.Record  	i.aggregate(ctx, val, c.Attributes())  } +func (i *int64Inst) Enabled(_ context.Context) bool { +	return len(i.measures) != 0 +} +  func (i *int64Inst) aggregate(ctx context.Context, val int64, s attribute.Set) { // nolint:revive  // okay to shadow pkg with method.  	for _, in := range i.measures {  		in(ctx, val, s) @@ -216,6 +228,7 @@ var (  	_ metric.Float64UpDownCounter = (*float64Inst)(nil)  	_ metric.Float64Histogram     = (*float64Inst)(nil)  	_ metric.Float64Gauge         = (*float64Inst)(nil) +	_ x.EnabledInstrument         = (*float64Inst)(nil)  )  func (i *float64Inst) Add(ctx context.Context, val float64, opts ...metric.AddOption) { @@ -228,14 +241,18 @@ func (i *float64Inst) Record(ctx context.Context, val float64, opts ...metric.Re  	i.aggregate(ctx, val, c.Attributes())  } +func (i *float64Inst) Enabled(_ context.Context) bool { +	return len(i.measures) != 0 +} +  func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Set) {  	for _, in := range i.measures {  		in(ctx, val, s)  	}  } -// observablID is a comparable unique identifier of an observable. -type observablID[N int64 | float64] struct { +// observableID is a comparable unique identifier of an observable. +type observableID[N int64 | float64] struct {  	name        string  	description string  	kind        InstrumentKind @@ -287,7 +304,7 @@ func newInt64Observable(m *meter, kind InstrumentKind, name, desc, u string) int  type observable[N int64 | float64] struct {  	metric.Observable -	observablID[N] +	observableID[N]  	meter           *meter  	measures        measures[N] @@ -296,7 +313,7 @@ type observable[N int64 | float64] struct {  func newObservable[N int64 | float64](m *meter, kind InstrumentKind, name, desc, u string) *observable[N] {  	return &observable[N]{ -		observablID: observablID[N]{ +		observableID: observableID[N]{  			name:        name,  			description: desc,  			kind:        kind, diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go index b18ee719b..fde219333 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/aggregate.go @@ -8,7 +8,6 @@ import (  	"time"  	"go.opentelemetry.io/otel/attribute" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  ) @@ -38,8 +37,8 @@ type Builder[N int64 | float64] struct {  	// create new exemplar reservoirs for a new seen attribute set.  	//  	// If this is not provided a default factory function that returns an -	// exemplar.Drop reservoir will be used. -	ReservoirFunc func() exemplar.FilteredReservoir[N] +	// dropReservoir reservoir will be used. +	ReservoirFunc func(attribute.Set) FilteredExemplarReservoir[N]  	// AggregationLimit is the cardinality limit of measurement attributes. Any  	// measurement for new attributes once the limit has been reached will be  	// aggregated into a single aggregate for the "otel.metric.overflow" @@ -50,12 +49,12 @@ type Builder[N int64 | float64] struct {  	AggregationLimit int  } -func (b Builder[N]) resFunc() func() exemplar.FilteredReservoir[N] { +func (b Builder[N]) resFunc() func(attribute.Set) FilteredExemplarReservoir[N] {  	if b.ReservoirFunc != nil {  		return b.ReservoirFunc  	} -	return exemplar.Drop +	return dropReservoir  }  type fltrMeasure[N int64 | float64] func(ctx context.Context, value N, fltrAttr attribute.Set, droppedAttr []attribute.KeyValue) diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go new file mode 100644 index 000000000..8396faaa4 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/drop.go @@ -0,0 +1,27 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" + +import ( +	"context" + +	"go.opentelemetry.io/otel/attribute" +	"go.opentelemetry.io/otel/sdk/metric/exemplar" +) + +// dropReservoir returns a [FilteredReservoir] that drops all measurements it is offered. +func dropReservoir[N int64 | float64](attribute.Set) FilteredExemplarReservoir[N] { +	return &dropRes[N]{} +} + +type dropRes[N int64 | float64] struct{} + +// Offer does nothing, all measurements offered will be dropped. +func (r *dropRes[N]) Offer(context.Context, N, []attribute.KeyValue) {} + +// Collect resets dest. No exemplars will ever be returned. +func (r *dropRes[N]) Collect(dest *[]exemplar.Exemplar) { +	clear(*dest) // Erase elements to let GC collect objects +	*dest = (*dest)[:0] +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go index 170ae8e58..25d709948 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exemplar.go @@ -6,7 +6,7 @@ package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggreg  import (  	"sync" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar" +	"go.opentelemetry.io/otel/sdk/metric/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  ) @@ -17,6 +17,7 @@ var exemplarPool = sync.Pool{  func collectExemplars[N int64 | float64](out *[]metricdata.Exemplar[N], f func(*[]exemplar.Exemplar)) {  	dest := exemplarPool.Get().(*[]exemplar.Exemplar)  	defer func() { +		clear(*dest) // Erase elements to let GC collect objects.  		*dest = (*dest)[:0]  		exemplarPool.Put(dest)  	}() diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go index 707342408..336ea91d1 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/exponential_histogram.go @@ -12,7 +12,6 @@ import (  	"go.opentelemetry.io/otel"  	"go.opentelemetry.io/otel/attribute" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  ) @@ -31,7 +30,7 @@ const (  // expoHistogramDataPoint is a single data point in an exponential histogram.  type expoHistogramDataPoint[N int64 | float64] struct {  	attrs attribute.Set -	res   exemplar.FilteredReservoir[N] +	res   FilteredExemplarReservoir[N]  	count uint64  	min   N @@ -51,16 +50,16 @@ type expoHistogramDataPoint[N int64 | float64] struct {  func newExpoHistogramDataPoint[N int64 | float64](attrs attribute.Set, maxSize int, maxScale int32, noMinMax, noSum bool) *expoHistogramDataPoint[N] {  	f := math.MaxFloat64 -	max := N(f) // if N is int64, max will overflow to -9223372036854775808 -	min := N(-f) +	ma := N(f) // if N is int64, max will overflow to -9223372036854775808 +	mi := N(-f)  	if N(maxInt64) > N(f) { -		max = N(maxInt64) -		min = N(minInt64) +		ma = N(maxInt64) +		mi = N(minInt64)  	}  	return &expoHistogramDataPoint[N]{  		attrs:    attrs, -		min:      max, -		max:      min, +		min:      ma, +		max:      mi,  		maxSize:  maxSize,  		noMinMax: noMinMax,  		noSum:    noSum, @@ -284,7 +283,7 @@ func (b *expoBuckets) downscale(delta int32) {  // newExponentialHistogram returns an Aggregator that summarizes a set of  // measurements as an exponential histogram. Each histogram is scoped by attributes  // and the aggregation cycle the measurements were made in. -func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *expoHistogram[N] { +func newExponentialHistogram[N int64 | float64](maxSize, maxScale int32, noMinMax, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *expoHistogram[N] {  	return &expoHistogram[N]{  		noSum:    noSum,  		noMinMax: noMinMax, @@ -307,7 +306,7 @@ type expoHistogram[N int64 | float64] struct {  	maxSize  int  	maxScale int32 -	newRes   func() exemplar.FilteredReservoir[N] +	newRes   func(attribute.Set) FilteredExemplarReservoir[N]  	limit    limiter[*expoHistogramDataPoint[N]]  	values   map[attribute.Distinct]*expoHistogramDataPoint[N]  	valuesMu sync.Mutex @@ -328,7 +327,7 @@ func (e *expoHistogram[N]) measure(ctx context.Context, value N, fltrAttr attrib  	v, ok := e.values[attr.Equivalent()]  	if !ok {  		v = newExpoHistogramDataPoint[N](attr, e.maxSize, e.maxScale, e.noMinMax, e.noSum) -		v.res = e.newRes() +		v.res = e.newRes(attr)  		e.values[attr.Equivalent()] = v  	} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go new file mode 100644 index 000000000..691a91060 --- /dev/null +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/filtered_reservoir.go @@ -0,0 +1,50 @@ +// Copyright The OpenTelemetry Authors +// SPDX-License-Identifier: Apache-2.0 + +package aggregate // import "go.opentelemetry.io/otel/sdk/metric/internal/aggregate" + +import ( +	"context" +	"time" + +	"go.opentelemetry.io/otel/attribute" +	"go.opentelemetry.io/otel/sdk/metric/exemplar" +) + +// FilteredExemplarReservoir wraps a [exemplar.Reservoir] with a filter. +type FilteredExemplarReservoir[N int64 | float64] interface { +	// Offer accepts the parameters associated with a measurement. The +	// parameters will be stored as an exemplar if the filter decides to +	// sample the measurement. +	// +	// The passed ctx needs to contain any baggage or span that were active +	// when the measurement was made. This information may be used by the +	// Reservoir in making a sampling decision. +	Offer(ctx context.Context, val N, attr []attribute.KeyValue) +	// Collect returns all the held exemplars in the reservoir. +	Collect(dest *[]exemplar.Exemplar) +} + +// filteredExemplarReservoir handles the pre-sampled exemplar of measurements made. +type filteredExemplarReservoir[N int64 | float64] struct { +	filter    exemplar.Filter +	reservoir exemplar.Reservoir +} + +// NewFilteredExemplarReservoir creates a [FilteredExemplarReservoir] which only offers values +// that are allowed by the filter. +func NewFilteredExemplarReservoir[N int64 | float64](f exemplar.Filter, r exemplar.Reservoir) FilteredExemplarReservoir[N] { +	return &filteredExemplarReservoir[N]{ +		filter:    f, +		reservoir: r, +	} +} + +func (f *filteredExemplarReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) { +	if f.filter(ctx) { +		// only record the current time if we are sampling this measurement. +		f.reservoir.Offer(ctx, time.Now(), exemplar.NewValue(val), attr) +	} +} + +func (f *filteredExemplarReservoir[N]) Collect(dest *[]exemplar.Exemplar) { f.reservoir.Collect(dest) } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go index ade0941f5..d577ae2c1 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/histogram.go @@ -11,13 +11,12 @@ import (  	"time"  	"go.opentelemetry.io/otel/attribute" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  )  type buckets[N int64 | float64] struct {  	attrs attribute.Set -	res   exemplar.FilteredReservoir[N] +	res   FilteredExemplarReservoir[N]  	counts   []uint64  	count    uint64 @@ -48,13 +47,13 @@ type histValues[N int64 | float64] struct {  	noSum  bool  	bounds []float64 -	newRes   func() exemplar.FilteredReservoir[N] +	newRes   func(attribute.Set) FilteredExemplarReservoir[N]  	limit    limiter[*buckets[N]]  	values   map[attribute.Distinct]*buckets[N]  	valuesMu sync.Mutex  } -func newHistValues[N int64 | float64](bounds []float64, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *histValues[N] { +func newHistValues[N int64 | float64](bounds []float64, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *histValues[N] {  	// The responsibility of keeping all buckets correctly associated with the  	// passed boundaries is ultimately this type's responsibility. Make a copy  	// here so we can always guarantee this. Or, in the case of failure, have @@ -94,7 +93,7 @@ func (s *histValues[N]) measure(ctx context.Context, value N, fltrAttr attribute  		//  		//   buckets = (-∞, 0], (0, 5.0], (5.0, 10.0], (10.0, +∞)  		b = newBuckets[N](attr, len(s.bounds)+1) -		b.res = s.newRes() +		b.res = s.newRes(attr)  		// Ensure min and max are recorded values (not zero), for new buckets.  		b.min, b.max = value, value @@ -109,7 +108,7 @@ func (s *histValues[N]) measure(ctx context.Context, value N, fltrAttr attribute  // newHistogram returns an Aggregator that summarizes a set of measurements as  // an histogram. -func newHistogram[N int64 | float64](boundaries []float64, noMinMax, noSum bool, limit int, r func() exemplar.FilteredReservoir[N]) *histogram[N] { +func newHistogram[N int64 | float64](boundaries []float64, noMinMax, noSum bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *histogram[N] {  	return &histogram[N]{  		histValues: newHistValues[N](boundaries, noSum, limit, r),  		noMinMax:   noMinMax, diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go index c35936840..d3a93f085 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/lastvalue.go @@ -9,7 +9,6 @@ import (  	"time"  	"go.opentelemetry.io/otel/attribute" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  ) @@ -17,10 +16,10 @@ import (  type datapoint[N int64 | float64] struct {  	attrs attribute.Set  	value N -	res   exemplar.FilteredReservoir[N] +	res   FilteredExemplarReservoir[N]  } -func newLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *lastValue[N] { +func newLastValue[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *lastValue[N] {  	return &lastValue[N]{  		newRes: r,  		limit:  newLimiter[datapoint[N]](limit), @@ -33,7 +32,7 @@ func newLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReserv  type lastValue[N int64 | float64] struct {  	sync.Mutex -	newRes func() exemplar.FilteredReservoir[N] +	newRes func(attribute.Set) FilteredExemplarReservoir[N]  	limit  limiter[datapoint[N]]  	values map[attribute.Distinct]datapoint[N]  	start  time.Time @@ -46,7 +45,7 @@ func (s *lastValue[N]) measure(ctx context.Context, value N, fltrAttr attribute.  	attr := s.limit.Attributes(fltrAttr, s.values)  	d, ok := s.values[attr.Equivalent()]  	if !ok { -		d.res = s.newRes() +		d.res = s.newRes(attr)  	}  	d.attrs = attr @@ -115,7 +114,7 @@ func (s *lastValue[N]) copyDpts(dest *[]metricdata.DataPoint[N], t time.Time) in  // newPrecomputedLastValue returns an aggregator that summarizes a set of  // observations as the last one made. -func newPrecomputedLastValue[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *precomputedLastValue[N] { +func newPrecomputedLastValue[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *precomputedLastValue[N] {  	return &precomputedLastValue[N]{lastValue: newLastValue[N](limit, r)}  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go index 891366922..8e132ad61 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/aggregate/sum.go @@ -9,25 +9,24 @@ import (  	"time"  	"go.opentelemetry.io/otel/attribute" -	"go.opentelemetry.io/otel/sdk/metric/internal/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  )  type sumValue[N int64 | float64] struct {  	n     N -	res   exemplar.FilteredReservoir[N] +	res   FilteredExemplarReservoir[N]  	attrs attribute.Set  }  // valueMap is the storage for sums.  type valueMap[N int64 | float64] struct {  	sync.Mutex -	newRes func() exemplar.FilteredReservoir[N] +	newRes func(attribute.Set) FilteredExemplarReservoir[N]  	limit  limiter[sumValue[N]]  	values map[attribute.Distinct]sumValue[N]  } -func newValueMap[N int64 | float64](limit int, r func() exemplar.FilteredReservoir[N]) *valueMap[N] { +func newValueMap[N int64 | float64](limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *valueMap[N] {  	return &valueMap[N]{  		newRes: r,  		limit:  newLimiter[sumValue[N]](limit), @@ -42,7 +41,7 @@ func (s *valueMap[N]) measure(ctx context.Context, value N, fltrAttr attribute.S  	attr := s.limit.Attributes(fltrAttr, s.values)  	v, ok := s.values[attr.Equivalent()]  	if !ok { -		v.res = s.newRes() +		v.res = s.newRes(attr)  	}  	v.attrs = attr @@ -55,7 +54,7 @@ func (s *valueMap[N]) measure(ctx context.Context, value N, fltrAttr attribute.S  // newSum returns an aggregator that summarizes a set of measurements as their  // arithmetic sum. Each sum is scoped by attributes and the aggregation cycle  // the measurements were made in. -func newSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *sum[N] { +func newSum[N int64 | float64](monotonic bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *sum[N] {  	return &sum[N]{  		valueMap:  newValueMap[N](limit, r),  		monotonic: monotonic, @@ -142,9 +141,9 @@ func (s *sum[N]) cumulative(dest *metricdata.Aggregation) int {  }  // newPrecomputedSum returns an aggregator that summarizes a set of -// observatrions as their arithmetic sum. Each sum is scoped by attributes and +// observations as their arithmetic sum. Each sum is scoped by attributes and  // the aggregation cycle the measurements were made in. -func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() exemplar.FilteredReservoir[N]) *precomputedSum[N] { +func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func(attribute.Set) FilteredExemplarReservoir[N]) *precomputedSum[N] {  	return &precomputedSum[N]{  		valueMap:  newValueMap[N](limit, r),  		monotonic: monotonic, @@ -152,7 +151,7 @@ func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() ex  	}  } -// precomputedSum summarizes a set of observatrions as their arithmetic sum. +// precomputedSum summarizes a set of observations as their arithmetic sum.  type precomputedSum[N int64 | float64] struct {  	*valueMap[N] diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go deleted file mode 100644 index 5a0f39ae1..000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/drop.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( -	"context" - -	"go.opentelemetry.io/otel/attribute" -) - -// Drop returns a [FilteredReservoir] that drops all measurements it is offered. -func Drop[N int64 | float64]() FilteredReservoir[N] { return &dropRes[N]{} } - -type dropRes[N int64 | float64] struct{} - -// Offer does nothing, all measurements offered will be dropped. -func (r *dropRes[N]) Offer(context.Context, N, []attribute.KeyValue) {} - -// Collect resets dest. No exemplars will ever be returned. -func (r *dropRes[N]) Collect(dest *[]Exemplar) { -	*dest = (*dest)[:0] -} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go deleted file mode 100644 index 9fedfa4be..000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/filtered_reservoir.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( -	"context" -	"time" - -	"go.opentelemetry.io/otel/attribute" -) - -// FilteredReservoir wraps a [Reservoir] with a filter. -type FilteredReservoir[N int64 | float64] interface { -	// Offer accepts the parameters associated with a measurement. The -	// parameters will be stored as an exemplar if the filter decides to -	// sample the measurement. -	// -	// The passed ctx needs to contain any baggage or span that were active -	// when the measurement was made. This information may be used by the -	// Reservoir in making a sampling decision. -	Offer(ctx context.Context, val N, attr []attribute.KeyValue) -	// Collect returns all the held exemplars in the reservoir. -	Collect(dest *[]Exemplar) -} - -// filteredReservoir handles the pre-sampled exemplar of measurements made. -type filteredReservoir[N int64 | float64] struct { -	filter    Filter -	reservoir Reservoir -} - -// NewFilteredReservoir creates a [FilteredReservoir] which only offers values -// that are allowed by the filter. -func NewFilteredReservoir[N int64 | float64](f Filter, r Reservoir) FilteredReservoir[N] { -	return &filteredReservoir[N]{ -		filter:    f, -		reservoir: r, -	} -} - -func (f *filteredReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) { -	if f.filter(ctx) { -		// only record the current time if we are sampling this measurment. -		f.reservoir.Offer(ctx, time.Now(), NewValue(val), attr) -	} -} - -func (f *filteredReservoir[N]) Collect(dest *[]Exemplar) { f.reservoir.Collect(dest) } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go deleted file mode 100644 index a6ff86d02..000000000 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/exemplar/hist.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright The OpenTelemetry Authors -// SPDX-License-Identifier: Apache-2.0 - -package exemplar // import "go.opentelemetry.io/otel/sdk/metric/internal/exemplar" - -import ( -	"context" -	"slices" -	"sort" -	"time" - -	"go.opentelemetry.io/otel/attribute" -) - -// Histogram returns a [Reservoir] that samples the last measurement that falls -// within a histogram bucket. The histogram bucket upper-boundaries are define -// by bounds. -// -// The passed bounds will be sorted by this function. -func Histogram(bounds []float64) Reservoir { -	slices.Sort(bounds) -	return &histRes{ -		bounds:  bounds, -		storage: newStorage(len(bounds) + 1), -	} -} - -type histRes struct { -	*storage - -	// bounds are bucket bounds in ascending order. -	bounds []float64 -} - -func (r *histRes) Offer(ctx context.Context, t time.Time, v Value, a []attribute.KeyValue) { -	var x float64 -	switch v.Type() { -	case Int64ValueType: -		x = float64(v.Int64()) -	case Float64ValueType: -		x = v.Float64() -	default: -		panic("unknown value type") -	} -	r.store[sort.SearchFloat64s(r.bounds, x)] = newMeasurement(ctx, t, v, a) -} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/README.md b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/README.md index aba69d654..59f736b73 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/README.md +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/README.md @@ -10,6 +10,7 @@ See the [Compatibility and Stability](#compatibility-and-stability) section for  - [Cardinality Limit](#cardinality-limit)  - [Exemplars](#exemplars) +- [Instrument Enabled](#instrument-enabled)  ### Cardinality Limit @@ -102,6 +103,24 @@ Revert to the default exemplar filter (`"trace_based"`)  unset OTEL_METRICS_EXEMPLAR_FILTER  ``` +### Instrument Enabled + +To help users avoid performing computationally expensive operations when recording measurements, synchronous instruments provide an `Enabled` method. + +#### Examples + +The following code shows an example of how to check if an instrument implements the `EnabledInstrument` interface before using the `Enabled` function to avoid doing an expensive computation: + +```go +type enabledInstrument interface { Enabled(context.Context) bool } + +ctr, err := m.Int64Counter("expensive-counter") +c, ok := ctr.(enabledInstrument) +if !ok || c.Enabled(context.Background()) { +    c.Add(expensiveComputation()) +} +``` +  ## Compatibility and Stability  Experimental features do not fall within the scope of the OpenTelemetry Go versioning and stability [policy](../../../../VERSIONING.md). diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go index 8cd2f3741..a98606238 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/internal/x/x.go @@ -8,41 +8,26 @@  package x // import "go.opentelemetry.io/otel/sdk/metric/internal/x"  import ( +	"context"  	"os"  	"strconv" -	"strings"  ) -var ( -	// Exemplars is an experimental feature flag that defines if exemplars -	// should be recorded for metric data-points. -	// -	// To enable this feature set the OTEL_GO_X_EXEMPLAR environment variable -	// to the case-insensitive string value of "true" (i.e. "True" and "TRUE" -	// will also enable this). -	Exemplars = newFeature("EXEMPLAR", func(v string) (string, bool) { -		if strings.ToLower(v) == "true" { -			return v, true -		} -		return "", false -	}) - -	// CardinalityLimit is an experimental feature flag that defines if -	// cardinality limits should be applied to the recorded metric data-points. -	// -	// To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment -	// variable to the integer limit value you want to use. -	// -	// Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0 -	// will disable the cardinality limits. -	CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) { -		n, err := strconv.Atoi(v) -		if err != nil { -			return 0, false -		} -		return n, true -	}) -) +// CardinalityLimit is an experimental feature flag that defines if +// cardinality limits should be applied to the recorded metric data-points. +// +// To enable this feature set the OTEL_GO_X_CARDINALITY_LIMIT environment +// variable to the integer limit value you want to use. +// +// Setting OTEL_GO_X_CARDINALITY_LIMIT to a value less than or equal to 0 +// will disable the cardinality limits. +var CardinalityLimit = newFeature("CARDINALITY_LIMIT", func(v string) (int, bool) { +	n, err := strconv.Atoi(v) +	if err != nil { +		return 0, false +	} +	return n, true +})  // Feature is an experimental feature control flag. It provides a uniform way  // to interact with these feature flags and parse their values. @@ -83,3 +68,14 @@ func (f Feature[T]) Enabled() bool {  	_, ok := f.Lookup()  	return ok  } + +// EnabledInstrument informs whether the instrument is enabled. +// +// EnabledInstrument interface is implemented by synchronous instruments. +type EnabledInstrument interface { +	// Enabled returns whether the instrument will process measurements for the given context. +	// +	// This function can be used in places where measuring an instrument +	// would result in computationally expensive operations. +	Enabled(context.Context) bool +} diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go b/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go index e0fd86ca7..c495985bc 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/manual_reader.go @@ -113,18 +113,17 @@ func (mr *ManualReader) Collect(ctx context.Context, rm *metricdata.ResourceMetr  	if err != nil {  		return err  	} -	var errs []error  	for _, producer := range mr.externalProducers.Load().([]Producer) { -		externalMetrics, err := producer.Produce(ctx) -		if err != nil { -			errs = append(errs, err) +		externalMetrics, e := producer.Produce(ctx) +		if e != nil { +			err = errors.Join(err, e)  		}  		rm.ScopeMetrics = append(rm.ScopeMetrics, externalMetrics...)  	}  	global.Debug("ManualReader collection", "Data", rm) -	return unifyErrors(errs) +	return err  }  // MarshalLog returns logging data about the ManualReader. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go index 2309e5b2b..a6ccd117b 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/meter.go @@ -150,6 +150,11 @@ func (m *meter) int64ObservableInstrument(id Instrument, callbacks []metric.Int6  				continue  			}  			inst.appendMeasures(in) + +			// Add the measures to the pipeline. It is required to maintain +			// measures per pipeline to avoid calling the measure that +			// is not part of the pipeline. +			insert.pipeline.addInt64Measure(inst.observableID, in)  			for _, cback := range callbacks {  				inst := int64Observer{measures: in}  				fn := cback @@ -309,6 +314,11 @@ func (m *meter) float64ObservableInstrument(id Instrument, callbacks []metric.Fl  				continue  			}  			inst.appendMeasures(in) + +			// Add the measures to the pipeline. It is required to maintain +			// measures per pipeline to avoid calling the measure that +			// is not part of the pipeline. +			insert.pipeline.addFloat64Measure(inst.observableID, in)  			for _, cback := range callbacks {  				inst := float64Observer{measures: in}  				fn := cback @@ -441,73 +451,80 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)  		return noopRegister{}, nil  	} -	reg := newObserver() -	var errs multierror +	var err error +	validInstruments := make([]metric.Observable, 0, len(insts))  	for _, inst := range insts { -		// Unwrap any global. -		if u, ok := inst.(interface { -			Unwrap() metric.Observable -		}); ok { -			inst = u.Unwrap() -		} -  		switch o := inst.(type) {  		case int64Observable: -			if err := o.registerable(m); err != nil { -				if !errors.Is(err, errEmptyAgg) { -					errs.append(err) +			if e := o.registerable(m); e != nil { +				if !errors.Is(e, errEmptyAgg) { +					err = errors.Join(err, e)  				}  				continue  			} -			reg.registerInt64(o.observablID) + +			validInstruments = append(validInstruments, inst)  		case float64Observable: -			if err := o.registerable(m); err != nil { -				if !errors.Is(err, errEmptyAgg) { -					errs.append(err) +			if e := o.registerable(m); e != nil { +				if !errors.Is(e, errEmptyAgg) { +					err = errors.Join(err, e)  				}  				continue  			} -			reg.registerFloat64(o.observablID) + +			validInstruments = append(validInstruments, inst)  		default:  			// Instrument external to the SDK. -			return nil, fmt.Errorf("invalid observable: from different implementation") +			return nil, errors.New("invalid observable: from different implementation")  		}  	} -	err := errs.errorOrNil() -	if reg.len() == 0 { +	if len(validInstruments) == 0 {  		// All insts use drop aggregation or are invalid.  		return noopRegister{}, err  	} -	// Some or all instruments were valid. -	cback := func(ctx context.Context) error { return f(ctx, reg) } -	return m.pipes.registerMultiCallback(cback), err +	unregs := make([]func(), len(m.pipes)) +	for ix, pipe := range m.pipes { +		reg := newObserver(pipe) +		for _, inst := range validInstruments { +			switch o := inst.(type) { +			case int64Observable: +				reg.registerInt64(o.observableID) +			case float64Observable: +				reg.registerFloat64(o.observableID) +			} +		} + +		// Some or all instruments were valid. +		cBack := func(ctx context.Context) error { return f(ctx, reg) } +		unregs[ix] = pipe.addMultiCallback(cBack) +	} + +	return unregisterFuncs{f: unregs}, err  }  type observer struct {  	embedded.Observer -	float64 map[observablID[float64]]struct{} -	int64   map[observablID[int64]]struct{} +	pipe    *pipeline +	float64 map[observableID[float64]]struct{} +	int64   map[observableID[int64]]struct{}  } -func newObserver() observer { +func newObserver(p *pipeline) observer {  	return observer{ -		float64: make(map[observablID[float64]]struct{}), -		int64:   make(map[observablID[int64]]struct{}), +		pipe:    p, +		float64: make(map[observableID[float64]]struct{}), +		int64:   make(map[observableID[int64]]struct{}),  	}  } -func (r observer) len() int { -	return len(r.float64) + len(r.int64) -} - -func (r observer) registerFloat64(id observablID[float64]) { +func (r observer) registerFloat64(id observableID[float64]) {  	r.float64[id] = struct{}{}  } -func (r observer) registerInt64(id observablID[int64]) { +func (r observer) registerInt64(id observableID[int64]) {  	r.int64[id] = struct{}{}  } @@ -521,22 +538,12 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ...  	switch conv := o.(type) {  	case float64Observable:  		oImpl = conv -	case interface { -		Unwrap() metric.Observable -	}: -		// Unwrap any global. -		async := conv.Unwrap() -		var ok bool -		if oImpl, ok = async.(float64Observable); !ok { -			global.Error(errUnknownObserver, "failed to record asynchronous") -			return -		}  	default:  		global.Error(errUnknownObserver, "failed to record")  		return  	} -	if _, registered := r.float64[oImpl.observablID]; !registered { +	if _, registered := r.float64[oImpl.observableID]; !registered {  		if !oImpl.dropAggregation {  			global.Error(errUnregObserver, "failed to record",  				"name", oImpl.name, @@ -548,7 +555,12 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ...  		return  	}  	c := metric.NewObserveConfig(opts) -	oImpl.observe(v, c.Attributes()) +	// Access to r.pipe.float64Measure is already guarded by a lock in pipeline.produce. +	// TODO (#5946): Refactor pipeline and observable measures. +	measures := r.pipe.float64Measures[oImpl.observableID] +	for _, m := range measures { +		m(context.Background(), v, c.Attributes()) +	}  }  func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric.ObserveOption) { @@ -556,22 +568,12 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric  	switch conv := o.(type) {  	case int64Observable:  		oImpl = conv -	case interface { -		Unwrap() metric.Observable -	}: -		// Unwrap any global. -		async := conv.Unwrap() -		var ok bool -		if oImpl, ok = async.(int64Observable); !ok { -			global.Error(errUnknownObserver, "failed to record asynchronous") -			return -		}  	default:  		global.Error(errUnknownObserver, "failed to record")  		return  	} -	if _, registered := r.int64[oImpl.observablID]; !registered { +	if _, registered := r.int64[oImpl.observableID]; !registered {  		if !oImpl.dropAggregation {  			global.Error(errUnregObserver, "failed to record",  				"name", oImpl.name, @@ -583,7 +585,12 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric  		return  	}  	c := metric.NewObserveConfig(opts) -	oImpl.observe(v, c.Attributes()) +	// Access to r.pipe.int64Measures is already guarded b a lock in pipeline.produce. +	// TODO (#5946): Refactor pipeline and observable measures. +	measures := r.pipe.int64Measures[oImpl.observableID] +	for _, m := range measures { +		m(context.Background(), v, c.Attributes()) +	}  }  type noopRegister struct{ embedded.Registration } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go b/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go index 67ee1b11a..dcd2182d9 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/periodic_reader.go @@ -251,18 +251,17 @@ func (r *PeriodicReader) collect(ctx context.Context, p interface{}, rm *metricd  	if err != nil {  		return err  	} -	var errs []error  	for _, producer := range r.externalProducers.Load().([]Producer) { -		externalMetrics, err := producer.Produce(ctx) -		if err != nil { -			errs = append(errs, err) +		externalMetrics, e := producer.Produce(ctx) +		if e != nil { +			err = errors.Join(err, e)  		}  		rm.ScopeMetrics = append(rm.ScopeMetrics, externalMetrics...)  	}  	global.Debug("PeriodicReader collection", "Data", rm) -	return unifyErrors(errs) +	return err  }  // export exports metric data m using r's exporter. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go b/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go index 823bf2fe3..775e24526 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/pipeline.go @@ -8,14 +8,13 @@ import (  	"context"  	"errors"  	"fmt" -	"strings"  	"sync"  	"sync/atomic"  	"go.opentelemetry.io/otel/internal/global" -	"go.opentelemetry.io/otel/metric"  	"go.opentelemetry.io/otel/metric/embedded"  	"go.opentelemetry.io/otel/sdk/instrumentation" +	"go.opentelemetry.io/otel/sdk/metric/exemplar"  	"go.opentelemetry.io/otel/sdk/metric/internal"  	"go.opentelemetry.io/otel/sdk/metric/internal/aggregate"  	"go.opentelemetry.io/otel/sdk/metric/internal/x" @@ -38,14 +37,17 @@ type instrumentSync struct {  	compAgg     aggregate.ComputeAggregation  } -func newPipeline(res *resource.Resource, reader Reader, views []View) *pipeline { +func newPipeline(res *resource.Resource, reader Reader, views []View, exemplarFilter exemplar.Filter) *pipeline {  	if res == nil {  		res = resource.Empty()  	}  	return &pipeline{ -		resource: res, -		reader:   reader, -		views:    views, +		resource:        res, +		reader:          reader, +		views:           views, +		int64Measures:   map[observableID[int64]][]aggregate.Measure[int64]{}, +		float64Measures: map[observableID[float64]][]aggregate.Measure[float64]{}, +		exemplarFilter:  exemplarFilter,  		// aggregations is lazy allocated when needed.  	}  } @@ -63,9 +65,26 @@ type pipeline struct {  	views  []View  	sync.Mutex -	aggregations   map[instrumentation.Scope][]instrumentSync -	callbacks      []func(context.Context) error -	multiCallbacks list.List +	int64Measures   map[observableID[int64]][]aggregate.Measure[int64] +	float64Measures map[observableID[float64]][]aggregate.Measure[float64] +	aggregations    map[instrumentation.Scope][]instrumentSync +	callbacks       []func(context.Context) error +	multiCallbacks  list.List +	exemplarFilter  exemplar.Filter +} + +// addInt64Measure adds a new int64 measure to the pipeline for each observer. +func (p *pipeline) addInt64Measure(id observableID[int64], m []aggregate.Measure[int64]) { +	p.Lock() +	defer p.Unlock() +	p.int64Measures[id] = m +} + +// addFloat64Measure adds a new float64 measure to the pipeline for each observer. +func (p *pipeline) addFloat64Measure(id observableID[float64], m []aggregate.Measure[float64]) { +	p.Lock() +	defer p.Unlock() +	p.float64Measures[id] = m  }  // addSync adds the instrumentSync to pipeline p with scope. This method is not @@ -105,14 +124,15 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics)  	p.Lock()  	defer p.Unlock() -	var errs multierror +	var err error  	for _, c := range p.callbacks {  		// TODO make the callbacks parallel. ( #3034 ) -		if err := c(ctx); err != nil { -			errs.append(err) +		if e := c(ctx); e != nil { +			err = errors.Join(err, e)  		}  		if err := ctx.Err(); err != nil {  			rm.Resource = nil +			clear(rm.ScopeMetrics) // Erase elements to let GC collect objects.  			rm.ScopeMetrics = rm.ScopeMetrics[:0]  			return err  		} @@ -120,12 +140,13 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics)  	for e := p.multiCallbacks.Front(); e != nil; e = e.Next() {  		// TODO make the callbacks parallel. ( #3034 )  		f := e.Value.(multiCallback) -		if err := f(ctx); err != nil { -			errs.append(err) +		if e := f(ctx); e != nil { +			err = errors.Join(err, e)  		}  		if err := ctx.Err(); err != nil {  			// This means the context expired before we finished running callbacks.  			rm.Resource = nil +			clear(rm.ScopeMetrics) // Erase elements to let GC collect objects.  			rm.ScopeMetrics = rm.ScopeMetrics[:0]  			return err  		} @@ -157,7 +178,7 @@ func (p *pipeline) produce(ctx context.Context, rm *metricdata.ResourceMetrics)  	rm.ScopeMetrics = rm.ScopeMetrics[:i] -	return errs.errorOrNil() +	return err  }  // inserter facilitates inserting of new instruments from a single scope into a @@ -219,7 +240,7 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation)  		measures []aggregate.Measure[N]  	) -	errs := &multierror{wrapped: errCreatingAggregators} +	var err error  	seen := make(map[uint64]struct{})  	for _, v := range i.pipeline.views {  		stream, match := v(inst) @@ -227,9 +248,9 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation)  			continue  		}  		matched = true -		in, id, err := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) -		if err != nil { -			errs.append(err) +		in, id, e := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) +		if e != nil { +			err = errors.Join(err, e)  		}  		if in == nil { // Drop aggregation.  			continue @@ -242,8 +263,12 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation)  		measures = append(measures, in)  	} +	if err != nil { +		err = errors.Join(errCreatingAggregators, err) +	} +  	if matched { -		return measures, errs.errorOrNil() +		return measures, err  	}  	// Apply implicit default view if no explicit matched. @@ -252,15 +277,18 @@ func (i *inserter[N]) Instrument(inst Instrument, readerAggregation Aggregation)  		Description: inst.Description,  		Unit:        inst.Unit,  	} -	in, _, err := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) -	if err != nil { -		errs.append(err) +	in, _, e := i.cachedAggregator(inst.Scope, inst.Kind, stream, readerAggregation) +	if e != nil { +		if err == nil { +			err = errCreatingAggregators +		} +		err = errors.Join(err, e)  	}  	if in != nil {  		// Ensured to have not seen given matched was false.  		measures = append(measures, in)  	} -	return measures, errs.errorOrNil() +	return measures, err  }  // addCallback registers a single instrument callback to be run when @@ -329,6 +357,9 @@ func (i *inserter[N]) cachedAggregator(scope instrumentation.Scope, kind Instrum  		// The view explicitly requested the default aggregation.  		stream.Aggregation = DefaultAggregationSelector(kind)  	} +	if stream.ExemplarReservoirProviderSelector == nil { +		stream.ExemplarReservoirProviderSelector = DefaultExemplarReservoirProviderSelector +	}  	if err := isAggregatorCompatible(kind, stream.Aggregation); err != nil {  		return nil, 0, fmt.Errorf( @@ -349,7 +380,7 @@ func (i *inserter[N]) cachedAggregator(scope instrumentation.Scope, kind Instrum  	cv := i.aggregators.Lookup(normID, func() aggVal[N] {  		b := aggregate.Builder[N]{  			Temporality:   i.pipeline.reader.temporality(kind), -			ReservoirFunc: reservoirFunc[N](stream.Aggregation), +			ReservoirFunc: reservoirFunc[N](stream.ExemplarReservoirProviderSelector(stream.Aggregation), i.pipeline.exemplarFilter),  		}  		b.Filter = stream.AttributeFilter  		// A value less than or equal to zero will disable the aggregation @@ -552,24 +583,16 @@ func isAggregatorCompatible(kind InstrumentKind, agg Aggregation) error {  // measurement.  type pipelines []*pipeline -func newPipelines(res *resource.Resource, readers []Reader, views []View) pipelines { +func newPipelines(res *resource.Resource, readers []Reader, views []View, exemplarFilter exemplar.Filter) pipelines {  	pipes := make([]*pipeline, 0, len(readers))  	for _, r := range readers { -		p := newPipeline(res, r, views) +		p := newPipeline(res, r, views, exemplarFilter)  		r.register(p)  		pipes = append(pipes, p)  	}  	return pipes  } -func (p pipelines) registerMultiCallback(c multiCallback) metric.Registration { -	unregs := make([]func(), len(p)) -	for i, pipe := range p { -		unregs[i] = pipe.addMultiCallback(c) -	} -	return unregisterFuncs{f: unregs} -} -  type unregisterFuncs struct {  	embedded.Registration  	f []func() @@ -602,15 +625,15 @@ func newResolver[N int64 | float64](p pipelines, vc *cache[string, instID]) reso  func (r resolver[N]) Aggregators(id Instrument) ([]aggregate.Measure[N], error) {  	var measures []aggregate.Measure[N] -	errs := &multierror{} +	var err error  	for _, i := range r.inserters { -		in, err := i.Instrument(id, i.readerDefaultAggregation(id.Kind)) -		if err != nil { -			errs.append(err) +		in, e := i.Instrument(id, i.readerDefaultAggregation(id.Kind)) +		if e != nil { +			err = errors.Join(err, e)  		}  		measures = append(measures, in...)  	} -	return measures, errs.errorOrNil() +	return measures, err  }  // HistogramAggregators returns the histogram Aggregators that must be updated by the instrument @@ -619,37 +642,18 @@ func (r resolver[N]) Aggregators(id Instrument) ([]aggregate.Measure[N], error)  func (r resolver[N]) HistogramAggregators(id Instrument, boundaries []float64) ([]aggregate.Measure[N], error) {  	var measures []aggregate.Measure[N] -	errs := &multierror{} +	var err error  	for _, i := range r.inserters {  		agg := i.readerDefaultAggregation(id.Kind)  		if histAgg, ok := agg.(AggregationExplicitBucketHistogram); ok && len(boundaries) > 0 {  			histAgg.Boundaries = boundaries  			agg = histAgg  		} -		in, err := i.Instrument(id, agg) -		if err != nil { -			errs.append(err) +		in, e := i.Instrument(id, agg) +		if e != nil { +			err = errors.Join(err, e)  		}  		measures = append(measures, in...)  	} -	return measures, errs.errorOrNil() -} - -type multierror struct { -	wrapped error -	errors  []string -} - -func (m *multierror) errorOrNil() error { -	if len(m.errors) == 0 { -		return nil -	} -	if m.wrapped == nil { -		return errors.New(strings.Join(m.errors, "; ")) -	} -	return fmt.Errorf("%w: %s", m.wrapped, strings.Join(m.errors, "; ")) -} - -func (m *multierror) append(err error) { -	m.errors = append(m.errors, err.Error()) +	return measures, err  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go b/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go index a82af538e..2fca89e5a 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/provider.go @@ -42,7 +42,7 @@ func NewMeterProvider(options ...Option) *MeterProvider {  	flush, sdown := conf.readerSignals()  	mp := &MeterProvider{ -		pipes:      newPipelines(conf.res, conf.readers, conf.views), +		pipes:      newPipelines(conf.res, conf.readers, conf.views, conf.exemplarFilter),  		forceFlush: flush,  		shutdown:   sdown,  	} @@ -76,15 +76,17 @@ func (mp *MeterProvider) Meter(name string, options ...metric.MeterOption) metri  	c := metric.NewMeterConfig(options...)  	s := instrumentation.Scope{ -		Name:      name, -		Version:   c.InstrumentationVersion(), -		SchemaURL: c.SchemaURL(), +		Name:       name, +		Version:    c.InstrumentationVersion(), +		SchemaURL:  c.SchemaURL(), +		Attributes: c.InstrumentationAttributes(),  	}  	global.Info("Meter created",  		"Name", s.Name,  		"Version", s.Version,  		"SchemaURL", s.SchemaURL, +		"Attributes", s.Attributes,  	)  	return mp.meters.Lookup(s, func() *meter { diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/reader.go b/vendor/go.opentelemetry.io/otel/sdk/metric/reader.go index d94bdee75..d13a70697 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/reader.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/reader.go @@ -5,26 +5,26 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"  import (  	"context" -	"fmt" +	"errors"  	"go.opentelemetry.io/otel/sdk/metric/metricdata"  )  // errDuplicateRegister is logged by a Reader when an attempt to registered it  // more than once occurs. -var errDuplicateRegister = fmt.Errorf("duplicate reader registration") +var errDuplicateRegister = errors.New("duplicate reader registration")  // ErrReaderNotRegistered is returned if Collect or Shutdown are called before  // the reader is registered with a MeterProvider. -var ErrReaderNotRegistered = fmt.Errorf("reader is not registered") +var ErrReaderNotRegistered = errors.New("reader is not registered")  // ErrReaderShutdown is returned if Collect or Shutdown are called after a  // reader has been Shutdown once. -var ErrReaderShutdown = fmt.Errorf("reader is shutdown") +var ErrReaderShutdown = errors.New("reader is shutdown")  // errNonPositiveDuration is logged when an environmental variable  // has non-positive value. -var errNonPositiveDuration = fmt.Errorf("non-positive duration") +var errNonPositiveDuration = errors.New("non-positive duration")  // Reader is the interface used between the SDK and an  // exporter.  Control flow is bi-directional through the @@ -60,8 +60,8 @@ type Reader interface {  	aggregation(InstrumentKind) Aggregation // nolint:revive  // import-shadow for method scoped by type.  	// Collect gathers and returns all metric data related to the Reader from -	// the SDK and stores it in out. An error is returned if this is called -	// after Shutdown or if out is nil. +	// the SDK and stores it in rm. An error is returned if this is called +	// after Shutdown or if rm is nil.  	//  	// This method needs to be concurrent safe, and the cancellation of the  	// passed context is expected to be honored. diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go index 44316caa1..7c4b8530d 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/version.go @@ -5,5 +5,5 @@ package metric // import "go.opentelemetry.io/otel/sdk/metric"  // version is the current release version of the metric SDK in use.  func version() string { -	return "1.29.0" +	return "1.34.0"  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/metric/view.go b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go index cd08c6732..630890f42 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/metric/view.go +++ b/vendor/go.opentelemetry.io/otel/sdk/metric/view.go @@ -96,11 +96,12 @@ func NewView(criteria Instrument, mask Stream) View {  	return func(i Instrument) (Stream, bool) {  		if matchFunc(i) {  			return Stream{ -				Name:            nonZero(mask.Name, i.Name), -				Description:     nonZero(mask.Description, i.Description), -				Unit:            nonZero(mask.Unit, i.Unit), -				Aggregation:     agg, -				AttributeFilter: mask.AttributeFilter, +				Name:                              nonZero(mask.Name, i.Name), +				Description:                       nonZero(mask.Description, i.Description), +				Unit:                              nonZero(mask.Unit, i.Unit), +				Aggregation:                       agg, +				AttributeFilter:                   mask.AttributeFilter, +				ExemplarReservoirProviderSelector: mask.ExemplarReservoirProviderSelector,  			}, true  		}  		return Stream{}, false diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go index 95a61d61d..c02aeefdd 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/auto.go @@ -7,7 +7,6 @@ import (  	"context"  	"errors"  	"fmt" -	"strings"  )  // ErrPartialResource is returned by a detector when complete source @@ -57,62 +56,37 @@ func Detect(ctx context.Context, detectors ...Detector) (*Resource, error) {  // these errors will be returned. Otherwise, nil is returned.  func detect(ctx context.Context, res *Resource, detectors []Detector) error {  	var ( -		r    *Resource -		errs detectErrs -		err  error +		r   *Resource +		err error +		e   error  	)  	for _, detector := range detectors {  		if detector == nil {  			continue  		} -		r, err = detector.Detect(ctx) -		if err != nil { -			errs = append(errs, err) -			if !errors.Is(err, ErrPartialResource) { +		r, e = detector.Detect(ctx) +		if e != nil { +			err = errors.Join(err, e) +			if !errors.Is(e, ErrPartialResource) {  				continue  			}  		} -		r, err = Merge(res, r) -		if err != nil { -			errs = append(errs, err) +		r, e = Merge(res, r) +		if e != nil { +			err = errors.Join(err, e)  		}  		*res = *r  	} -	if len(errs) == 0 { -		return nil -	} -	if errors.Is(errs, ErrSchemaURLConflict) { -		// If there has been a merge conflict, ensure the resource has no -		// schema URL. -		res.schemaURL = "" -	} -	return errs -} - -type detectErrs []error - -func (e detectErrs) Error() string { -	errStr := make([]string, len(e)) -	for i, err := range e { -		errStr[i] = fmt.Sprintf("* %s", err) -	} - -	format := "%d errors occurred detecting resource:\n\t%s" -	return fmt.Sprintf(format, len(e), strings.Join(errStr, "\n\t")) -} +	if err != nil { +		if errors.Is(err, ErrSchemaURLConflict) { +			// If there has been a merge conflict, ensure the resource has no +			// schema URL. +			res.schemaURL = "" +		} -func (e detectErrs) Unwrap() error { -	switch len(e) { -	case 0: -		return nil -	case 1: -		return e[0] +		err = fmt.Errorf("error detecting resource: %w", err)  	} -	return e[1:] -} - -func (e detectErrs) Is(target error) bool { -	return len(e) != 0 && errors.Is(e[0], target) +	return err  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go index 6ac1cdbf7..cf3c88e15 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/builtin.go @@ -20,15 +20,13 @@ type (  	// telemetrySDK is a Detector that provides information about  	// the OpenTelemetry SDK used.  This Detector is included as a  	// builtin. If these resource attributes are not wanted, use -	// the WithTelemetrySDK(nil) or WithoutBuiltin() options to -	// explicitly disable them. +	// resource.New() to explicitly disable them.  	telemetrySDK struct{}  	// host is a Detector that provides information about the host  	// being run on. This Detector is included as a builtin. If  	// these resource attributes are not wanted, use the -	// WithHost(nil) or WithoutBuiltin() options to explicitly -	// disable them. +	// resource.New() to explicitly disable them.  	host struct{}  	stringDetector struct { diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go index 71386e2da..3677c83d7 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/host_id_windows.go @@ -10,17 +10,16 @@ import (  	"golang.org/x/sys/windows/registry"  ) -// implements hostIDReader +// implements hostIDReader.  type hostIDReaderWindows struct{} -// read reads MachineGuid from the windows registry key: -// SOFTWARE\Microsoft\Cryptography +// read reads MachineGuid from the Windows registry key: +// SOFTWARE\Microsoft\Cryptography.  func (*hostIDReaderWindows) read() (string, error) {  	k, err := registry.OpenKey(  		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`,  		registry.QUERY_VALUE|registry.WOW64_64KEY,  	) -  	if err != nil {  		return "", err  	} diff --git a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go index 5e3d199d7..a6a5a53c0 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go +++ b/vendor/go.opentelemetry.io/otel/sdk/resource/os_windows.go @@ -17,7 +17,6 @@ import (  func platformOSDescription() (string, error) {  	k, err := registry.OpenKey(  		registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) -  	if err != nil {  		return "", err  	} diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go index 1d399a75d..ccc97e1b6 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/batch_span_processor.go @@ -280,6 +280,7 @@ func (bsp *batchSpanProcessor) exportSpans(ctx context.Context) error {  		//  		// It is up to the exporter to implement any type of retry logic if a batch is failing  		// to be exported, since it is specific to the protocol and backend being sent to. +		clear(bsp.batch) // Erase elements to let GC collect objects  		bsp.batch = bsp.batch[:0]  		if err != nil { @@ -316,7 +317,11 @@ func (bsp *batchSpanProcessor) processQueue() {  			bsp.batchMutex.Unlock()  			if shouldExport {  				if !bsp.timer.Stop() { -					<-bsp.timer.C +					// Handle both GODEBUG=asynctimerchan=[0|1] properly. +					select { +					case <-bsp.timer.C: +					default: +					}  				}  				if err := bsp.exportSpans(ctx); err != nil {  					otel.Handle(err) diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go b/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go index 821c83faa..8c308dd60 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/evictedqueue.go @@ -12,25 +12,26 @@ import (  // evictedQueue is a FIFO queue with a configurable capacity.  type evictedQueue[T any] struct { -	queue        []T -	capacity     int -	droppedCount int -	logDropped   func() +	queue          []T +	capacity       int +	droppedCount   int +	logDroppedMsg  string +	logDroppedOnce sync.Once  }  func newEvictedQueueEvent(capacity int) evictedQueue[Event] {  	// Do not pre-allocate queue, do this lazily.  	return evictedQueue[Event]{ -		capacity:   capacity, -		logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Event") }), +		capacity:      capacity, +		logDroppedMsg: "limit reached: dropping trace trace.Event",  	}  }  func newEvictedQueueLink(capacity int) evictedQueue[Link] {  	// Do not pre-allocate queue, do this lazily.  	return evictedQueue[Link]{ -		capacity:   capacity, -		logDropped: sync.OnceFunc(func() { global.Warn("limit reached: dropping trace trace.Link") }), +		capacity:      capacity, +		logDroppedMsg: "limit reached: dropping trace trace.Link",  	}  } @@ -53,6 +54,10 @@ func (eq *evictedQueue[T]) add(value T) {  	eq.queue = append(eq.queue, value)  } +func (eq *evictedQueue[T]) logDropped() { +	eq.logDroppedOnce.Do(func() { global.Warn(eq.logDroppedMsg) }) +} +  // copy returns a copy of the evictedQueue.  func (eq *evictedQueue[T]) copy() []T {  	return slices.Clone(eq.queue) diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go index 14c2e5beb..185aa7c08 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/provider.go @@ -139,9 +139,10 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T  		name = defaultTracerName  	}  	is := instrumentation.Scope{ -		Name:      name, -		Version:   c.InstrumentationVersion(), -		SchemaURL: c.SchemaURL(), +		Name:       name, +		Version:    c.InstrumentationVersion(), +		SchemaURL:  c.SchemaURL(), +		Attributes: c.InstrumentationAttributes(),  	}  	t, ok := func() (trace.Tracer, bool) { @@ -168,7 +169,7 @@ func (p *TracerProvider) Tracer(name string, opts ...trace.TracerOption) trace.T  		//   slowing down all tracing consumers.  		// - Logging code may be instrumented with tracing and deadlock because it could try  		//   acquiring the same non-reentrant mutex. -		global.Info("Tracer created", "name", name, "version", is.Version, "schemaURL", is.SchemaURL) +		global.Info("Tracer created", "name", name, "version", is.Version, "schemaURL", is.SchemaURL, "attributes", is.Attributes)  	}  	return t  } diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/sampler_env.go b/vendor/go.opentelemetry.io/otel/sdk/trace/sampler_env.go index d2d1f7246..9b672a1d7 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/sampler_env.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/sampler_env.go @@ -5,7 +5,6 @@ package trace // import "go.opentelemetry.io/otel/sdk/trace"  import (  	"errors" -	"fmt"  	"os"  	"strconv"  	"strings" @@ -26,7 +25,7 @@ const (  type errUnsupportedSampler string  func (e errUnsupportedSampler) Error() string { -	return fmt.Sprintf("unsupported sampler: %s", string(e)) +	return "unsupported sampler: " + string(e)  }  var ( @@ -39,7 +38,7 @@ type samplerArgParseError struct {  }  func (e samplerArgParseError) Error() string { -	return fmt.Sprintf("parsing sampler argument: %s", e.parseErr.Error()) +	return "parsing sampler argument: " + e.parseErr.Error()  }  func (e samplerArgParseError) Unwrap() error { diff --git a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go index 4945f5083..8f4fc3850 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/trace/span.go +++ b/vendor/go.opentelemetry.io/otel/sdk/trace/span.go @@ -174,6 +174,17 @@ func (s *recordingSpan) IsRecording() bool {  	s.mu.Lock()  	defer s.mu.Unlock() +	return s.isRecording() +} + +// isRecording returns if this span is being recorded. If this span has ended +// this will return false. +// +// This method assumes s.mu.Lock is held by the caller. +func (s *recordingSpan) isRecording() bool { +	if s == nil { +		return false +	}  	return s.endTime.IsZero()  } @@ -182,11 +193,15 @@ func (s *recordingSpan) IsRecording() bool {  // included in the set status when the code is for an error. If this span is  // not being recorded than this method does nothing.  func (s *recordingSpan) SetStatus(code codes.Code, description string) { -	if !s.IsRecording() { +	if s == nil {  		return  	} +  	s.mu.Lock()  	defer s.mu.Unlock() +	if !s.isRecording() { +		return +	}  	if s.status.Code > code {  		return  	} @@ -210,12 +225,15 @@ func (s *recordingSpan) SetStatus(code codes.Code, description string) {  // attributes the span is configured to have, the last added attributes will  // be dropped.  func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) { -	if !s.IsRecording() { +	if s == nil || len(attributes) == 0 {  		return  	}  	s.mu.Lock()  	defer s.mu.Unlock() +	if !s.isRecording() { +		return +	}  	limit := s.tracer.provider.spanLimits.AttributeCountLimit  	if limit == 0 { @@ -233,7 +251,7 @@ func (s *recordingSpan) SetAttributes(attributes ...attribute.KeyValue) {  	// Otherwise, add without deduplication. When attributes are read they  	// will be deduplicated, optimizing the operation. -	s.attributes = slices.Grow(s.attributes, len(s.attributes)+len(attributes)) +	s.attributes = slices.Grow(s.attributes, len(attributes))  	for _, a := range attributes {  		if !a.Valid() {  			// Drop all invalid attributes. @@ -280,13 +298,17 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {  	// Do not set a capacity when creating this map. Benchmark testing has  	// showed this to only add unused memory allocations in general use. -	exists := make(map[attribute.Key]int) -	s.dedupeAttrsFromRecord(&exists) +	exists := make(map[attribute.Key]int, len(s.attributes)) +	s.dedupeAttrsFromRecord(exists)  	// Now that s.attributes is deduplicated, adding unique attributes up to  	// the capacity of s will not over allocate s.attributes. -	sum := len(attrs) + len(s.attributes) -	s.attributes = slices.Grow(s.attributes, min(sum, limit)) + +	// max size = limit +	maxCap := min(len(attrs)+len(s.attributes), limit) +	if cap(s.attributes) < maxCap { +		s.attributes = slices.Grow(s.attributes, maxCap-cap(s.attributes)) +	}  	for _, a := range attrs {  		if !a.Valid() {  			// Drop all invalid attributes. @@ -296,6 +318,7 @@ func (s *recordingSpan) addOverCapAttrs(limit int, attrs []attribute.KeyValue) {  		if idx, ok := exists[a.Key]; ok {  			// Perform all updates before dropping, even when at capacity. +			a = truncateAttr(s.tracer.provider.spanLimits.AttributeValueLengthLimit, a)  			s.attributes[idx] = a  			continue  		} @@ -324,54 +347,99 @@ func truncateAttr(limit int, attr attribute.KeyValue) attribute.KeyValue {  	}  	switch attr.Value.Type() {  	case attribute.STRING: -		if v := attr.Value.AsString(); len(v) > limit { -			return attr.Key.String(safeTruncate(v, limit)) -		} +		v := attr.Value.AsString() +		return attr.Key.String(truncate(limit, v))  	case attribute.STRINGSLICE:  		v := attr.Value.AsStringSlice()  		for i := range v { -			if len(v[i]) > limit { -				v[i] = safeTruncate(v[i], limit) -			} +			v[i] = truncate(limit, v[i])  		}  		return attr.Key.StringSlice(v)  	}  	return attr  } -// safeTruncate truncates the string and guarantees valid UTF-8 is returned. -func safeTruncate(input string, limit int) string { -	if trunc, ok := safeTruncateValidUTF8(input, limit); ok { -		return trunc +// truncate returns a truncated version of s such that it contains less than +// the limit number of characters. Truncation is applied by returning the limit +// number of valid characters contained in s. +// +// If limit is negative, it returns the original string. +// +// UTF-8 is supported. When truncating, all invalid characters are dropped +// before applying truncation. +// +// If s already contains less than the limit number of bytes, it is returned +// unchanged. No invalid characters are removed. +func truncate(limit int, s string) string { +	// This prioritize performance in the following order based on the most +	// common expected use-cases. +	// +	//  - Short values less than the default limit (128). +	//  - Strings with valid encodings that exceed the limit. +	//  - No limit. +	//  - Strings with invalid encodings that exceed the limit. +	if limit < 0 || len(s) <= limit { +		return s +	} + +	// Optimistically, assume all valid UTF-8. +	var b strings.Builder +	count := 0 +	for i, c := range s { +		if c != utf8.RuneError { +			count++ +			if count > limit { +				return s[:i] +			} +			continue +		} + +		_, size := utf8.DecodeRuneInString(s[i:]) +		if size == 1 { +			// Invalid encoding. +			b.Grow(len(s) - 1) +			_, _ = b.WriteString(s[:i]) +			s = s[i:] +			break +		} +	} + +	// Fast-path, no invalid input. +	if b.Cap() == 0 { +		return s  	} -	trunc, _ := safeTruncateValidUTF8(strings.ToValidUTF8(input, ""), limit) -	return trunc -} -// safeTruncateValidUTF8 returns a copy of the input string safely truncated to -// limit. The truncation is ensured to occur at the bounds of complete UTF-8 -// characters. If invalid encoding of UTF-8 is encountered, input is returned -// with false, otherwise, the truncated input will be returned with true. -func safeTruncateValidUTF8(input string, limit int) (string, bool) { -	for cnt := 0; cnt <= limit; { -		r, size := utf8.DecodeRuneInString(input[cnt:]) -		if r == utf8.RuneError { -			return input, false +	// Truncate while validating UTF-8. +	for i := 0; i < len(s) && count < limit; { +		c := s[i] +		if c < utf8.RuneSelf { +			// Optimization for single byte runes (common case). +			_ = b.WriteByte(c) +			i++ +			count++ +			continue  		} -		if cnt+size > limit { -			return input[:cnt], true +		_, size := utf8.DecodeRuneInString(s[i:]) +		if size == 1 { +			// We checked for all 1-byte runes above, this is a RuneError. +			i++ +			continue  		} -		cnt += size + +		_, _ = b.WriteString(s[i : i+size]) +		i += size +		count++  	} -	return input, true + +	return b.String()  }  // End ends the span. This method does nothing if the span is already ended or  // is not being recorded.  // -// The only SpanOption currently supported is WithTimestamp which will set the -// end time for a Span's life-cycle. +// The only SpanEndOption currently supported are [trace.WithTimestamp], and +// [trace.WithStackTrace].  //  // If this method is called while panicking an error event is added to the  // Span before ending it and the panic is continued. @@ -386,9 +454,10 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {  	// the span's duration in case some operation below takes a while.  	et := monotonicEndTime(s.startTime) -	// Do relative expensive check now that we have an end time and see if we -	// need to do any more processing. -	if !s.IsRecording() { +	// Lock the span now that we have an end time and see if we need to do any more processing. +	s.mu.Lock() +	if !s.isRecording() { +		s.mu.Unlock()  		return  	} @@ -413,10 +482,11 @@ func (s *recordingSpan) End(options ...trace.SpanEndOption) {  	}  	if s.executionTracerTaskEnd != nil { +		s.mu.Unlock()  		s.executionTracerTaskEnd() +		s.mu.Lock()  	} -	s.mu.Lock()  	// Setting endTime to non-zero marks the span as ended and not recording.  	if config.Timestamp().IsZero() {  		s.endTime = et @@ -450,7 +520,13 @@ func monotonicEndTime(start time.Time) time.Time {  // does not change the Span status. If this span is not being recorded or err is nil  // than this method does nothing.  func (s *recordingSpan) RecordError(err error, opts ...trace.EventOption) { -	if s == nil || err == nil || !s.IsRecording() { +	if s == nil || err == nil { +		return +	} + +	s.mu.Lock() +	defer s.mu.Unlock() +	if !s.isRecording() {  		return  	} @@ -486,14 +562,23 @@ func recordStackTrace() string {  }  // AddEvent adds an event with the provided name and options. If this span is -// not being recorded than this method does nothing. +// not being recorded then this method does nothing.  func (s *recordingSpan) AddEvent(name string, o ...trace.EventOption) { -	if !s.IsRecording() { +	if s == nil { +		return +	} + +	s.mu.Lock() +	defer s.mu.Unlock() +	if !s.isRecording() {  		return  	}  	s.addEvent(name, o...)  } +// addEvent adds an event with the provided name and options. +// +// This method assumes s.mu.Lock is held by the caller.  func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) {  	c := trace.NewEventConfig(o...)  	e := Event{Name: name, Attributes: c.Attributes(), Time: c.Timestamp()} @@ -510,20 +595,21 @@ func (s *recordingSpan) addEvent(name string, o ...trace.EventOption) {  		e.Attributes = e.Attributes[:limit]  	} -	s.mu.Lock()  	s.events.add(e) -	s.mu.Unlock()  }  // SetName sets the name of this span. If this span is not being recorded than  // this method does nothing.  func (s *recordingSpan) SetName(name string) { -	if !s.IsRecording() { +	if s == nil {  		return  	}  	s.mu.Lock()  	defer s.mu.Unlock() +	if !s.isRecording() { +		return +	}  	s.name = name  } @@ -579,29 +665,26 @@ func (s *recordingSpan) Attributes() []attribute.KeyValue {  func (s *recordingSpan) dedupeAttrs() {  	// Do not set a capacity when creating this map. Benchmark testing has  	// showed this to only add unused memory allocations in general use. -	exists := make(map[attribute.Key]int) -	s.dedupeAttrsFromRecord(&exists) +	exists := make(map[attribute.Key]int, len(s.attributes)) +	s.dedupeAttrsFromRecord(exists)  }  // dedupeAttrsFromRecord deduplicates the attributes of s to fit capacity  // using record as the record of unique attribute keys to their index.  //  // This method assumes s.mu.Lock is held by the caller. -func (s *recordingSpan) dedupeAttrsFromRecord(record *map[attribute.Key]int) { +func (s *recordingSpan) dedupeAttrsFromRecord(record map[attribute.Key]int) {  	// Use the fact that slices share the same backing array.  	unique := s.attributes[:0]  	for _, a := range s.attributes { -		if idx, ok := (*record)[a.Key]; ok { +		if idx, ok := record[a.Key]; ok {  			unique[idx] = a  		} else {  			unique = append(unique, a) -			(*record)[a.Key] = len(unique) - 1 +			record[a.Key] = len(unique) - 1  		}  	} -	// s.attributes have element types of attribute.KeyValue. These types are -	// not pointers and they themselves do not contain pointer fields, -	// therefore the duplicate values do not need to be zeroed for them to be -	// garbage collected. +	clear(s.attributes[len(unique):]) // Erase unneeded elements to let GC collect objects.  	s.attributes = unique  } @@ -657,7 +740,7 @@ func (s *recordingSpan) Resource() *resource.Resource {  }  func (s *recordingSpan) AddLink(link trace.Link) { -	if !s.IsRecording() { +	if s == nil {  		return  	}  	if !link.SpanContext.IsValid() && len(link.Attributes) == 0 && @@ -665,6 +748,12 @@ func (s *recordingSpan) AddLink(link trace.Link) {  		return  	} +	s.mu.Lock() +	defer s.mu.Unlock() +	if !s.isRecording() { +		return +	} +  	l := Link{SpanContext: link.SpanContext, Attributes: link.Attributes}  	// Discard attributes over limit. @@ -678,9 +767,7 @@ func (s *recordingSpan) AddLink(link trace.Link) {  		l.Attributes = l.Attributes[:limit]  	} -	s.mu.Lock()  	s.links.add(l) -	s.mu.Unlock()  }  // DroppedAttributes returns the number of attributes dropped by the span @@ -755,12 +842,16 @@ func (s *recordingSpan) snapshot() ReadOnlySpan {  }  func (s *recordingSpan) addChild() { -	if !s.IsRecording() { +	if s == nil {  		return  	} +  	s.mu.Lock() +	defer s.mu.Unlock() +	if !s.isRecording() { +		return +	}  	s.childSpanCount++ -	s.mu.Unlock()  }  func (*recordingSpan) private() {} diff --git a/vendor/go.opentelemetry.io/otel/sdk/version.go b/vendor/go.opentelemetry.io/otel/sdk/version.go index b7cede891..6b4038510 100644 --- a/vendor/go.opentelemetry.io/otel/sdk/version.go +++ b/vendor/go.opentelemetry.io/otel/sdk/version.go @@ -5,5 +5,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk"  // Version is the current release version of the OpenTelemetry SDK in use.  func Version() string { -	return "1.29.0" +	return "1.34.0"  } diff --git a/vendor/go.opentelemetry.io/otel/trace/config.go b/vendor/go.opentelemetry.io/otel/trace/config.go index 273d58e00..9c0b720a4 100644 --- a/vendor/go.opentelemetry.io/otel/trace/config.go +++ b/vendor/go.opentelemetry.io/otel/trace/config.go @@ -213,7 +213,7 @@ var _ SpanStartEventOption = attributeOption{}  // WithAttributes adds the attributes related to a span life-cycle event.  // These attributes are used to describe the work a Span represents when this -// option is provided to a Span's start or end events. Otherwise, these +// option is provided to a Span's start event. Otherwise, these  // attributes provide additional information about the event being recorded  // (e.g. error, state change, processing progress, system event).  // diff --git a/vendor/go.opentelemetry.io/otel/trace/context.go b/vendor/go.opentelemetry.io/otel/trace/context.go index 5650a174b..8c45a7107 100644 --- a/vendor/go.opentelemetry.io/otel/trace/context.go +++ b/vendor/go.opentelemetry.io/otel/trace/context.go @@ -22,7 +22,7 @@ func ContextWithSpanContext(parent context.Context, sc SpanContext) context.Cont  	return ContextWithSpan(parent, nonRecordingSpan{sc: sc})  } -// ContextWithRemoteSpanContext returns a copy of parent with rsc set explicly +// ContextWithRemoteSpanContext returns a copy of parent with rsc set explicitly  // as a remote SpanContext and as the current Span. The Span implementation  // that wraps rsc is non-recording and performs no operations other than to  // return rsc as the SpanContext from the SpanContext method. diff --git a/vendor/go.opentelemetry.io/otel/trace/doc.go b/vendor/go.opentelemetry.io/otel/trace/doc.go index d661c5d10..cdbf41d6d 100644 --- a/vendor/go.opentelemetry.io/otel/trace/doc.go +++ b/vendor/go.opentelemetry.io/otel/trace/doc.go @@ -96,7 +96,7 @@ can embed the API interface directly.  This option is not recommended. It will lead to publishing packages that  contain runtime panics when users update to newer versions of -[go.opentelemetry.io/otel/trace], which may be done with a trasitive +[go.opentelemetry.io/otel/trace], which may be done with a transitive  dependency.  Finally, an author can embed another implementation in theirs. The embedded diff --git a/vendor/go.opentelemetry.io/otel/verify_examples.sh b/vendor/go.opentelemetry.io/otel/verify_examples.sh deleted file mode 100644 index e57bf57fc..000000000 --- a/vendor/go.opentelemetry.io/otel/verify_examples.sh +++ /dev/null @@ -1,74 +0,0 @@ -#!/bin/bash - -# Copyright The OpenTelemetry Authors -# SPDX-License-Identifier: Apache-2.0 - -set -euo pipefail - -cd $(dirname $0) -TOOLS_DIR=$(pwd)/.tools - -if [ -z "${GOPATH}" ] ; then -	printf "GOPATH is not defined.\n" -	exit -1 -fi - -if [ ! -d "${GOPATH}" ] ; then -	printf "GOPATH ${GOPATH} is invalid \n" -	exit -1 -fi - -# Pre-requisites -if ! git diff --quiet; then \ -	git status -	printf "\n\nError: working tree is not clean\n" -	exit -1 -fi - -if [ "$(git tag --contains $(git log -1 --pretty=format:"%H"))" = "" ] ; then -	printf "$(git log -1)" -	printf "\n\nError: HEAD is not pointing to a tagged version" -fi - -make ${TOOLS_DIR}/gojq - -DIR_TMP="${GOPATH}/src/oteltmp/" -rm -rf $DIR_TMP -mkdir -p $DIR_TMP - -printf "Copy examples to ${DIR_TMP}\n" -cp -a ./example ${DIR_TMP} - -# Update go.mod files -printf "Update go.mod: rename module and remove replace\n" - -PACKAGE_DIRS=$(find . -mindepth 2 -type f -name 'go.mod' -exec dirname {} \; | egrep 'example' | sed 's/^\.\///' | sort) - -for dir in $PACKAGE_DIRS; do -	printf "  Update go.mod for $dir\n" -	(cd "${DIR_TMP}/${dir}" && \ -	 # replaces is ("mod1" "mod2" …) -	 replaces=($(go mod edit -json | ${TOOLS_DIR}/gojq '.Replace[].Old.Path')) && \ -	 # strip double quotes -	 replaces=("${replaces[@]%\"}") && \ -	 replaces=("${replaces[@]#\"}") && \ -	 # make an array (-dropreplace=mod1 -dropreplace=mod2 …) -	 dropreplaces=("${replaces[@]/#/-dropreplace=}") && \ -	 go mod edit -module "oteltmp/${dir}" "${dropreplaces[@]}" && \ -	 go mod tidy) -done -printf "Update done:\n\n" - -# Build directories that contain main package. These directories are different than -# directories that contain go.mod files. -printf "Build examples:\n" -EXAMPLES=$(./get_main_pkgs.sh ./example) -for ex in $EXAMPLES; do -	printf "  Build $ex in ${DIR_TMP}/${ex}\n" -	(cd "${DIR_TMP}/${ex}" && \ -	 go build .) -done - -# Cleanup -printf "Remove copied files.\n" -rm -rf $DIR_TMP diff --git a/vendor/go.opentelemetry.io/otel/version.go b/vendor/go.opentelemetry.io/otel/version.go index f67039ed1..eb22002d8 100644 --- a/vendor/go.opentelemetry.io/otel/version.go +++ b/vendor/go.opentelemetry.io/otel/version.go @@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel"  // Version is the current release version of OpenTelemetry in use.  func Version() string { -	return "1.29.0" +	return "1.34.0"  } diff --git a/vendor/go.opentelemetry.io/otel/versions.yaml b/vendor/go.opentelemetry.io/otel/versions.yaml index 3ba611d71..ce4fe59b0 100644 --- a/vendor/go.opentelemetry.io/otel/versions.yaml +++ b/vendor/go.opentelemetry.io/otel/versions.yaml @@ -3,19 +3,13 @@  module-sets:    stable-v1: -    version: v1.29.0 +    version: v1.34.0      modules:        - go.opentelemetry.io/otel        - go.opentelemetry.io/otel/bridge/opencensus        - go.opentelemetry.io/otel/bridge/opencensus/test        - go.opentelemetry.io/otel/bridge/opentracing        - go.opentelemetry.io/otel/bridge/opentracing/test -      - go.opentelemetry.io/otel/example/dice -      - go.opentelemetry.io/otel/example/namedtracer -      - go.opentelemetry.io/otel/example/opencensus -      - go.opentelemetry.io/otel/example/otel-collector -      - go.opentelemetry.io/otel/example/passthrough -      - go.opentelemetry.io/otel/example/zipkin        - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc        - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp        - go.opentelemetry.io/otel/exporters/otlp/otlptrace @@ -29,12 +23,11 @@ module-sets:        - go.opentelemetry.io/otel/sdk/metric        - go.opentelemetry.io/otel/trace    experimental-metrics: -    version: v0.51.0 +    version: v0.56.0      modules: -      - go.opentelemetry.io/otel/example/prometheus        - go.opentelemetry.io/otel/exporters/prometheus    experimental-logs: -    version: v0.5.0 +    version: v0.10.0      modules:        - go.opentelemetry.io/otel/log        - go.opentelemetry.io/otel/sdk/log @@ -42,7 +35,7 @@ module-sets:        - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp        - go.opentelemetry.io/otel/exporters/stdout/stdoutlog    experimental-schema: -    version: v0.0.8 +    version: v0.0.12      modules:        - go.opentelemetry.io/otel/schema  excluded-modules: | 
