Skip to content

add self observability for stdout exporter#8263

Merged
pellared merged 22 commits into
open-telemetry:mainfrom
yumosx:feat/yumosx/inst-stdlog
May 26, 2026
Merged

add self observability for stdout exporter#8263
pellared merged 22 commits into
open-telemetry:mainfrom
yumosx:feat/yumosx/inst-stdlog

Conversation

@yumosx

@yumosx yumosx commented Apr 26, 2026

Copy link
Copy Markdown
Member

ref: #7020

goos: darwin
goarch: arm64
pkg: go.opentelemetry.io/otel/exporters/stdout/stdoutlog
                                      │ bench_observability_disabled_6x.txt │ bench_observability_upload_6x.txt │
                                      │               sec/op                │           sec/op            vs base   │
ExporterObservability/Disabled-8                                3.968µ ± 1%
ExporterObservability/UploadSuccess-8                                                        4.236µ ± 2%
geomean                                                         3.967µ                       4.235µ       ? ¹ ²
¹ benchmark set differs from baseline; geomeans may not be comparable
² ratios must be >0 to compute geomean

                                      │ bench_observability_disabled_6x.txt │ bench_observability_upload_6x.txt │
                                      │                B/op                 │            B/op             vs base   │
ExporterObservability/Disabled-8                               1.419Ki ± 0%
ExporterObservability/UploadSuccess-8                                                       1.420Ki ± 0%
geomean                                                        1.419Ki                      1.420Ki       ? ¹ ²
¹ benchmark set differs from baseline; geomeans may not be comparable
² ratios must be >0 to compute geomean

                                      │ bench_observability_disabled_6x.txt │ bench_observability_upload_6x.txt │
                                      │              allocs/op              │         allocs/op           vs base   │
ExporterObservability/Disabled-8                                 33.00 ± 0%
ExporterObservability/UploadSuccess-8                                                         33.00 ± 0%
geomean                                                          33.00                        33.00       ? ¹ ²
¹ benchmark set differs from baseline; geomeans may not be comparable
² ratios must be >0 to compute geomean

@codecov

codecov Bot commented Apr 26, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.55556% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.9%. Comparing base (714a196) to head (aabf803).

Files with missing lines Patch % Lines
...tdout/stdoutlog/internal/observ/instrumentation.go 92.8% 1 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff          @@
##            main   #8263   +/-   ##
=====================================
  Coverage   82.9%   82.9%           
=====================================
  Files        314     315    +1     
  Lines      25093   25109   +16     
=====================================
+ Hits       20809   20826   +17     
  Misses      3910    3910           
