blob: 6cde07b9ea4c1b2fcf1a7843d3bfb4054342fcfd [file] [log] [blame]
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package otel
import (
"fmt"
"strconv"
)
// OTLP JSON types for telemetry export.
//
// Specification
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/docs/specification.md
// intAsString is an int64 that marshals to/from a JSON string.
//
// int64 values are encoded as strings because JSON numbers are IEEE 754
// double-precision floats, which can only represent integers exactly up to
// 2^53. Timestamps in nanoseconds and large counts would lose precision.
// See: https://github.com/open-telemetry/opentelemetry-proto/issues/268
// And: https://protobuf.dev/programming-guides/json/
type intAsString int64
func (i intAsString) MarshalJSON() ([]byte, error) {
return fmt.Appendf(nil, `"%d"`, i), nil
}
func (i *intAsString) UnmarshalJSON(data []byte) error {
// Strip quotes if present. Per the spec, both JSON strings ("123")
// and JSON numbers (123) must be accepted for decoding int64 values.
if len(data) >= 2 && data[0] == '"' && data[len(data)-1] == '"' {
data = data[1 : len(data)-1]
}
v, err := strconv.ParseInt(string(data), 10, 64)
if err != nil {
return err
}
*i = intAsString(v)
return nil
}
// Common oltp types
// otlpResource corresponds to Resource.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/resource/v1/resource.proto#L28
type otlpResource struct {
Attributes []otlpAttribute `json:"attributes"`
}
// otlpScope corresponds to InstrumentationScope.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L76
type otlpScope struct {
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// otlpAttribute corresponds to KeyValue.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L66
type otlpAttribute struct {
Key string `json:"key"`
Value otlpAttributeValue `json:"value"`
}
// otlpAttributeValue corresponds to AnyValue.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/common/v1/common.proto#L28
type otlpAttributeValue struct {
StringValue *string `json:"stringValue,omitempty"`
IntValue *intAsString `json:"intValue,omitempty"`
DoubleValue *float64 `json:"doubleValue,omitempty"`
BoolValue *bool `json:"boolValue,omitempty"`
}
// Trace types
// otlpTraceExportRequest is the payload for ExportTraceServiceRequest.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/collector/trace/v1/trace_service.proto#L34
type otlpTraceExportRequest struct {
ResourceSpans []otlpResourceSpans `json:"resourceSpans"`
}
// otlpResourceSpans corresponds to ResourceSpans.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L48
type otlpResourceSpans struct {
Resource otlpResource `json:"resource"`
ScopeSpans []otlpScopeSpans `json:"scopeSpans"`
}
// otlpScopeSpans corresponds to ScopeSpans.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L68
type otlpScopeSpans struct {
Scope otlpScope `json:"scope"`
Spans []otlpSpan `json:"spans"`
}
// otlpSpan corresponds to Span.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L89
type otlpSpan struct {
TraceID string `json:"traceId"`
SpanID string `json:"spanId"`
ParentSpanID string `json:"parentSpanId,omitempty"`
Name string `json:"name"`
Kind int `json:"kind"`
StartTimeUnixNano intAsString `json:"startTimeUnixNano"`
EndTimeUnixNano intAsString `json:"endTimeUnixNano"`
Attributes []otlpAttribute `json:"attributes,omitempty"`
Status otlpSpanStatus `json:"status"`
}
// otlpSpanStatus corresponds to Status.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/trace/v1/trace.proto#L308
type otlpSpanStatus struct {
Code int `json:"code"`
Message string `json:"message,omitempty"`
}
// Metrics types
// otlpMetricsRequest is the payload for ExportMetricsServiceRequest.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/collector/metrics/v1/metrics_service.proto#L34
type otlpMetricsRequest struct {
ResourceMetrics []otlpResourceMetrics `json:"resourceMetrics"`
}
// otlpResourceMetrics corresponds to ResourceMetrics.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L66
type otlpResourceMetrics struct {
Resource otlpResource `json:"resource"`
ScopeMetrics []otlpScopeMetrics `json:"scopeMetrics"`
}
// otlpScopeMetrics corresponds to ScopeMetrics.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L86
type otlpScopeMetrics struct {
Scope otlpScope `json:"scope"`
Metrics []otlpMetric `json:"metrics"`
}
// otlpMetric corresponds to Metric.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L188
type otlpMetric struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Unit string `json:"unit,omitempty"`
Gauge *otlpGauge `json:"gauge,omitempty"`
Sum *otlpSum `json:"sum,omitempty"`
Histogram *otlpHistogram `json:"histogram,omitempty"`
}
// otlpGauge corresponds to Gauge.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L232
type otlpGauge struct {
DataPoints []otlpNumberDataPoint `json:"dataPoints"`
}
// otlpSum corresponds to Sum.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L240
type otlpSum struct {
DataPoints []otlpNumberDataPoint `json:"dataPoints"`
AggregationTemporality int `json:"aggregationTemporality"` // 1=delta, 2=cumulative
IsMonotonic bool `json:"isMonotonic"`
}
// otlpHistogram corresponds to Histogram.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L255
type otlpHistogram struct {
DataPoints []otlpHistogramDataPoint `json:"dataPoints"`
AggregationTemporality int `json:"aggregationTemporality"`
}
// otlpNumberDataPoint corresponds to NumberDataPoint.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L385
type otlpNumberDataPoint struct {
Attributes []otlpAttribute `json:"attributes,omitempty"`
TimeUnixNano intAsString `json:"timeUnixNano"`
AsInt *intAsString `json:"asInt,omitempty"`
AsDouble *float64 `json:"asDouble,omitempty"`
}
// otlpHistogramDataPoint corresponds to HistogramDataPoint.
// https://github.com/open-telemetry/opentelemetry-proto/blob/v1.9.0/opentelemetry/proto/metrics/v1/metrics.proto#L434
type otlpHistogramDataPoint struct {
Attributes []otlpAttribute `json:"attributes,omitempty"`
TimeUnixNano intAsString `json:"timeUnixNano"`
Count intAsString `json:"count"`
Sum *float64 `json:"sum,omitempty"`
BucketCounts []intAsString `json:"bucketCounts"`
ExplicitBounds []float64 `json:"explicitBounds"`
Min *float64 `json:"min,omitempty"`
Max *float64 `json:"max,omitempty"`
}