Component
go.opentelemetry.io/contrib/bridges/prometheus
Describe the issue
All Prometheus-to-OTLP metric converters determine whether an explicit sample timestamp is present by checking whether m.GetTimestampMs() != 0.
TimestampMs is an optional *int64. Its generated getter returns 0 both when the field is absent and when it is explicitly set to Unix epoch (0). As a result, an explicitly supplied epoch timestamp is treated as absent and replaced with the time of Produce.
The affected converters are:
This was identified in #9099 (comment).
The OpenTelemetry Prometheus compatibility specification requires a present Prometheus sample timestamp to be converted to the OTLP data point timestamp: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/prometheus_and_openmetrics.md#timestamps.
Expected behavior
Converters should test field presence with m.TimestampMs != nil. If the field is present, including when its value is 0, the OTLP data point time should be set with time.UnixMilli(m.GetTimestampMs()). Only an absent timestamp should use the time of Produce.
Steps to reproduce
- Create a Prometheus metric with an explicit epoch timestamp, for example with
prometheus.NewMetricWithTimestamp(time.Unix(0, 0), metric) or with TimestampMs: proto.Int64(0) on a dto.Metric.
- Gather and convert the metric using the Prometheus bridge.
- Observe that the OTLP data point timestamp is the current production time instead of
1970-01-01T00:00:00Z.
Suggested regression coverage
Add table-driven coverage for every converter verifying:
- absent
TimestampMs uses the production time;
- present
TimestampMs equal to 0 produces Unix epoch;
- present non-zero
TimestampMs preserves that timestamp.
Environment
Observed on the current main branch and in the implementation proposed by #9099. This behavior is independent of operating system and architecture.
Component
go.opentelemetry.io/contrib/bridges/prometheusDescribe the issue
All Prometheus-to-OTLP metric converters determine whether an explicit sample timestamp is present by checking whether
m.GetTimestampMs() != 0.TimestampMsis an optional*int64. Its generated getter returns0both when the field is absent and when it is explicitly set to Unix epoch (0). As a result, an explicitly supplied epoch timestamp is treated as absent and replaced with the time ofProduce.The affected converters are:
convertGaugeconvertCounterconvertExponentialHistogramconvertSummaryconvertHistogramconvertUntyped, introduced in Prometheus Bridge: Support untyped metrics #9099This was identified in #9099 (comment).
The OpenTelemetry Prometheus compatibility specification requires a present Prometheus sample timestamp to be converted to the OTLP data point timestamp: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/compatibility/prometheus_and_openmetrics.md#timestamps.
Expected behavior
Converters should test field presence with
m.TimestampMs != nil. If the field is present, including when its value is0, the OTLP data point time should be set withtime.UnixMilli(m.GetTimestampMs()). Only an absent timestamp should use the time ofProduce.Steps to reproduce
prometheus.NewMetricWithTimestamp(time.Unix(0, 0), metric)or withTimestampMs: proto.Int64(0)on adto.Metric.1970-01-01T00:00:00Z.Suggested regression coverage
Add table-driven coverage for every converter verifying:
TimestampMsuses the production time;TimestampMsequal to0produces Unix epoch;TimestampMspreserves that timestamp.Environment
Observed on the current
mainbranch and in the implementation proposed by #9099. This behavior is independent of operating system and architecture.