Pipeline data (pdata) implements data structures that represent telemetry data in-memory. All data received is converted into this format, travels through the pipeline in this format, and is converted from this format by exporters when sending.
Current implementation primarily uses OTLP protobuf structs as the underlying data structures for many of the declared structs. We keep a pointer to OTLP protobuf in the "orig" member field. This allows efficient translation to/from OTLP wire protocol. The underlying data structure is kept private so that we are free to make changes to it in the future.
The pdata API is designed to avoid mutable data sharing and bugs that stem from that. Each pdata instance cannot contain a reference to an object that is used in another pdata instance.
Names of pdata packages don't follow names of the protobuf packages. The pdata has a package per telemetry type
starting with p
, e.g. ptrace
, and pcommon
package which includes pdata API for protobuf definitions from
common
and resource
protobuf packages.
Pipeline data structs SHOULD be based on the names of the underlying OTLP protobuf messages. Data types for protobuf messages defined as part of another message SHOULD include the owner's name as a prefix. The following examples are two pdata structs based on protobuf messages defined at the package level and as part of another message:
pmetric.NumberDataPoint
based on aNumberDataPoint
protobuf message defined in metrics.proto package.pmetric.ExponentialHistogramDataPointBuckets
based on aBuckets
protobuf message defined inExponentialHistogramDataPoint
message of metrics.proto package.
Exceptions to the naming rules are possible, but not encouraged. Another name can be chosen for brevity or if the struct provides a different interface to manipulate the underlying data. The following exceptions are currently accepted:
plog.Logs
based onLogsData
protobuf message.pmetric.Metrics
based onMetricsData
protobuf message.ptrace.Traces
based onTracesData
protobuf message.pcommon.Slice
based onArrayValue
protobuf message.pcommon.Map
based onKeyValueList
protobuf message.pcommon.Value
based onAnyValue
protobuf message.
Each pdata struct MUST have an initialization function starting with New
prefix. Usage of zero-initialized values is
prohibited and can cause a panic. Each pdata struct MUST provide the following methods:
MoveTo(<type>)
: moves all the data from one struct instance to another. The destination instance is overwritten and the source instance is re-initialized as a new empty instance.CopyTo(<type>)
: deep copies all the data from one struct instance to another. The destination instance is overwritten and the source instance is not modified.
Each pdata struct based on a protobuf message SHOULD have getter methods for every protobuf field. Exceptions to
this rule are allowed if exposing a field is not desirable in pdata. For example, a deprecated protobuf field MAY
not be exposed in pdata. Also, pdata MAY provide a different interface to manipulate protobuf fields without
exposing them explicitly as is done with pcommon.Map
.
Name of a pdata getter methods representing singular protobuf fields SHOULD match the name the protobuf field but
written in CamelCase aligned with Go naming conventions. If a protobuf field is of scalar or enum type, the
corresponding pdata struct MUST provide a setter method with Set
prefix.
Some fields of scalar type in a protobuf message MAY be represented by another pdata type providing an additional
interface, for example pcommon.Timestamp
is another type that wraps uint64
value and provides an additional
interface to work with timestamps. pdata fields returning pcommon.Timestamp
don't follow the recommended naming
schema, Timestamp
word is used instead of TimeUnixNano
to represent protobuf fields that contain
time_unix_nano
, for example StartTimestamp
pdata field is used for start_time_unix_nano
protobuf fields.
Each optional field in a protobuf message exposed in pdata MUST have the following additional methods:
- A method starting with
Has
to determine if the field is set. For example,func (ms HistogramDataPoint) HasMin() bool
. - A method starting with
Remove
prefix to remove a value associated with the optional field. For example,func (ms HistogramDataPoint) RemoveMin()
.
A pdata struct representing a protobuf message with an exposed oneof field MUST provide getter and setter methods for each option of the oneof field. Name of each setter and getter SHOULD be called the same as the protobuf oneof field options. The following exception is adopted in pdata for numeric oneof protobuf fields for brevity:
oneof value {
double as_double = 4;
sfixed64 as_int = 6;
}
is represented in pdata in a shorter form of the following methods:
DoubleValue() float64
SetDoubleValue(float64)
IntValue() int64
SetIntValue(v int64)
If a oneof field option is another protobuf message, the setter name MUST include Empty
in its name. Such setter
MUST set the oneof field to an empty initialized struct and return it. The following conditions define whether the
name of the oneof field must be included in the setter and getter method names:
- If a oneof field represents the whole protobuf message, name of the oneof field itself MAY be omitted in setter and getter methods. For example:
func (ms Metric) Sum() Sum
func (ms Metric) SetEmptySum() Sum
- If a oneof field is relevant only to a particular field of the message, the pdata getter and setter methods MUST include name of the oneof field along with name of the option. For example:
func (ms NumberDataPoint) IntValue() int64
func (ms NumberDataPoint) SetIntValue(v int64)
Additionally, the pdata struct MUST provide a type getter for every exposed oneof protobuf field. Name of the getter
MUST be Type
for oneof fields representing the whole protobuf message (1), or <oneof field>Type
for oneof fields
relevant only to a particular field. The function MUST return an int32
enum type called <struct name>Type
for (1)
and <struct name><oneof field>Type
for (2). For example:
func (ms Metric) Type() MetricType
(1)func (ms NumberDataPoint) ValueType() NumberDataPointValueType
(2)
The enum constants MUST be called the same as the type with a suffix named after the oneof option, e.g.:
MetricTypeSum
(1)NumberDataPointValueTypeString
(2)
An unset oneof protobuf value MUST be represented by a pdata constant with Empty
suffix, e.g.:
MetricTypeEmpty
(1)NumberDataPointValueTypeEmpty
(2)
The pdata enum type SHOULD have String()
method returning a string value of the corresponding oneof field option.
Each repeated protobuf message field exposed in pdata MUST be represented as another pdata struct that SHOULD be
called the same as the underlying protobuf field with Slice
suffix. An exception example is pdata.Map
that
provides a different interface to manipulate the underlying protobuf data.
Each repeated scalar protobuf field exposed in pdata MUST be represented as another pdata type wrapping a native go
slice. Name of the type SHOULD include name of the primitive data type ending with Slice
suffix, e.g. UInt64Slice
.
Each protobuf enum field exposed in pdata MUST have a type declared with underlying int64
type. Name of the type
SHOULD follow the same rules as for struct type names representing protobuf messages:
- If a protobuf enum is defined on the package level, pdata type SHOULD have the same name.
- If a protobuf enum is defined as part of another message, pdata type SHOULD include the protobuf message name as a prefix.
Constants defined for the pdata int64 type MUST have the same names and numeric values defined in protobuf. Names of the constants must be translated from ALL_CAPS_SNAKE_CASE to CamelCase.
The pdata enum type SHOULD have String()
method returning a string value for each constant.
Example of a protobuf enum definition in pdata:
type AggregationTemporality int32
const (
AggregationTemporalityUnspecified = AggregationTemporality(otlpmetrics.AggregationTemporality_AGGREGATION_TEMPORALITY_UNSPECIFIED)
AggregationTemporalityDelta = AggregationTemporality(otlpmetrics.AggregationTemporality_AGGREGATION_TEMPORALITY_DELTA)
AggregationTemporalityCumulative = AggregationTemporality(otlpmetrics.AggregationTemporality_AGGREGATION_TEMPORALITY_CUMULATIVE)
)
Flags fields are typically defined in protobuf as uint32
fields representing 32 distinct boolean flags. The
exposed protobuf flags fields MUST be defined as new types with uint32
underlying type and called according to
the same rules as struct names representing protobuf messages and other enum types. Each pdata flags type MUST have
an empty variable of the fields type with Default
prefix. Each flag MUST have a getter method returning a
particular flag and a setter method with With
prefix returning a new instance of the pdata flags type. Any instance
of the pdata type is immutable since it's just a wrapper over uint32
.
The following pdata type is used for log record flags field:
type LogRecordFlags uint32
var DefaultLogRecordFlags = LogRecordFlags(0)
func (ms LogRecordFlags) IsSampled() bool
func (ms LogRecordFlags) WithIsSampled(b bool) LogRecordFlags
The following protobuf message:
message NumberDataPoint {
reserved 1;
repeated opentelemetry.proto.common.v1.KeyValue attributes = 7;
fixed64 start_time_unix_nano = 2;
fixed64 time_unix_nano = 3;
oneof value {
double as_double = 4;
sfixed64 as_int = 6;
}
repeated Exemplar exemplars = 5;
uint32 flags = 8;
}
is represented by the following pdata API
type NumberDataPoint
func NewNumberDataPoint() NumberDataPoint
func (ms NumberDataPoint) MoveTo(dest NumberDataPoint)
func (ms NumberDataPoint) CopyTo(dest NumberDataPoint)
func (ms NumberDataPoint) Attributes() pcommon.Map
func (ms NumberDataPoint) StartTimestamp() pcommon.Timestamp
func (ms NumberDataPoint) SetStartTimestamp(v pcommon.Timestamp)
func (ms NumberDataPoint) Timestamp() pcommon.Timestamp
func (ms NumberDataPoint) SetTimestamp(v pcommon.Timestamp)
func (ms NumberDataPoint) ValueType() NumberDataPointValueType
func (ms NumberDataPoint) DoubleValue() float64
func (ms NumberDataPoint) SetDoubleValue(v float64)
func (ms NumberDataPoint) IntValue() int64
func (ms NumberDataPoint) SetIntValue(v int64)
func (ms NumberDataPoint) Exemplars() ExemplarSlice
func (ms NumberDataPoint) Flags() DataPointFlags
func (ms NumberDataPoint) SetFlags(v DataPointFlags)