Skip to content

Conversation

@mahendrabishnoi2
Copy link
Member

@mahendrabishnoi2 mahendrabishnoi2 commented Aug 7, 2025

Fixes #7014

This PR adds support for below self observability metrics for stdoutmetric exporter

  1. otel.sdk.exporter.metric_data_point.inflight
  2. otel.sdk.exporter.metric_data_point.exported
  3. otel.sdk.exporter.operation.duration

These metrics are experimental and hence behind a feature flag OTEL_GO_X_SELF_OBSERVABILITY.
Definition of above metrics is available at https://github.com/open-telemetry/semantic-conventions/blob/v1.36.0/docs/otel/sdk-metrics.md

@codecov
Copy link

codecov bot commented Aug 7, 2025

Codecov Report

❌ Patch coverage is 88.37209% with 15 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.8%. Comparing base (5358fd7) to head (2f84c09).
⚠️ Report is 176 commits behind head on main.

Files with missing lines Patch % Lines
...ic/internal/selfobservability/selfobservability.go 75.0% 9 Missing and 3 partials ⚠️
exporters/stdout/stdoutmetric/exporter.go 94.1% 2 Missing and 1 partial ⚠️
Additional details and impacted files

Impacted file tree graph

@@          Coverage Diff           @@
##            main   #7150    +/-   ##
======================================
  Coverage   82.8%   82.8%            
======================================
  Files        265     268     +3     
  Lines      24896   25018   +122     
======================================
+ Hits       20631   20737   +106     
- Misses      3885    3897    +12     
- Partials     380     384     +4     
Files with missing lines Coverage Δ
...rs/stdout/stdoutmetric/internal/counter/counter.go 100.0% <100.0%> (ø)
exporters/stdout/stdoutmetric/internal/x/x.go 100.0% <100.0%> (ø)
exporters/stdout/stdoutmetric/exporter.go 94.4% <94.1%> (-0.6%) ⬇️
...ic/internal/selfobservability/selfobservability.go 75.0% <75.0%> (ø)

... 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.

@mahendrabishnoi2 mahendrabishnoi2 changed the title feat: exporter/stdout metric auto instrumentation feat: stdoutmetric exporter auto instrumentation Aug 7, 2025
@mahendrabishnoi2 mahendrabishnoi2 marked this pull request as ready for review August 9, 2025 12:44
Copy link
Member Author

@mahendrabishnoi2 mahendrabishnoi2 left a comment

Choose a reason for hiding this comment

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

I don't like how verbose the tests are. Looking for feedback on tests.

if err != nil {
attrs = make([]attribute.KeyValue, len(em.attrs)+1)
copy(attrs, em.attrs)
attrs = append(attrs, semconv.ErrorType(err))
Copy link
Member Author

Choose a reason for hiding this comment

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

semconv.ErrorType - I have copied this from another PR that is not merged yet.
Reason: for stdout metric exporter, I'm not able to think of a set of errors that can be defined and used like other exporters (queue_full etc.)
Looking for feedback.

otel.Handle(err)
}

em.attrs = []attribute.KeyValue{componentName, componentType}
Copy link
Member Author

Choose a reason for hiding this comment

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

As per specification, it requires host and port attributes as well. Not sure what the correct values would be for stdoutmetric exporter.
Looking for feedback.

Copy link
Member

@flc1125 flc1125 left a comment

Choose a reason for hiding this comment

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

reviewed: functional parts only (excluding unit tests)

@mahendrabishnoi2 mahendrabishnoi2 force-pushed the stdoutmetric-auto-instrumentation branch from ff285e6 to 460f303 Compare August 16, 2025 06:42
Comment on lines 224 to 335
rm := &metricdata.ResourceMetrics{
ScopeMetrics: []metricdata.ScopeMetrics{
{
Metrics: []metricdata.Metrics{
{
Name: "gauge_int64",
Data: metricdata.Gauge[int64]{
DataPoints: []metricdata.DataPoint[int64]{{Value: 1}, {Value: 2}},
},
},
{
Name: "gauge_float64",
Data: metricdata.Gauge[float64]{
DataPoints: []metricdata.DataPoint[float64]{
{Value: 1.0},
{Value: 2.0},
{Value: 3.0},
},
},
},
{
Name: "sum_int64",
Data: metricdata.Sum[int64]{
DataPoints: []metricdata.DataPoint[int64]{{Value: 10}},
},
},
{
Name: "sum_float64",
Data: metricdata.Sum[float64]{
DataPoints: []metricdata.DataPoint[float64]{{Value: 10.5}, {Value: 20.5}},
},
},
{
Name: "histogram_int64",
Data: metricdata.Histogram[int64]{
DataPoints: []metricdata.HistogramDataPoint[int64]{
{Count: 1},
{Count: 2},
{Count: 3},
},
},
},
{
Name: "histogram_float64",
Data: metricdata.Histogram[float64]{
DataPoints: []metricdata.HistogramDataPoint[float64]{{Count: 1}},
},
},
{
Name: "exponential_histogram_int64",
Data: metricdata.ExponentialHistogram[int64]{
DataPoints: []metricdata.ExponentialHistogramDataPoint[int64]{
{Count: 1},
{Count: 2},
},
},
},
{
Name: "exponential_histogram_float64",
Data: metricdata.ExponentialHistogram[float64]{
DataPoints: []metricdata.ExponentialHistogramDataPoint[float64]{
{Count: 1},
{Count: 2},
{Count: 3},
{Count: 4},
},
},
},
{
Name: "summary",
Data: metricdata.Summary{
DataPoints: []metricdata.SummaryDataPoint{{Count: 1}},
},
},
},
},
},
}

