[chore] Roll otel deps back to v1.29.0 / v0.51.0 (#3337)

This commit is contained in:
tobi 2024-09-24 12:26:26 +02:00 committed by GitHub
parent e59d2384e8
commit de72855790
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 252 additions and 372 deletions

18
go.mod
View file

@ -64,14 +64,14 @@ require (
github.com/uptrace/bun/extra/bunotel v1.2.1 github.com/uptrace/bun/extra/bunotel v1.2.1
github.com/wagslane/go-password-validator v0.3.0 github.com/wagslane/go-password-validator v0.3.0
github.com/yuin/goldmark v1.7.4 github.com/yuin/goldmark v1.7.4
go.opentelemetry.io/otel v1.30.0 go.opentelemetry.io/otel v1.29.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
go.opentelemetry.io/otel/exporters/prometheus v0.52.0 go.opentelemetry.io/otel/exporters/prometheus v0.51.0
go.opentelemetry.io/otel/metric v1.30.0 go.opentelemetry.io/otel/metric v1.29.0
go.opentelemetry.io/otel/sdk v1.30.0 go.opentelemetry.io/otel/sdk v1.29.0
go.opentelemetry.io/otel/sdk/metric v1.30.0 go.opentelemetry.io/otel/sdk/metric v1.29.0
go.opentelemetry.io/otel/trace v1.30.0 go.opentelemetry.io/otel/trace v1.29.0
go.uber.org/automaxprocs v1.5.3 go.uber.org/automaxprocs v1.5.3
golang.org/x/crypto v0.27.0 golang.org/x/crypto v0.27.0
golang.org/x/image v0.20.0 golang.org/x/image v0.20.0
@ -208,7 +208,7 @@ require (
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.8.0 // indirect golang.org/x/arch v0.8.0 // indirect

36
go.sum
View file

@ -638,24 +638,24 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 h1:lsInsfvhVIfOI6qHVyysXMNDnjO9Npvl7tlDPJFBVd4= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0/go.mod h1:KQsVNh4OjgjTG0G6EiNi1jVpnaeeKsKMRwbLN+f1+8M= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 h1:m0yTiGDLUvVYaTFbAvCkVYIYcvwKt3G7OLoN77NUs/8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0/go.mod h1:wBQbT4UekBfegL2nx0Xk1vBcnzyBPsIVm9hRG4fYcr4= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 h1:umZgi92IyxfXd/l4kaDhnKgY8rnN/cZcF1LKc6I8OQ8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0/go.mod h1:4lVs6obhSVRb1EW5FhOuBTyiQhtRtAnnva9vD3yRfq8= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc=
go.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ= go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw=
go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0= go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4=
go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo=
go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM= go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY=
go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y= go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ=
go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8= go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=

View file

@ -64,12 +64,12 @@ issues:
- path: _test\.go - path: _test\.go
linters: linters:
- gosec - gosec
# Ignoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand) # Igonoring gosec G404: Use of weak random number generator (math/rand instead of crypto/rand)
# as we commonly use it in tests and examples. # as we commonly use it in tests and examples.
- text: "G404:" - text: "G404:"
linters: linters:
- gosec - gosec
# Ignoring gosec G402: TLS MinVersion too low # Igonoring gosec G402: TLS MinVersion too low
# as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well. # as the https://pkg.go.dev/crypto/tls#Config handles MinVersion default well.
- text: "G402: TLS MinVersion too low." - text: "G402: TLS MinVersion too low."
linters: linters:

View file

@ -11,25 +11,6 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
<!-- Released section --> <!-- Released section -->
<!-- Don't change this section unless doing release --> <!-- Don't change this section unless doing release -->
## [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 ## [1.29.0/0.51.0/0.5.0] 2024-08-23
This release is the last to support [Go 1.21]. This release is the last to support [Go 1.21].
@ -1914,7 +1895,7 @@ with major version 0.
- Setting error status while recording error with Span from oteltest package. (#1729) - 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. - 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. Because of this `"go.opentelemetry.io/otel/trace".RemoteSpanContextFromContext` is removed as it is no longer needed.
Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContext` can be used to return the current Span. Instead, `"go.opentelemetry.io/otel/trace".SpanContextFromContex` 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) 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. - 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) This field is redundant to the information returned from the `Remote` method of the `SpanContext` held in the `ParentContext` field. (#1749)
@ -2488,7 +2469,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) - Prometheus exporter will not apply stale updates or forget inactive metrics. (#903)
- Add test for api.standard `HTTPClientAttributesFromHTTPRequest`. (#905) - 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) - Bump github.com/golangci/golangci-lint from 1.27.0 to 1.28.1 in /tools. (#901, #913)
- Update otel-collector example to use the v0.5.0 collector. (#915) - Update otel-colector 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 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 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. - The `grpctrace` instrumentation `rpc.service` attribute now contains the package name if one exists.
@ -3081,8 +3062,7 @@ It contains api and sdk for trace and meter.
- CircleCI build CI manifest files. - CircleCI build CI manifest files.
- CODEOWNERS file to track owners of this project. - CODEOWNERS file to track owners of this project.
[Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.30.0...HEAD [Unreleased]: https://github.com/open-telemetry/opentelemetry-go/compare/v1.29.0...HEAD
[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.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.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 [1.27.0/0.49.0/0.3.0]: https://github.com/open-telemetry/opentelemetry-go/releases/tag/v1.27.0

View file

@ -578,10 +578,7 @@ See also:
The tests should never leak goroutines. The tests should never leak goroutines.
Use the term `ConcurrentSafe` in the test name when it aims to verify the Use the term `ConcurrentSafe` in the test name when it aims to verify the
absence of race conditions. The top-level tests with this term will be run absence of race conditions.
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 ### Internal packages

View file

@ -145,14 +145,12 @@ build-tests/%:
# Tests # Tests
TEST_TARGETS := test-default test-bench test-short test-verbose test-race test-concurrent-safe TEST_TARGETS := test-default test-bench test-short test-verbose test-race
.PHONY: $(TEST_TARGETS) test .PHONY: $(TEST_TARGETS) test
test-default test-race: ARGS=-race test-default test-race: ARGS=-race
test-bench: ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=. test-bench: ARGS=-run=xxxxxMatchNothingxxxxx -test.benchtime=1ms -bench=.
test-short: ARGS=-short test-short: ARGS=-short
test-verbose: ARGS=-v -race test-verbose: ARGS=-v -race
test-concurrent-safe: ARGS=-run=ConcurrentSafe -count=100 -race
test-concurrent-safe: TIMEOUT=120
$(TEST_TARGETS): test $(TEST_TARGETS): test
test: $(OTEL_GO_MOD_DIRS:%=test/%) test: $(OTEL_GO_MOD_DIRS:%=test/%)
test/%: DIR=$* test/%: DIR=$*

View file

@ -51,18 +51,25 @@ Currently, this project supports the following environments.
|----------|------------|--------------| |----------|------------|--------------|
| Ubuntu | 1.23 | amd64 | | Ubuntu | 1.23 | amd64 |
| Ubuntu | 1.22 | amd64 | | Ubuntu | 1.22 | amd64 |
| Ubuntu | 1.21 | amd64 |
| Ubuntu | 1.23 | 386 | | Ubuntu | 1.23 | 386 |
| Ubuntu | 1.22 | 386 | | Ubuntu | 1.22 | 386 |
| Ubuntu | 1.21 | 386 |
| Linux | 1.23 | arm64 | | Linux | 1.23 | arm64 |
| Linux | 1.22 | arm64 | | Linux | 1.22 | arm64 |
| Linux | 1.21 | arm64 |
| macOS 13 | 1.23 | amd64 | | macOS 13 | 1.23 | amd64 |
| macOS 13 | 1.22 | amd64 | | macOS 13 | 1.22 | amd64 |
| macOS 13 | 1.21 | amd64 |
| macOS | 1.23 | arm64 | | macOS | 1.23 | arm64 |
| macOS | 1.22 | arm64 | | macOS | 1.22 | arm64 |
| macOS | 1.21 | arm64 |
| Windows | 1.23 | amd64 | | Windows | 1.23 | amd64 |
| Windows | 1.22 | amd64 | | Windows | 1.22 | amd64 |
| Windows | 1.21 | amd64 |
| Windows | 1.23 | 386 | | Windows | 1.23 | 386 |
| Windows | 1.22 | 386 | | Windows | 1.22 | 386 |
| Windows | 1.21 | 386 |
While this project should work for other systems, no compatibility guarantees While this project should work for other systems, no compatibility guarantees
are made for those systems currently. are made for those systems currently.

View file

@ -50,7 +50,7 @@ type Property struct {
// component boundaries may impose their own restrictions on Property key. // component boundaries may impose their own restrictions on Property key.
// For example, the W3C Baggage specification restricts the Property keys to strings that // For example, the W3C Baggage specification restricts the Property keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6. // satisfy the token definition from RFC7230, Section 3.2.6.
// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key. // For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key.
func NewKeyProperty(key string) (Property, error) { func NewKeyProperty(key string) (Property, error) {
if !validateBaggageName(key) { if !validateBaggageName(key) {
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, 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. // component boundaries may impose their own restrictions on Property key.
// For example, the W3C Baggage specification restricts the Property keys to strings that // For example, the W3C Baggage specification restricts the Property keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6. // satisfy the token definition from RFC7230, Section 3.2.6.
// For maximum compatibility, alphanumeric value are strongly recommended to be used as Property key. // For maximum compatibility, alpha-numeric value are strongly recommended to be used as Property key.
func NewKeyValuePropertyRaw(key, value string) (Property, error) { func NewKeyValuePropertyRaw(key, value string) (Property, error) {
if !validateBaggageName(key) { if !validateBaggageName(key) {
return newInvalidProperty(), fmt.Errorf("%w: %q", errInvalidKey, 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. // component boundaries may impose their own restrictions on baggage key.
// For example, the W3C Baggage specification restricts the baggage keys to strings that // For example, the W3C Baggage specification restricts the baggage keys to strings that
// satisfy the token definition from RFC7230, Section 3.2.6. // satisfy the token definition from RFC7230, Section 3.2.6.
// For maximum compatibility, alphanumeric value are strongly recommended to be used as baggage key. // For maximum compatibility, alpha-numeric value are strongly recommended to be used as baggage key.
func NewMemberRaw(key, value string, props ...Property) (Member, error) { func NewMemberRaw(key, value string, props ...Property) (Member, error) {
m := Member{ m := Member{
key: key, key: key,

View file

@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
if cfg.ServiceConfig != "" { if cfg.ServiceConfig != "" {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig)) cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
} }
// Prioritize GRPCCredentials over Insecure (passing both is an error). // Priroritize GRPCCredentials over Insecure (passing both is an error).
if cfg.Traces.GRPCCredentials != nil { if cfg.Traces.GRPCCredentials != nil {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials)) cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
} else if cfg.Traces.Insecure { } else if cfg.Traces.Insecure {

View file

@ -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 must contain a scheme ("http" or "https") and host.
The value may additionally contain a port and a path. The value may additionally contain a port and a path.
The value should not contain a query string or fragment. The value should not contain a query string or fragment.
The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WithInsecure], and [WithURLPath] options. The configuration can be overridden by [WithEndpoint], [WithEndpointURL], [WitnInsecure], and [WithURLPath] options.
OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS (default: none) - OTEL_EXPORTER_OTLP_HEADERS, OTEL_EXPORTER_OTLP_TRACES_HEADERS (default: none) -
key-value pairs used as headers associated with HTTP requests. key-value pairs used as headers associated with HTTP requests.

View file

@ -125,7 +125,7 @@ func NewGRPCConfig(opts ...GRPCOption) Config {
if cfg.ServiceConfig != "" { if cfg.ServiceConfig != "" {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig)) cfg.DialOptions = append(cfg.DialOptions, grpc.WithDefaultServiceConfig(cfg.ServiceConfig))
} }
// Prioritize GRPCCredentials over Insecure (passing both is an error). // Priroritize GRPCCredentials over Insecure (passing both is an error).
if cfg.Traces.GRPCCredentials != nil { if cfg.Traces.GRPCCredentials != nil {
cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials)) cfg.DialOptions = append(cfg.DialOptions, grpc.WithTransportCredentials(cfg.Traces.GRPCCredentials))
} else if cfg.Traces.Insecure { } else if cfg.Traces.Insecure {

View file

@ -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. // Version is the current release version of the OpenTelemetry OTLP trace exporter in use.
func Version() string { func Version() string {
return "1.30.0" return "1.29.0"
} }

View file

@ -7,7 +7,6 @@ import (
"strings" "strings"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/model"
"go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/metric"
@ -132,10 +131,7 @@ func WithoutScopeInfo() Option {
// have special behavior based on their name. // have special behavior based on their name.
func WithNamespace(ns string) Option { func WithNamespace(ns string) Option {
return optionFunc(func(cfg config) config { return optionFunc(func(cfg config) config {
if model.NameValidationScheme != model.UTF8Validation { ns = sanitizeName(ns)
// Only sanitize if prometheus does not support UTF-8.
ns = model.EscapeName(ns, model.NameEscapingScheme)
}
if !strings.HasSuffix(ns, "_") { if !strings.HasSuffix(ns, "_") {
// namespace and metric names should be separated with an underscore, // namespace and metric names should be separated with an underscore,
// adds a trailing underscore if there is not one already. // adds a trailing underscore if there is not one already.

View file

@ -11,10 +11,11 @@ import (
"slices" "slices"
"strings" "strings"
"sync" "sync"
"unicode"
"unicode/utf8"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
dto "github.com/prometheus/client_model/go" dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/model"
"google.golang.org/protobuf/proto" "google.golang.org/protobuf/proto"
"go.opentelemetry.io/otel" "go.opentelemetry.io/otel"
@ -297,26 +298,14 @@ func addGaugeMetric[N int64 | float64](ch chan<- prometheus.Metric, gauge metric
} }
// getAttrs parses the attribute.Set to two lists of matching Prometheus-style // getAttrs parses the attribute.Set to two lists of matching Prometheus-style
// keys and values. // 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) { func getAttrs(attrs attribute.Set, ks, vs [2]string, resourceKV keyVals) ([]string, []string) {
keys := make([]string, 0, attrs.Len())
values := make([]string, 0, attrs.Len())
itr := attrs.Iter()
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) keysMap := make(map[string][]string)
itr := attrs.Iter()
for itr.Next() { for itr.Next() {
kv := itr.Attribute() kv := itr.Attribute()
key := model.EscapeName(string(kv.Key), model.NameEscapingScheme) key := strings.Map(sanitizeRune, string(kv.Key))
if _, ok := keysMap[key]; !ok { if _, ok := keysMap[key]; !ok {
keysMap[key] = []string{kv.Value.Emit()} keysMap[key] = []string{kv.Value.Emit()}
} else { } else {
@ -324,12 +313,14 @@ func getAttrs(attrs attribute.Set, ks, vs [2]string, resourceKV keyVals) ([]stri
keysMap[key] = append(keysMap[key], kv.Value.Emit()) keysMap[key] = append(keysMap[key], kv.Value.Emit())
} }
} }
keys := make([]string, 0, attrs.Len())
values := make([]string, 0, attrs.Len())
for key, vals := range keysMap { for key, vals := range keysMap {
keys = append(keys, key) keys = append(keys, key)
slices.Sort(vals) slices.Sort(vals)
values = append(values, strings.Join(vals, ";")) values = append(values, strings.Join(vals, ";"))
} }
}
if ks[0] != "" { if ks[0] != "" {
keys = append(keys, ks[:]...) keys = append(keys, ks[:]...)
@ -356,6 +347,13 @@ func createScopeInfoMetric(scope instrumentation.Scope) (prometheus.Metric, erro
return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), scope.Name, scope.Version) return prometheus.NewConstMetric(desc, prometheus.GaugeValue, float64(1), scope.Name, scope.Version)
} }
func sanitizeRune(r rune) rune {
if unicode.IsLetter(r) || unicode.IsDigit(r) || r == ':' || r == '_' {
return r
}
return '_'
}
var unitSuffixes = map[string]string{ var unitSuffixes = map[string]string{
// Time // Time
"d": "_days", "d": "_days",
@ -394,11 +392,7 @@ var unitSuffixes = map[string]string{
// getName returns the sanitized name, prefixed with the namespace and suffixed with unit. // getName returns the sanitized name, prefixed with the namespace and suffixed with unit.
func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string { func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
name := m.Name name := sanitizeName(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 addCounterSuffix := !c.withoutCounterSuffixes && *typ == dto.MetricType_COUNTER
if addCounterSuffix { if addCounterSuffix {
// Remove the _total suffix here, as we will re-add the total suffix // Remove the _total suffix here, as we will re-add the total suffix
@ -417,6 +411,59 @@ func (c *collector) getName(m metricdata.Metrics, typ *dto.MetricType) string {
return name 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 { func (c *collector) metricType(m metricdata.Metrics) *dto.MetricType {
switch v := m.Data.(type) { switch v := m.Data.(type) {
case metricdata.Histogram[int64], metricdata.Histogram[float64]: case metricdata.Histogram[int64], metricdata.Histogram[float64]:

View file

@ -5,8 +5,8 @@ package global // import "go.opentelemetry.io/otel/internal/global"
import ( import (
"container/list" "container/list"
"reflect"
"sync" "sync"
"sync/atomic"
"go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/metric"
"go.opentelemetry.io/otel/metric/embedded" "go.opentelemetry.io/otel/metric/embedded"
@ -76,7 +76,7 @@ func (p *meterProvider) Meter(name string, opts ...metric.MeterOption) metric.Me
return val return val
} }
t := &meter{name: name, opts: opts, instruments: make(map[instID]delegatedInstrument)} t := &meter{name: name, opts: opts}
p.meters[key] = t p.meters[key] = t
return t return t
} }
@ -92,29 +92,17 @@ type meter struct {
opts []metric.MeterOption opts []metric.MeterOption
mtx sync.Mutex mtx sync.Mutex
instruments map[instID]delegatedInstrument instruments []delegatedInstrument
registry list.List registry list.List
delegate metric.Meter delegate atomic.Value // metric.Meter
} }
type delegatedInstrument interface { type delegatedInstrument interface {
setDelegate(metric.Meter) 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 // setDelegate configures m to delegate all Meter functionality to Meters
// created by provider. // created by provider.
// //
@ -122,12 +110,12 @@ type instID struct {
// //
// It is guaranteed by the caller that this happens only once. // It is guaranteed by the caller that this happens only once.
func (m *meter) setDelegate(provider metric.MeterProvider) { func (m *meter) setDelegate(provider metric.MeterProvider) {
meter := provider.Meter(m.name, m.opts...)
m.delegate.Store(meter)
m.mtx.Lock() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
meter := provider.Meter(m.name, m.opts...)
m.delegate = meter
for _, inst := range m.instruments { for _, inst := range m.instruments {
inst.setDelegate(meter) inst.setDelegate(meter)
} }
@ -145,295 +133,169 @@ func (m *meter) setDelegate(provider metric.MeterProvider) {
} }
func (m *meter) Int64Counter(name string, options ...metric.Int64CounterOption) (metric.Int64Counter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64Counter(name, options...)
}
i := &siCounter{name: name, opts: options} i := &siCounter{name: name, opts: options}
cfg := metric.NewInt64CounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64UpDownCounter(name string, options ...metric.Int64UpDownCounterOption) (metric.Int64UpDownCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64UpDownCounter(name, options...)
}
i := &siUpDownCounter{name: name, opts: options} i := &siUpDownCounter{name: name, opts: options}
cfg := metric.NewInt64UpDownCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64Histogram(name string, options ...metric.Int64HistogramOption) (metric.Int64Histogram, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64Histogram(name, options...)
}
i := &siHistogram{name: name, opts: options} i := &siHistogram{name: name, opts: options}
cfg := metric.NewInt64HistogramConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64Gauge(name string, options ...metric.Int64GaugeOption) (metric.Int64Gauge, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64Gauge(name, options...)
}
i := &siGauge{name: name, opts: options} i := &siGauge{name: name, opts: options}
cfg := metric.NewInt64GaugeConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64ObservableCounter(name string, options ...metric.Int64ObservableCounterOption) (metric.Int64ObservableCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64ObservableCounter(name, options...)
}
i := &aiCounter{name: name, opts: options} i := &aiCounter{name: name, opts: options}
cfg := metric.NewInt64ObservableCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64ObservableUpDownCounter(name string, options ...metric.Int64ObservableUpDownCounterOption) (metric.Int64ObservableUpDownCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64ObservableUpDownCounter(name, options...)
}
i := &aiUpDownCounter{name: name, opts: options} i := &aiUpDownCounter{name: name, opts: options}
cfg := metric.NewInt64ObservableUpDownCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Int64ObservableGauge(name string, options ...metric.Int64ObservableGaugeOption) (metric.Int64ObservableGauge, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Int64ObservableGauge(name, options...)
}
i := &aiGauge{name: name, opts: options} i := &aiGauge{name: name, opts: options}
cfg := metric.NewInt64ObservableGaugeConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64Counter(name string, options ...metric.Float64CounterOption) (metric.Float64Counter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64Counter(name, options...)
}
i := &sfCounter{name: name, opts: options} i := &sfCounter{name: name, opts: options}
cfg := metric.NewFloat64CounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64UpDownCounter(name string, options ...metric.Float64UpDownCounterOption) (metric.Float64UpDownCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64UpDownCounter(name, options...)
}
i := &sfUpDownCounter{name: name, opts: options} i := &sfUpDownCounter{name: name, opts: options}
cfg := metric.NewFloat64UpDownCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64Histogram(name string, options ...metric.Float64HistogramOption) (metric.Float64Histogram, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64Histogram(name, options...)
}
i := &sfHistogram{name: name, opts: options} i := &sfHistogram{name: name, opts: options}
cfg := metric.NewFloat64HistogramConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64Gauge(name string, options ...metric.Float64GaugeOption) (metric.Float64Gauge, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64Gauge(name, options...)
}
i := &sfGauge{name: name, opts: options} i := &sfGauge{name: name, opts: options}
cfg := metric.NewFloat64GaugeConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64ObservableCounter(name string, options ...metric.Float64ObservableCounterOption) (metric.Float64ObservableCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64ObservableCounter(name, options...)
}
i := &afCounter{name: name, opts: options} i := &afCounter{name: name, opts: options}
cfg := metric.NewFloat64ObservableCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64ObservableUpDownCounter(name string, options ...metric.Float64ObservableUpDownCounterOption) (metric.Float64ObservableUpDownCounter, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64ObservableUpDownCounter(name, options...)
}
i := &afUpDownCounter{name: name, opts: options} i := &afUpDownCounter{name: name, opts: options}
cfg := metric.NewFloat64ObservableUpDownCounterConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
func (m *meter) Float64ObservableGauge(name string, options ...metric.Float64ObservableGaugeOption) (metric.Float64ObservableGauge, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
return m.delegate.Float64ObservableGauge(name, options...)
}
i := &afGauge{name: name, opts: options} i := &afGauge{name: name, opts: options}
cfg := metric.NewFloat64ObservableGaugeConfig(options...) m.instruments = append(m.instruments, i)
id := instID{
name: name,
kind: reflect.TypeOf(i),
description: cfg.Description(),
unit: cfg.Unit(),
}
m.instruments[id] = i
return i, nil return i, nil
} }
// RegisterCallback captures the function that will be called during Collect. // RegisterCallback captures the function that will be called during Collect.
func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable) (metric.Registration, error) { 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() m.mtx.Lock()
defer m.mtx.Unlock() defer m.mtx.Unlock()
if m.delegate != nil {
insts = unwrapInstruments(insts)
return m.delegate.RegisterCallback(f, insts...)
}
reg := &registration{instruments: insts, function: f} reg := &registration{instruments: insts, function: f}
e := m.registry.PushBack(reg) e := m.registry.PushBack(reg)
reg.unreg = func() error { reg.unreg = func() error {

View file

@ -213,7 +213,7 @@ type Float64Observer interface {
} }
// Float64Callback is a function registered with a Meter that makes // Float64Callback is a function registered with a Meter that makes
// observations for a Float64Observable instrument it is registered with. // observations for a Float64Observerable instrument it is registered with.
// Calls to the Float64Observer record measurement values for the // Calls to the Float64Observer record measurement values for the
// Float64Observable. // Float64Observable.
// //

View file

@ -212,7 +212,7 @@ type Int64Observer interface {
} }
// Int64Callback is a function registered with a Meter that makes observations // Int64Callback is a function registered with a Meter that makes observations
// for an Int64Observable instrument it is registered with. Calls to the // for an Int64Observerable instrument it is registered with. Calls to the
// Int64Observer record measurement values for the Int64Observable. // Int64Observer record measurement values for the Int64Observable.
// //
// The function needs to complete in a finite amount of time and the deadline // The function needs to complete in a finite amount of time and the deadline

View file

@ -19,10 +19,6 @@
"matchManagers": ["gomod"], "matchManagers": ["gomod"],
"matchDepTypes": ["indirect"], "matchDepTypes": ["indirect"],
"enabled": false "enabled": false
},
{
"matchPackageNames": ["google.golang.org/genproto/googleapis/**"],
"groupName": "googleapis"
} }
] ]
} }

View file

@ -8,7 +8,6 @@ import (
"fmt" "fmt"
"sync" "sync"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/sdk/resource" "go.opentelemetry.io/otel/sdk/resource"
) )
@ -104,11 +103,7 @@ func (o optionFunc) apply(conf config) config {
// go.opentelemetry.io/otel/sdk/resource package will be used. // go.opentelemetry.io/otel/sdk/resource package will be used.
func WithResource(res *resource.Resource) Option { func WithResource(res *resource.Resource) Option {
return optionFunc(func(conf config) config { return optionFunc(func(conf config) config {
var err error conf.res = res
conf.res, err = resource.Merge(resource.Environment(), res)
if err != nil {
otel.Handle(err)
}
return conf return conf
}) })
} }

View file

@ -234,8 +234,8 @@ func (i *float64Inst) aggregate(ctx context.Context, val float64, s attribute.Se
} }
} }
// observableID is a comparable unique identifier of an observable. // observablID is a comparable unique identifier of an observable.
type observableID[N int64 | float64] struct { type observablID[N int64 | float64] struct {
name string name string
description string description string
kind InstrumentKind kind InstrumentKind
@ -287,7 +287,7 @@ func newInt64Observable(m *meter, kind InstrumentKind, name, desc, u string) int
type observable[N int64 | float64] struct { type observable[N int64 | float64] struct {
metric.Observable metric.Observable
observableID[N] observablID[N]
meter *meter meter *meter
measures measures[N] measures measures[N]
@ -296,7 +296,7 @@ type observable[N int64 | float64] struct {
func newObservable[N int64 | float64](m *meter, kind InstrumentKind, name, desc, u string) *observable[N] { func newObservable[N int64 | float64](m *meter, kind InstrumentKind, name, desc, u string) *observable[N] {
return &observable[N]{ return &observable[N]{
observableID: observableID[N]{ observablID: observablID[N]{
name: name, name: name,
description: desc, description: desc,
kind: kind, kind: kind,

View file

@ -142,7 +142,7 @@ func (s *sum[N]) cumulative(dest *metricdata.Aggregation) int {
} }
// newPrecomputedSum returns an aggregator that summarizes a set of // newPrecomputedSum returns an aggregator that summarizes a set of
// observations as their arithmetic sum. Each sum is scoped by attributes and // observatrions as their arithmetic sum. Each sum is scoped by attributes and
// the aggregation cycle the measurements were made in. // 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() exemplar.FilteredReservoir[N]) *precomputedSum[N] {
return &precomputedSum[N]{ return &precomputedSum[N]{
@ -152,7 +152,7 @@ func newPrecomputedSum[N int64 | float64](monotonic bool, limit int, r func() ex
} }
} }
// precomputedSum summarizes a set of observations as their arithmetic sum. // precomputedSum summarizes a set of observatrions as their arithmetic sum.
type precomputedSum[N int64 | float64] struct { type precomputedSum[N int64 | float64] struct {
*valueMap[N] *valueMap[N]

View file

@ -41,7 +41,7 @@ func NewFilteredReservoir[N int64 | float64](f Filter, r Reservoir) FilteredRese
func (f *filteredReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) { func (f *filteredReservoir[N]) Offer(ctx context.Context, val N, attr []attribute.KeyValue) {
if f.filter(ctx) { if f.filter(ctx) {
// only record the current time if we are sampling this measurement. // only record the current time if we are sampling this measurment.
f.reservoir.Offer(ctx, time.Now(), NewValue(val), attr) f.reservoir.Offer(ctx, time.Now(), NewValue(val), attr)
} }
} }

View file

@ -19,7 +19,7 @@ var (
// Do not use crypto/rand. There is no reason for the decrease in performance // Do not use crypto/rand. There is no reason for the decrease in performance
// given this is not a security sensitive decision. // given this is not a security sensitive decision.
rng = rand.New(rand.NewSource(time.Now().UnixNano())) rng = rand.New(rand.NewSource(time.Now().UnixNano()))
// Ensure concurrent safe access to rng and its underlying source. // Ensure concurrent safe accecess to rng and its underlying source.
rngMu sync.Mutex rngMu sync.Mutex
) )

View file

@ -459,7 +459,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
} }
continue continue
} }
reg.registerInt64(o.observableID) reg.registerInt64(o.observablID)
case float64Observable: case float64Observable:
if err := o.registerable(m); err != nil { if err := o.registerable(m); err != nil {
if !errors.Is(err, errEmptyAgg) { if !errors.Is(err, errEmptyAgg) {
@ -467,7 +467,7 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
} }
continue continue
} }
reg.registerFloat64(o.observableID) reg.registerFloat64(o.observablID)
default: default:
// Instrument external to the SDK. // Instrument external to the SDK.
return nil, fmt.Errorf("invalid observable: from different implementation") return nil, fmt.Errorf("invalid observable: from different implementation")
@ -488,14 +488,14 @@ func (m *meter) RegisterCallback(f metric.Callback, insts ...metric.Observable)
type observer struct { type observer struct {
embedded.Observer embedded.Observer
float64 map[observableID[float64]]struct{} float64 map[observablID[float64]]struct{}
int64 map[observableID[int64]]struct{} int64 map[observablID[int64]]struct{}
} }
func newObserver() observer { func newObserver() observer {
return observer{ return observer{
float64: make(map[observableID[float64]]struct{}), float64: make(map[observablID[float64]]struct{}),
int64: make(map[observableID[int64]]struct{}), int64: make(map[observablID[int64]]struct{}),
} }
} }
@ -503,11 +503,11 @@ func (r observer) len() int {
return len(r.float64) + len(r.int64) return len(r.float64) + len(r.int64)
} }
func (r observer) registerFloat64(id observableID[float64]) { func (r observer) registerFloat64(id observablID[float64]) {
r.float64[id] = struct{}{} r.float64[id] = struct{}{}
} }
func (r observer) registerInt64(id observableID[int64]) { func (r observer) registerInt64(id observablID[int64]) {
r.int64[id] = struct{}{} r.int64[id] = struct{}{}
} }
@ -536,7 +536,7 @@ func (r observer) ObserveFloat64(o metric.Float64Observable, v float64, opts ...
return return
} }
if _, registered := r.float64[oImpl.observableID]; !registered { if _, registered := r.float64[oImpl.observablID]; !registered {
if !oImpl.dropAggregation { if !oImpl.dropAggregation {
global.Error(errUnregObserver, "failed to record", global.Error(errUnregObserver, "failed to record",
"name", oImpl.name, "name", oImpl.name,
@ -571,7 +571,7 @@ func (r observer) ObserveInt64(o metric.Int64Observable, v int64, opts ...metric
return return
} }
if _, registered := r.int64[oImpl.observableID]; !registered { if _, registered := r.int64[oImpl.observablID]; !registered {
if !oImpl.dropAggregation { if !oImpl.dropAggregation {
global.Error(errUnregObserver, "failed to record", global.Error(errUnregObserver, "failed to record",
"name", oImpl.name, "name", oImpl.name,

View file

@ -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. // version is the current release version of the metric SDK in use.
func version() string { func version() string {
return "1.30.0" return "1.29.0"
} }

View file

@ -10,16 +10,17 @@ import (
"golang.org/x/sys/windows/registry" "golang.org/x/sys/windows/registry"
) )
// implements hostIDReader. // implements hostIDReader
type hostIDReaderWindows struct{} type hostIDReaderWindows struct{}
// read reads MachineGuid from the Windows registry key: // read reads MachineGuid from the windows registry key:
// SOFTWARE\Microsoft\Cryptography. // SOFTWARE\Microsoft\Cryptography
func (*hostIDReaderWindows) read() (string, error) { func (*hostIDReaderWindows) read() (string, error) {
k, err := registry.OpenKey( k, err := registry.OpenKey(
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`, registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Cryptography`,
registry.QUERY_VALUE|registry.WOW64_64KEY, registry.QUERY_VALUE|registry.WOW64_64KEY,
) )
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -17,6 +17,7 @@ import (
func platformOSDescription() (string, error) { func platformOSDescription() (string, error) {
k, err := registry.OpenKey( k, err := registry.OpenKey(
registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE)
if err != nil { if err != nil {
return "", err return "", err
} }

View file

@ -5,5 +5,5 @@ package sdk // import "go.opentelemetry.io/otel/sdk"
// Version is the current release version of the OpenTelemetry SDK in use. // Version is the current release version of the OpenTelemetry SDK in use.
func Version() string { func Version() string {
return "1.30.0" return "1.29.0"
} }

View file

@ -22,7 +22,7 @@ func ContextWithSpanContext(parent context.Context, sc SpanContext) context.Cont
return ContextWithSpan(parent, nonRecordingSpan{sc: sc}) return ContextWithSpan(parent, nonRecordingSpan{sc: sc})
} }
// ContextWithRemoteSpanContext returns a copy of parent with rsc set explicitly // ContextWithRemoteSpanContext returns a copy of parent with rsc set explicly
// as a remote SpanContext and as the current Span. The Span implementation // 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 // that wraps rsc is non-recording and performs no operations other than to
// return rsc as the SpanContext from the SpanContext method. // return rsc as the SpanContext from the SpanContext method.

View file

@ -96,7 +96,7 @@ can embed the API interface directly.
This option is not recommended. It will lead to publishing packages that This option is not recommended. It will lead to publishing packages that
contain runtime panics when users update to newer versions of contain runtime panics when users update to newer versions of
[go.opentelemetry.io/otel/trace], which may be done with a transitive [go.opentelemetry.io/otel/trace], which may be done with a trasitive
dependency. dependency.
Finally, an author can embed another implementation in theirs. The embedded Finally, an author can embed another implementation in theirs. The embedded

View file

@ -5,5 +5,5 @@ package otel // import "go.opentelemetry.io/otel"
// Version is the current release version of OpenTelemetry in use. // Version is the current release version of OpenTelemetry in use.
func Version() string { func Version() string {
return "1.30.0" return "1.29.0"
} }

View file

@ -3,7 +3,7 @@
module-sets: module-sets:
stable-v1: stable-v1:
version: v1.30.0 version: v1.29.0
modules: modules:
- go.opentelemetry.io/otel - go.opentelemetry.io/otel
- go.opentelemetry.io/otel/bridge/opencensus - go.opentelemetry.io/otel/bridge/opencensus
@ -29,12 +29,12 @@ module-sets:
- go.opentelemetry.io/otel/sdk/metric - go.opentelemetry.io/otel/sdk/metric
- go.opentelemetry.io/otel/trace - go.opentelemetry.io/otel/trace
experimental-metrics: experimental-metrics:
version: v0.52.0 version: v0.51.0
modules: modules:
- go.opentelemetry.io/otel/example/prometheus - go.opentelemetry.io/otel/example/prometheus
- go.opentelemetry.io/otel/exporters/prometheus - go.opentelemetry.io/otel/exporters/prometheus
experimental-logs: experimental-logs:
version: v0.6.0 version: v0.5.0
modules: modules:
- go.opentelemetry.io/otel/log - go.opentelemetry.io/otel/log
- go.opentelemetry.io/otel/sdk/log - go.opentelemetry.io/otel/sdk/log
@ -42,7 +42,7 @@ module-sets:
- go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp
- go.opentelemetry.io/otel/exporters/stdout/stdoutlog - go.opentelemetry.io/otel/exporters/stdout/stdoutlog
experimental-schema: experimental-schema:
version: v0.0.9 version: v0.0.8
modules: modules:
- go.opentelemetry.io/otel/schema - go.opentelemetry.io/otel/schema
excluded-modules: excluded-modules:

36
vendor/modules.txt vendored
View file

@ -979,8 +979,8 @@ go.mongodb.org/mongo-driver/bson/bsonrw
go.mongodb.org/mongo-driver/bson/bsontype go.mongodb.org/mongo-driver/bson/bsontype
go.mongodb.org/mongo-driver/bson/primitive go.mongodb.org/mongo-driver/bson/primitive
go.mongodb.org/mongo-driver/x/bsonx/bsoncore go.mongodb.org/mongo-driver/x/bsonx/bsoncore
# go.opentelemetry.io/otel v1.30.0 # go.opentelemetry.io/otel v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel go.opentelemetry.io/otel
go.opentelemetry.io/otel/attribute go.opentelemetry.io/otel/attribute
go.opentelemetry.io/otel/baggage go.opentelemetry.io/otel/baggage
@ -999,50 +999,50 @@ go.opentelemetry.io/otel/semconv/v1.20.0/httpconv
go.opentelemetry.io/otel/semconv/v1.24.0 go.opentelemetry.io/otel/semconv/v1.24.0
go.opentelemetry.io/otel/semconv/v1.26.0 go.opentelemetry.io/otel/semconv/v1.26.0
go.opentelemetry.io/otel/semconv/v1.7.0 go.opentelemetry.io/otel/semconv/v1.7.0
# go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.30.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace go.opentelemetry.io/otel/exporters/otlp/otlptrace
go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform go.opentelemetry.io/otel/exporters/otlp/otlptrace/internal/tracetransform
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.30.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc/internal/retry
# go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.30.0 # go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/envconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/otlpconfig
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp/internal/retry
# go.opentelemetry.io/otel/exporters/prometheus v0.52.0 # go.opentelemetry.io/otel/exporters/prometheus v0.51.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/exporters/prometheus go.opentelemetry.io/otel/exporters/prometheus
# go.opentelemetry.io/otel/metric v1.30.0 # go.opentelemetry.io/otel/metric v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/metric go.opentelemetry.io/otel/metric
go.opentelemetry.io/otel/metric/embedded go.opentelemetry.io/otel/metric/embedded
go.opentelemetry.io/otel/metric/noop go.opentelemetry.io/otel/metric/noop
# go.opentelemetry.io/otel/sdk v1.30.0 # go.opentelemetry.io/otel/sdk v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/sdk go.opentelemetry.io/otel/sdk
go.opentelemetry.io/otel/sdk/instrumentation go.opentelemetry.io/otel/sdk/instrumentation
go.opentelemetry.io/otel/sdk/internal/env go.opentelemetry.io/otel/sdk/internal/env
go.opentelemetry.io/otel/sdk/internal/x go.opentelemetry.io/otel/sdk/internal/x
go.opentelemetry.io/otel/sdk/resource go.opentelemetry.io/otel/sdk/resource
go.opentelemetry.io/otel/sdk/trace go.opentelemetry.io/otel/sdk/trace
# go.opentelemetry.io/otel/sdk/metric v1.30.0 # go.opentelemetry.io/otel/sdk/metric v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/sdk/metric go.opentelemetry.io/otel/sdk/metric
go.opentelemetry.io/otel/sdk/metric/internal go.opentelemetry.io/otel/sdk/metric/internal
go.opentelemetry.io/otel/sdk/metric/internal/aggregate go.opentelemetry.io/otel/sdk/metric/internal/aggregate
go.opentelemetry.io/otel/sdk/metric/internal/exemplar go.opentelemetry.io/otel/sdk/metric/internal/exemplar
go.opentelemetry.io/otel/sdk/metric/internal/x go.opentelemetry.io/otel/sdk/metric/internal/x
go.opentelemetry.io/otel/sdk/metric/metricdata go.opentelemetry.io/otel/sdk/metric/metricdata
# go.opentelemetry.io/otel/trace v1.30.0 # go.opentelemetry.io/otel/trace v1.29.0
## explicit; go 1.22 ## explicit; go 1.21
go.opentelemetry.io/otel/trace go.opentelemetry.io/otel/trace
go.opentelemetry.io/otel/trace/embedded go.opentelemetry.io/otel/trace/embedded
go.opentelemetry.io/otel/trace/noop go.opentelemetry.io/otel/trace/noop