opencensus-specs

Record API Overview

The stats library allows users to record metrics for their applications or libraries. The core data types used are:

Measure

A Measure describes the type of the individual values/measurements recorded by an application. It includes information such as the type of measurement, the units of measurement and descriptive names for the data. This provides the fundamental type used for recording data.

A Measure describes a value with the following metadata:

Implementations MAY define a Measure data type, constructed from the parameters above. Measure MAY have getters for retrieving all of the information used in Measure definition. Once created, Measure metadata is immutable.

Example in Java:

private static final MeasureDouble RPC_LATENCY =
    MeasureDouble.create("grpc.io/latency", "latency", "ms");

References to Measures in the system MAY be obtained from querying of registered Measures. This functionality is required to decouple the recording of the data from the exporting of the data.

For languages that do not allow private properties/metadata and if they are needed implementations MAY define a MeasureDescription data type which contains all the read-only fields from the Measure definition such as: name, description, unit and type.

Measurement

A Measurement is defined from the following:

Implementations MAY define a MeasurementMap which describes a set of data points to be collected for a set of Measures. Adding this functionality may improve the efficiency of the record usage API. Additionally, when recording Measurements, MeasurementMap should optionally take a map of string key-value pairs to record an exemplar. The string map is called attachments and represents the contextual information of an exemplar, for example trace id, span id or dropped labels.

Recording Stats

Users should record Measurements against a context, either an explicit context or the implicit current context. Tags from the context are recorded with the Measurements if they are any. When recording against an explicit context, implementations should allow users to add extra tags, and those tags should not be added to the current context.

Note that there is no implicit recording for exemplars. If you want to record a Measurement against an exemplar, you have to explicitly pass a string-string map.

Implementations SHOULD provide a means of recording multiple Measurements at once. This functionality can be provided through one of the following options:

Record semantics

Record may defer view updates to a background thread or process. Therefore, updates to views may not take effect right away. No guarantees are necessarily provided about the order in which Record calls are processed.

Example in Java:

// Static constants.
private static final MeasureDouble RPC_LATENCY =
    MeasureDouble.create("grpc.io/client/latency", "latency", "ms");
private static final MeasureLong RPC_BYTES_SENT =
    MeasureLong.create("grpc.io/client/bytes_sent", "bytes sent", "kb");
private static final TagKey MY_KEY = TagKey.create("my.org/key");
// Record against implicit context.
MeasurementMap measurementMap = new MeasurementMap();
measurementMap.put(RPC_LATENCY, 10.3);
measurementMap.put(RPC_BYTES_SENT, 124);
measurementMap.record();  // Reads context from thread-local.
// Record against explicit context.
MeasurementMap measurementMap = new MeasurementMap();
measurementMap.put(RPC_LATENCY, 15);
measurementMap.put(RPC_BYTES_SENT, 200);
TagValue value = TagValue.create("some value");
measurementMap.record(
    Tags.getTagger().currentBuilder().put(MY_KEY, value).build());  // Records against an extra tag.
// Another example on recording against sampled SpanContext.
SpanContext spanContext = tracer.getCurrentSpan().getContext();
if (spanContext.getTraceOptions().isSampled()) {
  // Client code needs to take care of encoding.
  // 'Attachment' is the string representation of the contextual information of an exemplar.
  measurementMap.putAttachment("TraceId", encode(spanContext.getTraceId()));
  measurementMap.putAttachment("SpanId", encode(spanContext.getSpanId()));
  measurementMap.record(tagContext);
}