Skip to content

Add public constructors to metrics data types and make SdkLogRecord::…#3457

Open
mdecimus wants to merge 2 commits intoopen-telemetry:mainfrom
stalwartlabs:main
Open

Add public constructors to metrics data types and make SdkLogRecord::…#3457
mdecimus wants to merge 2 commits intoopen-telemetry:mainfrom
stalwartlabs:main

Conversation

@mdecimus
Copy link
Copy Markdown

@mdecimus mdecimus commented Apr 9, 2026

Fixes #2992

Changes

Stalwart Mail Server uses its own metrics collector and export pipeline rather than the SDK's periodic reader. Since 0.30 made all fields on metrics data types pub(crate), it's no longer possible to construct Metric, Sum, Gauge, Histogram, ResourceMetrics, ScopeMetrics, or their data points from outside the crate. This adds new() constructors to each type so that custom exporters can build ResourceMetrics to pass to PushMetricExporter::export().

Similarly, SdkLogRecord::new() is made public and Default is implemented, so consumers with custom logging backends can create log records directly without having to instantiate a SdkLoggerProvider.

Merge requirement checklist

@mdecimus mdecimus requested a review from a team as a code owner April 9, 2026 14:05
@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented Apr 9, 2026

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

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 9, 2026

Codecov Report

❌ Patch coverage is 1.00000% with 99 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.9%. Comparing base (94aa56e) to head (274b4d3).

Files with missing lines Patch % Lines
opentelemetry-sdk/src/metrics/data/mod.rs 0.0% 96 Missing ⚠️
opentelemetry-sdk/src/logs/record.rs 25.0% 3 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##            main   #3457     +/-   ##
=======================================
- Coverage   83.2%   82.9%   -0.4%     
=======================================
  Files        128     128             
  Lines      25048   25147     +99     
=======================================
  Hits       20860   20860             
- Misses      4188    4287     +99     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

@scottgerring
Copy link
Copy Markdown
Member

Hey @mdecimus !
Comparing this to the linked issue I think a few things are in play:

  • Custom error log / handler callback -> I can't see that in this PR, but it is something Cijo mentioned seemed reasonable
  • Making it possible to create SdkLogRecords directly --> in this PR and in the issue, but there's outstanding questions around the use case here
  • Making metrics constructors public --> not in the issue (I think?) but in here. This seems to tie back to some changes made previously to cut down on the public API

I think the first point could be raised easily as a standalone PR if you are still interested in this!

To the second two points to provide some more context for you, we are very cautious of expanding public API; it would be great to work through the reasoning for this on the linked issue. Depending on where that lands we'd probably also ask to break out the SdkLogRecord changes from the metrics API changes.

@mdecimus
Copy link
Copy Markdown
Author

mdecimus commented Apr 30, 2026

Thanks for the review @scottgerring!

To give some context: Stalwart Mail Server has its own telemetry collector that aggregates spans, logs, and metrics from across the codebase using a custom event system. We don't use tracing, the SDK's periodic reader, batch processor, or any of the SDK's pipeline machinery; we just need the OTLP exporters as a transport to ship our already-aggregated data to a collector. Our flow looks like:

  1. Stalwart's collector aggregates events
  2. We translate them into SdkLogRecord / SpanData / ResourceMetrics
  3. We hand them to LogExporter::export() / SpanExporter::export() / PushMetricExporter::export() directly

This means we're a downstream consumer of the SDK types without using the SDK's processors, which is why we hit these construction limitations.

Regarding SdkLogRecord: the use case is exactly the above; we need to build SdkLogRecords in our own export task to feed to a LogExporter. Today the only way to do this is SdkLoggerProvider::builder().build().logger("name").create_log_record(), which forces us to instantiate a full provider just to get an empty record. Making new() public (or adding Default) removes that ceremony with no real change in surface area, since the struct is already #[non_exhaustive] and all fields are set through the trait.

Regarding the metrics constructors: since 0.30 made Metric, Sum, Gauge, Histogram, ResourceMetrics, ScopeMetrics, and the data point types pub(crate), it's now impossible for any external consumer to call PushMetricExporter::export() at all, since the trait requires you to pass a &ResourceMetrics you cannot construct. The exporter trait is public but inert without a way to build its argument. The constructors here are minimal and additive; they don't expose any new fields.

Regarding the error handler: this isn't included in this PR. Adding it back cleanly would mean threading a global callback through the otel_error!/otel_warn! macros (currently they delegate to tracing when internal-logs is enabled, or compile to nothing otherwise), which is a bigger design change that probably warrants its own discussion. We ended up not needing it for Stalwart anyway, since we manually check Result at every export() call site.

Happy to split this into two PRs (one for SdkLogRecord, one for metrics constructors) if that makes review easier. Just let me know which direction you'd prefer.

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.

[Feature]: Add support for custom error handlers + make SdkLogRecord::new public again

2 participants