You've already forked opentelemetry-go
mirror of
https://github.com/open-telemetry/opentelemetry-go.git
synced 2025-08-10 22:31:50 +02:00
Add support for native histogram exemplars (#6772)
Added support for exemplars in exponential histograms. Closes #5777 --------- Co-authored-by: Tyler Yahn <MrAlias@users.noreply.github.com>
This commit is contained in:
@@ -48,6 +48,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
|||||||
See the [migration documentation](./semconv/v1.36.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.34.0.`(#7032)
|
See the [migration documentation](./semconv/v1.36.0/MIGRATION.md) for information on how to upgrade from `go.opentelemetry.io/otel/semconv/v1.34.0.`(#7032)
|
||||||
- Add experimental self-observability span metrics in `go.opentelemetry.io/otel/sdk/trace`.
|
- Add experimental self-observability span metrics in `go.opentelemetry.io/otel/sdk/trace`.
|
||||||
Check the `go.opentelemetry.io/otel/sdk/trace/internal/x` package documentation for more information. (#7027)
|
Check the `go.opentelemetry.io/otel/sdk/trace/internal/x` package documentation for more information. (#7027)
|
||||||
|
- Add native histogram exemplar support in `go.opentelemetry.io/otel/exporters/prometheus`. (#6772)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@@ -382,8 +382,7 @@ func addExponentialHistogramMetric[N int64 | float64](
|
|||||||
otel.Handle(err)
|
otel.Handle(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
m = addExemplars(m, dp.Exemplars, labelNamer)
|
||||||
// TODO(GiedriusS): add exemplars here after https://github.com/prometheus/client_golang/pull/1654#pullrequestreview-2434669425 is done.
|
|
||||||
ch <- m
|
ch <- m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1113,6 +1113,18 @@ func TestExemplars(t *testing.T) {
|
|||||||
escapingScheme: model.NoEscaping,
|
escapingScheme: model.NoEscaping,
|
||||||
validationScheme: model.UTF8Validation,
|
validationScheme: model.UTF8Validation,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "exponential histogram",
|
||||||
|
recordMetrics: func(ctx context.Context, meter otelmetric.Meter) {
|
||||||
|
hist, err := meter.Int64Histogram("exponential_histogram")
|
||||||
|
require.NoError(t, err)
|
||||||
|
hist.Record(ctx, 9, attrsOpt)
|
||||||
|
},
|
||||||
|
expectedExemplarValue: 9,
|
||||||
|
expectedLabels: expectedNonEscapedLabels,
|
||||||
|
escapingScheme: model.NoEscaping,
|
||||||
|
validationScheme: model.UTF8Validation,
|
||||||
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
originalEscapingScheme := model.NameEscapingScheme
|
originalEscapingScheme := model.NameEscapingScheme
|
||||||
@@ -1144,13 +1156,24 @@ func TestExemplars(t *testing.T) {
|
|||||||
metric.WithReader(exporter),
|
metric.WithReader(exporter),
|
||||||
metric.WithResource(res),
|
metric.WithResource(res),
|
||||||
metric.WithView(metric.NewView(
|
metric.WithView(metric.NewView(
|
||||||
metric.Instrument{Name: "*"},
|
metric.Instrument{Name: "foo"},
|
||||||
metric.Stream{
|
metric.Stream{
|
||||||
// filter out all attributes so they are added as filtered
|
// filter out all attributes so they are added as filtered
|
||||||
// attributes to the exemplar
|
// attributes to the exemplar
|
||||||
AttributeFilter: attribute.NewAllowKeysFilter(),
|
AttributeFilter: attribute.NewAllowKeysFilter(),
|
||||||
},
|
},
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
|
metric.WithView(metric.NewView(
|
||||||
|
metric.Instrument{Name: "exponential_histogram"},
|
||||||
|
metric.Stream{
|
||||||
|
Aggregation: metric.AggregationBase2ExponentialHistogram{
|
||||||
|
MaxSize: 20,
|
||||||
|
},
|
||||||
|
AttributeFilter: attribute.NewAllowKeysFilter(),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
meter := provider.Meter("meter", otelmetric.WithInstrumentationVersion("v0.1.0"))
|
meter := provider.Meter("meter", otelmetric.WithInstrumentationVersion("v0.1.0"))
|
||||||
|
|
||||||
@@ -1179,16 +1202,23 @@ func TestExemplars(t *testing.T) {
|
|||||||
case dto.MetricType_COUNTER:
|
case dto.MetricType_COUNTER:
|
||||||
exemplar = metric.GetCounter().GetExemplar()
|
exemplar = metric.GetCounter().GetExemplar()
|
||||||
case dto.MetricType_HISTOGRAM:
|
case dto.MetricType_HISTOGRAM:
|
||||||
for _, b := range metric.GetHistogram().GetBucket() {
|
h := metric.GetHistogram()
|
||||||
|
for _, b := range h.GetBucket() {
|
||||||
if b.GetExemplar() != nil {
|
if b.GetExemplar() != nil {
|
||||||
exemplar = b.GetExemplar()
|
exemplar = b.GetExemplar()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if h.GetZeroThreshold() != 0 || h.GetZeroCount() != 0 ||
|
||||||
|
len(h.PositiveSpan) != 0 || len(h.NegativeSpan) != 0 {
|
||||||
|
require.NotNil(t, h.Exemplars)
|
||||||
|
exemplar = h.Exemplars[0]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
require.NotNil(t, exemplar)
|
require.NotNil(t, exemplar)
|
||||||
require.Equal(t, tc.expectedExemplarValue, exemplar.GetValue())
|
require.Equal(t, tc.expectedExemplarValue, exemplar.GetValue())
|
||||||
require.Len(t, exemplar.GetLabel(), len(tc.expectedLabels))
|
require.Len(t, exemplar.GetLabel(), len(tc.expectedLabels))
|
||||||
|
|
||||||
for _, label := range exemplar.GetLabel() {
|
for _, label := range exemplar.GetLabel() {
|
||||||
val, ok := tc.expectedLabels[label.GetName()]
|
val, ok := tc.expectedLabels[label.GetName()]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
Reference in New Issue
Block a user