Skip to content

Commit

Permalink
Merge branch 'master' into semconv-messaging
Browse files Browse the repository at this point in the history
  • Loading branch information
arminru authored Feb 13, 2020
2 parents c699fdb + e698d8d commit 3f64ff5
Show file tree
Hide file tree
Showing 13 changed files with 484 additions and 171 deletions.
10 changes: 7 additions & 3 deletions specification/api-metrics-meter.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Metric SDK-facing API

This document will be updated as part of the v0.2 milestone with a
detailed list of `Meter` API methods. These methods will match the
user-facing API specified [here](api-metrics-user.md).
<!-- toc -->
<!-- tocstop -->

This document will be updated as part of the v0.4 milestone with a
detailed list of `Meter` API functions. These functions are given a
high-level description in the [overview document](api-metrics.md) and
this document will simply give details on the `Meter` API.
95 changes: 66 additions & 29 deletions specification/api-metrics-user.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
# Metric User-facing API

Note: This specification for the v0.2 OpenTelemetry milestone does not
cover the Observer gauge instrument discussed in the
[overview](api-metrics.md). Observer instruments will be added in the
v0.3 milestone.

TODO: Add a table of contents.
<!-- toc -->

- [Overview](#overview)
* [Obtaining a Meter](#obtaining-a-meter)
* [Metric names](#metric-names)
* [Format of a metric event](#format-of-a-metric-event)
* [New constructors](#new-constructors)
+ [Metric instrument constructor example code](#metric-instrument-constructor-example-code)
* [Metric calling conventions](#metric-calling-conventions)
+ [Bound instrument calling convention](#bound-instrument-calling-convention)
+ [Direct instrument calling convention](#direct-instrument-calling-convention)
+ [RecordBatch calling convention](#recordbatch-calling-convention)
+ [Label set re-use is encouraged](#label-set-re-use-is-encouraged)
- [Missing label keys](#missing-label-keys)
- [Option: Convenience method to bypass `meter.Labels(...)`](#option-convenience-method-to-bypass-meterlabels)
- [Option: Ordered LabelSet construction](#option-ordered-labelset-construction)
- [Detailed specification](#detailed-specification)
* [Instrument construction](#instrument-construction)
+ [Recommended label keys](#recommended-label-keys)
+ [Instrument options](#instrument-options)
* [Bound instrument API](#bound-instrument-api)
* [Direct instrument API](#direct-instrument-api)
* [Interaction with distributed correlation context](#interaction-with-distributed-correlation-context)

<!-- tocstop -->

Note: This specification for the v0.3 OpenTelemetry milestone does not
include specification related to the Observer instrument, as described
in the [overview](api-metrics.md). Observer instruments were detailed
in [OTEP
72-metric-observer](https://github.com/open-telemetry/oteps/blob/master/text/0072-metric-observer.md)
and will be added to this document following the v0.3 milestone.
Gauge instruments will be removed from this specification folowing the
v0.3 milestone too, as discussed in [OTEP
80-remove-metric-gauge](https://github.com/open-telemetry/oteps/blob/master/text/0080-remove-metric-gauge.md).

## Overview

Metric instruments are the entry point for application and framework
developers to instrument their code using counters, gauges, and
measures.
Metric instruments are the entry point for application and framework developers to instrument their code using counters, gauges, and measures.
Metrics are created by calling methods on a `Meter` which is in turn created by a global `MeterProvider`.

### Obtaining a Meter

New `Meter` instances can be created via a `MeterProvider` and its `getMeter` method.
`MeterProvider`s are generally expected to be used as singletons.
Implementations SHOULD provide a single global default `MeterProvider`. The `getMeter` method expects two string arguments:

- `name` (required): This name must identify the instrumentation library (also referred to as integration, e.g. `io.opentelemetry.contrib.mongodb`)
and *not* the instrumented library.
In case an invalid name (null or empty string) is specified, a working default `Meter` implementation is returned as a fallback
rather than returning null or throwing an exception.
A `MeterProvider` could also return a no-op `Meter` here if application owners configure the SDK to suppress telemetry produced by this library.
This name will be used as the `namespace` for any metrics created using the returned `Meter`.
- `version` (optional): Specifies the version of the instrumentation library (e.g. `semver:1.0.0`).

### Metric names

Expand All @@ -23,23 +65,18 @@ external systems. Metric names conform to the following syntax:
3. The first character must be non-numeric, non-space, non-punctuation
4. Subsequent characters must be belong to the alphanumeric characters, '_', '.', and '-'.

Metrics names belong to a namespace by virtue of a "Named" `Meter`
instance. A "Named" `Meter` refers to the requirement that every
`Meter` instance must have an associated `component` label, determined
statically in the code. The `component` label value of the associated
`Meter` serves as its namespace, allowing the same metric name to be
used in multiple libraries of code, unambiguously, within the same
application.

Metric instruments are defined using a `Meter` instance, using a
variety of `New` methods specific to the kind of metric and type of
input (integer or floating point). The Meter will return an error
when a metric name is already registered with a different kind for the
same component name. Metric systems are expected to automatically
prefix exported metrics by the `component` namespace in a manner
consistent with the target system. For example, a Prometheus exporter
SHOULD use the component followed by `_` as the [application
prefix](https://prometheus.io/docs/practices/naming/#metric-names).
Metric names belong to a namespace, which is the `name` of the associated `Meter`,
allowing the same metric name to be used in multiple libraries of code,
unambiguously, within the same application.

Metric instruments are defined using a `Meter` instance, using a variety
of `New` methods specific to the kind of metric and type of input(integer
or floating point). The Meter will return an error when a metric name is
already registered with a different kind for the same name. Metric systems
are expected to automatically prefix exported metrics by the namespace in a
manner consistent with the target system. For example, a Prometheus exporter
SHOULD use the namespace followed by `_` as the
[application prefix](https://prometheus.io/docs/practices/naming/#metric-names).

### Format of a metric event

Expand Down Expand Up @@ -71,7 +108,7 @@ either floating point or integer inputs, see the detailed design below.
Binding instruments to a single `Meter` instance has two benefits:

1. Instruments can be exported from the zero state, prior to first use, with no explicit `Register` call
2. The component name provided by the named `Meter` satisfies a namespace requirement
2. The name provided by the `Meter` satisfies a namespace requirement

The recommended practice is to define structures to contain the
instruments in use and keep references only to the instruments that
Expand All @@ -82,14 +119,14 @@ metric instruments statically and providing the `Meter` interface at
the time of use. In this example, typical of statsd clients, existing
code may not be structured with a convenient place to store new metric
instruments. Where this becomes a burden, it is recommended to use
the global meter factory to construct a static named `Meter`, to
the global meter provider to construct a static `Meter`, to
construct metric instruments.

The situation is similar for users of Prometheus clients, where
instruments are allocated statically and there is an implicit global.
Such code may not have access to the appropriate `Meter` where
instruments are defined. Where this becomes a burden, it is
recommended to use the global meter factory to construct a static
recommended to use the global meter provider to construct a static
named `Meter`, to construct metric instruments.

Applications are expected to construct long-lived instruments.
Expand Down
141 changes: 98 additions & 43 deletions specification/api-propagators.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
Table of Contents
</summary>

- [Binary Format](#binary-format)
- [ToBytes](#tobytes)
- [FromBytes](#frombytes)
- [Overview](#overview)
- [HTTP Text Format](#http-text-format)
- [Fields](#fields)
- [Inject](#inject)
Expand All @@ -16,51 +14,35 @@ Table of Contents
- [Extract](#extract)
- [Getter argument](#getter)
- [Get](#get)
- [Composite Propagator](#composite-propagator)
- [Global Propagators](#global-propagators)

</details>

Propagators API consists of two main formats:
## Overview

- `BinaryFormat` is used to serialize and deserialize a value into a binary representation.
- `HTTPTextFormat` is used to inject and extract a value as text into carriers that travel
in-band across process boundaries.

Deserializing must set `IsRemote` to true on the returned `SpanContext`.

## Binary Format

`BinaryFormat` is a formatter to serialize and deserialize a value into a binary format.

`BinaryFormat` MUST expose the APIs that serializes values into bytes,
and deserializes values from bytes.

### ToBytes
Cross-cutting concerns send their state to the next process using
`Propagator`s, which are defined as objects used to read and write
context data to and from messages exchanged by the applications.
Each concern creates a set of `Propagator`s for every supported `Format`.

Serializes the given value into the on-the-wire representation.
Propagators leverage the `Context` to inject and extract data for each
cross-cutting concern, such as traces and correlation context.

Required arguments:

- the value to serialize, can be `SpanContext` or `DistributedContext`.

Returns the on-the-wire byte representation of the value.
The Propagators API is expected to be leveraged by users writing
instrumentation libraries.

### FromBytes
The Propagators API currently consists of one `Format`:

Creates a value from the given on-the-wire encoded representation.

If the value could not be parsed, the underlying implementation SHOULD decide to return ether
an empty value, an invalid value, or a valid value.

Required arguments:

- on-the-wire byte representation of the value.
- `HTTPTextFormat` is used to inject values into and extract values from carriers as text that travel
in-band across process boundaries.

Returns a value deserialized from bytes.
A binary `Format` will be added in the future.

## HTTP Text Format

`HTTPTextFormat` is a formatter that injects and extracts a value as text into carriers that
travel in-band across process boundaries.
`HTTPTextFormat` is a formatter that injects and extracts a cross-cutting concern
value as text into carriers that travel in-band across process boundaries.

Encoding is expected to conform to the HTTP Header Field semantics. Values are often encoded as
RPC/HTTP request headers.
Expand Down Expand Up @@ -94,7 +76,7 @@ Injects the value downstream. For example, as http headers.

Required arguments:

- the value to be injected, can be `SpanContext` or `DistributedContext`.
- A `Context`. The Propagator MUST retrieve the appropriate value from the `Context` first, such as `SpanContext`, `CorrelationContext` or another cross-cutting concern context. For languages supporting current `Context` state, this argument is OPTIONAL, defaulting to the current `Context` instance.
- the carrier that holds propagation fields. For example, an outgoing message or http request.
- the `Setter` invoked for each propagation key to add or remove.

Expand All @@ -120,18 +102,23 @@ The implemenation SHOULD preserve casing (e.g. it should not transform `Content-

### Extract

Extracts the value from upstream. For example, as http headers.
Extracts the value from an incoming request. For example, from the headers of an HTTP request.

If the value could not be parsed, the underlying implementation will decide to return an
object representing either an empty value, an invalid value, or a valid value. Implementations
MUST not return null.
If a value can not be parsed from the carrier for a cross-cutting concern,
the implementation MUST NOT throw an exception. It MUST store a value in the `Context`
that the implementation can recognize as a null or empty value.

Required arguments:

- A `Context`. For languages supporting current `Context` state this argument is OPTIONAL, defaulting to the current `Context` instance.
- the carrier holds propagation fields. For example, an outgoing message or http request.
- the instance of `Getter` invoked for each propagation key to get.

Returns the non-null extracted value.
Returns a new `Context` derived from the `Context` passed as argument,
containing the extracted value, which can be a `SpanContext`,
`CorrelationContext` or another cross-cutting concern context.

If the extracted value is a `SpanContext`, its `IsRemote` property MUST be set to true.

#### Getter argument

Expand All @@ -150,4 +137,72 @@ Required arguments:
- the carrier of propagation fields, such as an HTTP request.
- the key of the field.

The Get function is responsible for handling case sensitivity. If the getter is intended to work with a HTTP request object, the getter MUST be case insensitive. To improve compatibility with other text-based protocols, text format implemenations MUST ensure to always use the canonical casing for their attributes. NOTE: Cannonical casing for HTTP headers is usually title case (e.g. `Content-Type` instead of `content-type`).
The Get function is responsible for handling case sensitivity. If the getter is intended to work with a HTTP request object, the getter MUST be case insensitive. To improve compatibility with other text-based protocols, text `Format` implementions MUST ensure to always use the canonical casing for their attributes. NOTE: Cannonical casing for HTTP headers is usually title case (e.g. `Content-Type` instead of `content-type`).

## Composite Propagator

Implementations MUST offer a facility to group multiple `Propagator`s
from different cross-cutting concerns in order to leverage them as a
single entity.

The resulting composite `Propagator` will invoke the `Propagators`
in the order they were specified.

Each composite `Propagator` will be bound to a specific `Format`, such
as `HttpTextFormat`, as different `Format`s will likely operate on different
data types.
There MUST be functions to accomplish the following operations.

- Create a composite propagator
- Extract from a composite propagator
- Inject into a composite propagator

### Create a Composite Propagator

Required arguments:

- A list of `Propagator`s.

Returns a new composite `Propagator` with the specified `Propagator`s.

### Extract

Required arguments:

- A `Context`.
- The carrier that holds propagation fields.
- The instance of `Getter` invoked for each propagation key to get.

### Inject

Required arguments:

- A `Context`.
- The carrier that holds propagation fields.
- The `Setter` invoked for each propagation key to add or remove.

## Global Propagators

Implementations MAY provide global `Propagator`s for
each supported `Format`.

If offered, the global `Propagator`s should default to a composite `Propagator`
containing W3C Trace Context and Correlation Context `Propagator`s,
in order to provide propagation even in the presence of no-op
OpenTelemetry implementations.

### Get Global Propagator

This method MUST exist for each supported `Format`.

Returns a global `Propagator`. This usually will be composite instance.

### Set Global Propagator

This method MUST exist for each supported `Format`.

Sets the global `Propagator` instance.

Required parameters:

- A `Propagator`. This usually will be a composite instance.
Loading

0 comments on commit 3f64ff5

Please sign in to comment.