+ Partials     374     373    -1     
Files with missing lines Coverage Δ
exporters/stdout/stdoutlog/exporter.go 100.0% <100.0%> (+8.0%) ⬆️
...rters/stdout/stdoutlog/internal/counter/counter.go 100.0% <100.0%> (ø)
...tdout/stdoutlog/internal/observ/instrumentation.go 98.0% <92.8%> (+<0.1%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds experimental self-observability (SDK exporter metrics) to the stdoutlog exporter, gated behind the OTEL_GO_X_OBSERVABILITY feature flag, following the project’s exporter-observability direction from issue #7020.

Changes:

  • Generate and add an internal counter package to provide unique exporter IDs (and allow deterministic resets in tests).
  • Wire stdoutlog.Exporter to initialize observability instrumentation and record inflight/exported/duration metrics during Export.
  • Add observability-focused tests and a benchmark for enabled vs disabled overhead.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
exporters/stdout/stdoutlog/internal/gen.go Adds go:generate rules to generate the internal counter package.
exporters/stdout/stdoutlog/internal/counter/counter.go Generated atomic counter used to assign unique exporter IDs.
exporters/stdout/stdoutlog/internal/counter/counter_test.go Generated tests validating counter behavior and concurrency-safety.
exporters/stdout/stdoutlog/exporter.go Initializes instrumentation and records observability metrics around Export.
exporters/stdout/stdoutlog/exporter_test.go Adds tests/benchmarks validating emitted metrics when observability is enabled.

Comment thread exporters/stdout/stdoutlog/exporter_test.go Outdated
Comment thread exporters/stdout/stdoutlog/exporter_test.go
Comment thread exporters/stdout/stdoutlog/exporter_test.go
@yumosx

yumosx commented Apr 27, 2026

Copy link
Copy Markdown
Member Author

I missed the changelog. I will add it later

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.

Comment thread exporters/stdout/stdoutlog/exporter_test.go
Comment thread exporters/stdout/stdoutlog/exporter.go
Comment thread exporters/stdout/stdoutlog/exporter_test.go

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread exporters/stdout/stdoutlog/exporter_test.go
Comment thread exporters/stdout/stdoutlog/internal/observ/instrumentation.go
Comment thread exporters/stdout/stdoutlog/internal/observ/instrumentation.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Comment thread exporters/stdout/stdoutlog/internal/observ/instrumentation.go
Comment thread exporters/stdout/stdoutlog/internal/observ/instrumentation.go Outdated
Comment thread exporters/stdout/stdoutlog/exporter.go Outdated
yumosx and others added 5 commits May 6, 2026 11:33
…is true

Previously, the error.type attribute was only added when exportedLogsEnable
was true. If opDurationEnable was true but exportedLogsEnable was false,
the error attribute was never recorded.

Now the condition is expanded to (exportedLogsEnable || opDurationEnable),
while still only calling e.inst.exported.Add when exportedLogsEnable is true.
Previously, stdoutlog.New returned (nil, err) when self-observability
setup failed, making the exporter unusable. This differed from
stdouttrace.New and stdoutmetric.New, which return the exporter
alongside the error, allowing core export functionality to continue
even when experimental observability fails.

Change stdoutlog.New to return the exporter with inst=nil and the
instrumentation error separately, matching the behavior of the other
stdout exporters. The Export method already guards against nil inst,
so this is safe.

Fixes the inconsistency where enabling observability could prevent
stdout log export from working.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@yumosx

yumosx commented May 8, 2026

Copy link
Copy Markdown
Member Author
Vulnerability #1: GO-2026-4971
    Panic in Dial and LookupPort when handling NUL byte on Windows in net
  More info: https://pkg.go.dev/vuln/GO-2026-4971
  Standard library
    Found in: net@go1.26.2
    Fixed in: net@go1.26.3
    Example traces found:
Error:       #1: client.go:151:2: otlploggrpc.client.UploadLogs calls context.WithCancel, which eventually calls net.Dialer.DialContext

Your code is affected by 1 vulnerability from the Go standard library.
This scan also found 5 vulnerabilities in packages you import and 2
vulnerabilities in modules you require, but your code doesn't appear to call
these vulnerabilities.
Use '-show verbose' for more details.
make: *** [Makefile:235: govulncheck/./exporters/otlp/otlplog/otlploggrpc] Error 3
Error: Process completed with exit code 2.

The CI failure doesn't seem to be caused by this PR.

@yumosx

yumosx commented May 18, 2026

Copy link
Copy Markdown
Member Author

@flc1125 can you help review it?

yumosx and others added 2 commits May 18, 2026 14:15
The observ package uses semconv v1.41.0, but the test was importing
v1.40.0, causing SchemaURL mismatch failures in TestObservability.

Updates the test imports to match the actual package version.
@linux-foundation-easycla

linux-foundation-easycla Bot commented May 24, 2026

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

@yumosx yumosx force-pushed the feat/yumosx/inst-stdlog branch from 809b0e9 to c7f67de Compare May 24, 2026 13:48

@pellared pellared left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yumosx, thanks and sorry for waiting so long for a second review.

@pellared pellared added this to the v1.44.0 milestone May 26, 2026
@pellared pellared merged commit 9a68034 into open-telemetry:main May 26, 2026
33 of 34 checks passed
pellared added a commit that referenced this pull request May 27, 2026
### Added

- Add `ByteSlice` and `ByteSliceValue` functions for new `BYTESLICE`
attribute type in `go.opentelemetry.io/otel/attribute`. (#7948)
- Apply attribute value limit to the `KindBytes` attribute type in
`go.opentelemetry.io/otel/sdk/log`. (#7990)
- Apply attribute value limit to the `BYTESLICE` attribute type in
`go.opentelemetry.io/otel/sdk/trace`. (#7990)
- Support `BYTESLICE` attributes in `go.opentelemetry.io/otel/trace`.
(#8153)
- Support `BYTESLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace`. (#8153)
- Support `BYTESLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlplog`. (#8153)
- Support `BYTESLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#8153)
- Support `BYTESLICE` attributes in
`go.opentelemetry.io/otel/exporters/zipkin`. (#8153)
- Add `String` method for `Value` type in
`go.opentelemetry.io/otel/attribute`. (#8142)
- Add `Slice` and `SliceValue` functions for new `SLICE` attribute type
in `go.opentelemetry.io/otel/attribute`. (#8166)
- Support `SLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace`. (#8216)
- Support `SLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlplog`. (#8216)
- Support `SLICE` attributes in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric`. (#8216)
- Support `SLICE` attributes in
`go.opentelemetry.io/otel/exporters/zipkin`. (#8216)
- Apply `AttributeValueLengthLimit` to `attribute.SLICE` type attribute
values in `go.opentelemetry.io/otel/sdk/trace`, recursively truncating
contained string values. (#8217)
- Add `Error` field on `Record` type in
`go.opentelemetry.io/otel/log/logtest`. (#8148)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`.
(#8157)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`.
(#8157)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`.
(#8157)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`.
(#8157)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`. (#8157)
- Add `WithMaxRequestSize` option in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8157)
- Add `Settable` to `go.opentelemetry.io/otel/metric/x` to allow reusing
attribute options. (#8178)
- Add experimental support for splitting metric data across multiple
batches in `go.opentelemetry.io/otel/sdk/metric`.
Set `OTEL_GO_X_METRIC_EXPORT_BATCH_SIZE=<max_size>` to enable for all
periodic readers.
See `go.opentelemetry.io/otel/sdk/metric/internal/x` for feature
documentation. (#8071)
- Add experimental self-observability metrics in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`.
  Enable with `OTEL_GO_X_SELF_OBSERVABILITY=true` environment variable.
See
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc/internal/x`
for feature documentation. (#8192)
- Add experimental self-observability metrics in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`.
  Enable with `OTEL_GO_X_SELF_OBSERVABILITY=true` environment variable.
See
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp/internal/x`
for feature documentation. (#8194)
- Add experimental self-observability metrics in
`go.opentelemetry.io/otel/exporters/stdout/stdoutlog`.
  Enable with `OTEL_GO_X_SELF_OBSERVABILITY=true` environment variable.
See `go.opentelemetry.io/otel/stdout/stdoutlog/internal/x` for feature
documentation. (#8263)
- Add `WithDefaultAttributes` to `go.opentelemetry.io/otel/metric/x` to
support setting default attributes on instruments. (#8135)
- Add `go.opentelemetry.io/otel/semconv/v1.41.0` package.
The package contains semantic conventions from the `v1.41.0` version of
the OpenTelemetry Semantic Conventions.
See the [migration documentation](./semconv/v1.41.0/MIGRATION.md) for
information on how to upgrade from
`go.opentelemetry.io/otel/semconv/v1.40.0`. (#8324)
- Add Observable variants of instruments to
`go.opentelemetry.io/otel/semconv/v1.41.0` package. (#8350)
- Generate explicit histogram bucket boundaries from weaver
configuration for HTTP and RPC duration instruments in
`go.opentelemetry.io/otel/semconv/v1.41.0`. (#8002)

### Changed

- ⚠️ **Breaking Change:** `go.opentelemetry.io/otel/sdk/metric` now
applies a default cardinality limit of 2000 to comply with the Metrics
SDK specification recommendation.
New attribute sets are dropped when the cardinality limit is reached.
The measurement of these sets are aggregated into a special attribute
set containing `attribute.Bool("otel.metric.overflow", true)`.
  This can break users who relied on the previous unlimited default.
Set `WithCardinalityLimit(0)` or the deprecated
`OTEL_GO_X_CARDINALITY_LIMIT=0` environment variable to preserve
unlimited cardinality.
Note that support for `OTEL_GO_X_CARDINALITY_LIMIT` may be removed in a
future release. (#8247)
- `ErrorType` in `go.opentelemetry.io/otel/semconv` now unwraps errors
created with `fmt.Errorf` when deriving the `error.type` attribute.
(#8133)
- `go.opentelemetry.io/otel/sdk/log` now unwraps error chains created
with `fmt.Errorf` when deriving the `error.type` attribute from errors
on log records. (#8133)
- `Set.MarshalLog` method in `go.opentelemetry.io/otel/attribute` now
uses `Value.String` formatting following the [OpenTelemetry AnyValue
representation for non-OTLP
protocols](https://opentelemetry.io/docs/specs/otel/common/#anyvalue).
(#8169)
- Optimize `go.opentelemetry.io/otel/sdk/metric` to return a drop
reservoir and short-circuit `Offer` calls to the exemplar reservoir when
`exemplar.AlwaysOffFilter` is configured. (#8211) (#8267)
- Optimize `go.opentelemetry.io/otel/sdk/metric` to return a drop
reservoir for asynchronous instruments when `exemplar.TraceBasedFilter`
is configured. (#8286)

### Deprecated

- Deprecate `Value.Emit` method in `go.opentelemetry.io/otel/attribute`.
  Use `Value.String` instead. (#8176)

### Fixed

- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Limit OTLP request size to 64 MiB by default in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`.
The limit applies before compression, oversized requests are treated as
non-retryable errors, and the limit can be configured with the new
`WithMaxRequestSize` option. (#8157, #8365)
- Fix gzipped request body replay on redirect in
`go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp`.
(#8135)
- Fix gzipped request body replay on redirect in
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8152)
- `go.opentelemetry.io/otel/exporters/prometheus` now uses
`Value.String` formatting for label values following the [OpenTelemetry
AnyValue representation for non-OTLP
protocols](https://opentelemetry.io/docs/specs/otel/common/#anyvalue).
(#8170)
- Propagate errors from the exporter when calling `Shutdown` on
`BatchSpanProcessor` in `go.opentelemetry.io/otel/sdk/trace`. (#8197)
- Fix stale status code reporting on self-observability metrics in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp` and
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8226)
- Fix a concurrent `Collect` data race and potential panic in
`go.opentelemetry.io/otel/exporters/prometheus` when
`WithResourceAsConstantLabels` option is used. (#8227)
- Fix race condition in `FixedSizeReservoir` in
`go.opentelemetry.io/otel/sdk/metric/exemplar` by reverting #7447.
(#8249)
- Fix `FixedSizeReservoir` in
`go.opentelemetry.io/otel/sdk/metric/exemplar` to safely handle zero
size.
A capacity check in the constructor initializes the reservoir safely and
skips initialization for zero-cap; early returns in `Offer()` and
`Collect()` ensure no-op behavior. (#8295)
- Fix counting of spans and logs in self-observability metrics in
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc`,
`go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp`,
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc`, and
`go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp`. (#8254)
- Drop conflicting scope attributes named `name`, `version`, or
`schema_url` from metric labels in
`go.opentelemetry.io/otel/exporters/prometheus`, preserving the
dedicated `otel_scope_name`, `otel_scope_version`, and
`otel_scope_schema_url` labels. (#8264)
- Close schema files opened by `ParseFile` in
`go.opentelemetry.io/otel/schema/v1.0` and
`go.opentelemetry.io/otel/schema/v1.1`.
([GHSA-995v-fvrw-c78m](GHSA-995v-fvrw-c78m))
- Enforce the 8192-byte baggage size limit during extraction/parsing,
changing behavior when the limit is exceeded in
`go.opentelemetry.io/otel/baggage` and
`go.opentelemetry.io/otel/propagation`. (#8222)
- Fix `go.opentelemetry.io/otel/semconv/v1.41.0` to include `Attr*`
helper methods for required attributes on observable instruments.
(#8361)
- Limit baggage extraction error reporting in
`go.opentelemetry.io/otel/propagation` to prevent malformed or oversized
baggage headers from flooding logs.
([GHSA-5wrp-cwcj-q835](GHSA-5wrp-cwcj-q835))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants