-
Notifications
You must be signed in to change notification settings - Fork 1.2k
stdoutmetric: self-observability: exporter metrics #7150
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 26 commits
48b1568
c03b9f0
4ddd0b3
987b77e
b4d2756
b7181a4
c6f91ac
a9ad0e2
7b1fb2d
ef4a629
51f2f2b
38eb316
b67b593
ecbb337
d6d0dd8
ee64105
ddfb3c3
db64dc0
089252e
884ade7
32b6f61
460f303
9fea018
a6f0637
938cbb0
b247192
ee0328e
4c357a9
2edfed9
18e0530
9976cfc
2f84c09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -7,16 +7,22 @@ import ( | |||
| "bytes" | ||||
| "context" | ||||
| "encoding/json" | ||||
| "errors" | ||||
| "io" | ||||
| "strconv" | ||||
| "testing" | ||||
| "time" | ||||
|
|
||||
| "github.com/stretchr/testify/assert" | ||||
| "github.com/stretchr/testify/require" | ||||
|
|
||||
| "go.opentelemetry.io/otel" | ||||
| "go.opentelemetry.io/otel/attribute" | ||||
| "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" | ||||
| "go.opentelemetry.io/otel/sdk/metric" | ||||
| "go.opentelemetry.io/otel/sdk/metric/metricdata" | ||||
| semconv "go.opentelemetry.io/otel/semconv/v1.36.0" | ||||
| "go.opentelemetry.io/otel/semconv/v1.36.0/otelconv" | ||||
| ) | ||||
|
|
||||
| func testEncoderOption() stdoutmetric.Option { | ||||
|
|
@@ -25,6 +31,13 @@ func testEncoderOption() stdoutmetric.Option { | |||
| return stdoutmetric.WithEncoder(enc) | ||||
| } | ||||
|
|
||||
| // failingEncoder always returns an error when Encode is called. | ||||
| type failingEncoder struct{} | ||||
|
|
||||
| func (failingEncoder) Encode(any) error { | ||||
| return errors.New("encoding failed") | ||||
| } | ||||
|
|
||||
| func testCtxErrHonored(factory func(*testing.T) func(context.Context) error) func(t *testing.T) { | ||||
| return func(t *testing.T) { | ||||
| t.Helper() | ||||
|
|
@@ -178,3 +191,200 @@ func TestAggregationSelector(t *testing.T) { | |||
| var unknownKind metric.InstrumentKind | ||||
| assert.Equal(t, metric.AggregationDrop{}, exp.Aggregation(unknownKind)) | ||||
| } | ||||
|
|
||||
| func TestExporter_Export_SelfObservability(t *testing.T) { | ||||
| tests := []struct { | ||||
| name string | ||||
| selfObservabilityEnabled bool | ||||
| expectedExportedCount int64 | ||||
| }{ | ||||
| { | ||||
| name: "Enabled", | ||||
| selfObservabilityEnabled: true, | ||||
| expectedExportedCount: 19, | ||||
| }, | ||||
| { | ||||
| name: "Disabled", | ||||
| selfObservabilityEnabled: false, | ||||
| expectedExportedCount: 0, | ||||
| }, | ||||
| } | ||||
| for _, tt := range tests { | ||||
| t.Run(tt.name, func(t *testing.T) { | ||||
| t.Setenv("OTEL_GO_X_SELF_OBSERVABILITY", strconv.FormatBool(tt.selfObservabilityEnabled)) | ||||
| reader := metric.NewManualReader() | ||||
| mp := metric.NewMeterProvider(metric.WithReader(reader)) | ||||
| origMp := otel.GetMeterProvider() | ||||
| otel.SetMeterProvider(mp) | ||||
| defer otel.SetMeterProvider(origMp) | ||||
mahendrabishnoi2 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||
|
|
||||
| exp, err := stdoutmetric.New(testEncoderOption()) | ||||
| require.NoError(t, err) | ||||
|
|
||||
| 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) | ||||
|
||||
| func AssertEqual[T Datatypes](t TestingT, expected, actual T, opts ...Option) bool { |
There was a problem hiding this comment.
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?
Uh oh!
There was an error while loading. Please reload this page.