ctx := context.Background()
err = exp.Export(ctx, rm)
require.NoError(t, err)

var metrics metricdata.ResourceMetrics
err = reader.Collect(ctx, &metrics)
require.NoError(t, err)

var foundExported, foundDuration, foundInflight bool
var exportedCount int64

for _, sm := range metrics.ScopeMetrics {
for _, m := range sm.Metrics {
switch m.Name {
case otelconv.SDKExporterMetricDataPointExported{}.Name():
foundExported = true
if sum, ok := m.Data.(metricdata.Sum[int64]); ok {
for _, dp := range sum.DataPoints {
exportedCount += dp.Value
}
}
case otelconv.SDKExporterOperationDuration{}.Name():
foundDuration = true
case otelconv.SDKExporterMetricDataPointInflight{}.Name():
foundInflight = true
}
}
}

assert.Equal(t, tt.selfObservabilityEnabled, foundExported)
assert.Equal(t, tt.selfObservabilityEnabled, foundDuration)
assert.Equal(t, tt.selfObservabilityEnabled, foundInflight)
assert.Equal(t, tt.expectedExportedCount, exportedCount)
Copy link
Member

Choose a reason for hiding this comment

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

Maybe it’s just my OCD, but could we reorganize the unit tests here?

Also, we can use

func AssertEqual[T Datatypes](t TestingT, expected, actual T, opts ...Option) bool {
for testing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good suggestion. I have merged both tests cases and using metricdatatest.AssertEqual now.

Could you please check this again and see if anything else can be improved?

- use pool to amortize slice allocation
- pass actual context
- use t.Cleanup instead of defer in tests
- improve readability by returning without using err var
- use metricdatatest for comparision in testcase
@pellared
Copy link
Member

pellared commented Sep 1, 2025

@mahendrabishnoi2 PTAL #7272

@flc1125
Copy link
Member

flc1125 commented Sep 11, 2025

Hi, since this process involves specification adjustments and historical review records (which may contain invalid review suggestions), it’s impossible to tell which items need attention amid the large volume of information.

Could we create a new PR based on the current branch before preparing for the review, so that subsequent reviews can proceed more smoothly?

Thanks~

@MrAlias MrAlias added this to the v1.39.0 milestone Sep 15, 2025
@MrAlias
Copy link
Contributor

MrAlias commented Sep 15, 2025

@mahendrabishnoi2 similar to #7162 (comment), can you take a look at #7014 for the checklist that needs to be completed from this issue?

Also, feel free to close or mark this as a draft while you work through the next steps.

@MrAlias MrAlias requested review from dmathieu and flc1125 September 23, 2025 16:02
@flc1125
Copy link
Member

flc1125 commented Sep 24, 2025

@mahendrabishnoi2 Hi, before the new PR arrives, I would like to set this PR to draft mode.

@flc1125 flc1125 marked this pull request as draft September 24, 2025 12:49
@mahendrabishnoi2
Copy link
Member Author

@mahendrabishnoi2 Hi, before the new PR arrives, I would like to set this PR to draft mode.

Sure @flc1125. I didn't get option to do so.

@flc1125
Copy link
Member

flc1125 commented Sep 24, 2025

I didn't get option to do so.

It has been switched to draft mode.

@MrAlias
Copy link
Contributor

MrAlias commented Oct 7, 2025

@mahendrabishnoi2 I just wanted to check in with this PR. Are you still able to update this PR or open a new PR to address the instrumentation requirements?

@mahendrabishnoi2
Copy link
Member Author

@mahendrabishnoi2 I just wanted to check in with this PR. Are you still able to update this PR or open a new PR to address the instrumentation requirements?

Yes @MrAlias. I'm planning to close #7374 first. I was hoping to get inputs on #7374 (comment) and #7374 (comment).
Once I have inputs there, it'll be relatively straightforward to incorporate the same in this PR as I had already made some of the suggested changes in this PR even before the guideline was published by looking at some of your merged PRs.

@mahendrabishnoi2
Copy link
Member Author

Superseded by #7492

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.

Metrics SDK observability - stdoutmetric exporter metrics

5 participants