Skip to content

Commit

Permalink
Add requirement section specification
Browse files Browse the repository at this point in the history
  • Loading branch information
ocelotl committed Nov 9, 2020
1 parent 2507216 commit 6f6cbcd
Show file tree
Hide file tree
Showing 8 changed files with 516 additions and 70 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ bin
.swp

# Misspell binary
.tools
.tools

# Pytest cache
__pycache__

# JSON files generated by the specification parser
*.json
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Technical committee holds regular meetings, notes are held
## Table of Contents

- [Overview](specification/overview.md)
- [Requirements](specification/requirements.md)
- [Glossary](specification/glossary.md)
- [Library Guidelines](specification/library-guidelines.md)
- [Package/Library Layout](specification/library-layout.md)
Expand Down
19 changes: 13 additions & 6 deletions specification/metrics/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,12 +91,19 @@ can be configured at run time.

### Behavior of the API in the absence of an installed SDK

In the absence of an installed Metrics SDK, the Metrics API MUST consist only
of no-ops. None of the calls on any part of the API can have any side effects
or do anything meaningful. Meters MUST return no-op implementations of any
instruments. From a user's perspective, calls to these should be ignored without raising errors
(i.e., *no* `null` references MUST be returned in languages where accessing these results in errors).
The API MUST NOT throw exceptions on any calls made to it.
###### requirement: only_no_ops
> The metrics API MUST consist only of no-ops. None of the calls on any part of the API can have any side effects or do anything meaningful.
###### requirement: meters_return_no_ops
> Meters MUST return no-op implementations of any instruments.
From a user's perspective, calls to these should be ignored without raising errors.

###### requirement: no_null_references
> No null references MUST be returned in languages where accessing these results in errors.
###### requirement: no_api_exceptions
> The API MUST NOT throw exceptions on any calls made to it.
### Measurements

Expand Down
185 changes: 122 additions & 63 deletions specification/metrics/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ API specification](api.md).

The SDK implementors are expected to follow the best practices for the
language and runtime environment when implementing the OpenTelemetry
API. Implementors SHOULD follow the general prescriptions on safety
and performance given in [OpenTelemetry library
API.

###### requirement: follow_general_prescriptions
> Implementors SHOULD follow the general prescriptions on safety and performance.
These guidelines are given in [OpenTelemetry library
guidelines](../library-guidelines.md).

## SDK Terminology
Expand Down Expand Up @@ -88,6 +92,29 @@ These are the significant data types used in the model architecture:
- **ExportRecord**: consists of Instrument, Label Set, Resource, Timestamp(s), and Aggregation
- **ExportRecordSet**: a set of export records.

###### requirement: aggregator_data_type
> An Aggregator data type MUST be implemented
###### requirement: aggregator_snapshot_data_type
> An Aggregator Snapshot data type MUST be implemented
###### requirement: aggregator_selector_data_type
> An Aggregator Selector data type MUST be implemented
###### requirement: accumulation_selector_data_type
> An Accumulation Selector data type MUST be implemented
###### requirement: aggregation_selector_data_type
> An Aggregation Selector data type MUST be implemented
###### requirement: export_kind_delta_data_type
> An Export Kind Delta data type MUST be implemented
###### requirement: export_kind_cumulative_data_type
> An Export Kind Cumulative data type MUST be implemented
###### requirement: export_kind_passthrough_data_type
> An Export Kind PassThrough data type MUST be implemented
###### requirement: export_kind_selector_data_type
> An Export Kind Selector data type MUST be implemented
###### requirement: export_record_data_type
> An Export Record data type MUST be implemented
###### requirement: export_record_set_data_type
> An Export Record Set data type MUST be implemented
The term **SDK instrument** refers to the underlying implementation of
an instrument.

Expand All @@ -112,16 +139,26 @@ in the export pipeline. The Processor is responsible for selecting
Aggregators to use for specific instruments, via an independent
`AggregationSelector` interface, for reducing dimensionality, and for
conversion between DELTA and CUMULATIVE data point representation.

###### requirement: aggregation_selector_interface
> The Processor MUST provide an AggregationSelector interface.
The Processor interface supports arbitrary protocol-independent data
transformation, and Processors can be chained together to form more
complex export pipelines.

###### requirement: chainable_processors
> It MUST be possible to chain multiple Processors
The Exporter component converts processed data into a specific
protocol and exports it somewhere. Following the [library
guidelines](../library-guidelines.md), exporters are expected to
contain minimal functionality and customization is preferably
expressed through Processors.

###### requirement: exporter_customization
> Exporter customization SHOULD be expressed through Processors.
The Controller component coordinates the sequence of actions to
collect, process, and export metric data over a collection interval,
ensuring that access to the export pipeline is properly synchronized.
Expand All @@ -137,9 +174,15 @@ map into a data path. The diagram is not meant to prescribe an
overall architecture for the SDK, just to name the stages of an export
pipeline and place them in context.

SDKs are required to use the standard names for these components, as
this helps build consistency across OpenTelemetry. Every SDK SHOULD
include these components and the interfaces detailed below, although
###### requirement: component_names
> SDKs MUST use the standard names Accumulator, Processor, Exporter and Controller for the respective components.
Using the standard names helps build consistency across OpenTelemetry.

###### requirement: components
> The Accumulator, Processor, Exporter and Controller components SHOULD be included.
SDKs must include these components and the interfaces detailed below, although
the actual organization of each SDK may differ depending on the
available libraries and performance characteristics of the source
language. For example, an SDK could be implemented using one
Expand All @@ -156,38 +199,47 @@ metadata.

#### MeterProvider

###### requirement: meter_provider
> An implementation for MeterProvider MUST be provided.
##### Shutdown

This method provides a way for provider to do any cleanup required.

`Shutdown` MUST be called only once for each `MeterProvider` instance. After
the call to `Shutdown`, subsequent attempts to get a `Meter` are not allowed. SDKs
SHOULD return a valid no-op Meter for these calls, if possible.

`Shutdown` SHOULD provide a way to let the caller know whether it succeeded,
failed or timed out.

`Shutdown` SHOULD complete or abort within some timeout. `Shutdown` can be
implemented as a blocking API or an asynchronous API which notifies the caller
via a callback or an event. Language library authors can decide if they want to
make the shutdown timeout configurable.
###### requirement: shutdown
> An implementation of MeterProvider MUST have a Shutdown method.
###### requirement: shutdown_once
> MeterProvider.Shutdown MUST be called only once for each MeterProvider instance.
###### requirement: shutdown_further_calls
> Further calls to MeterProvider.Shutdown MUST NOT be allowed.
###### requirement: shutdown_further_calls_return
> A valid No Op Meter MAY be returned for these further calls.
###### requirement: shutdown_result
> MeterProvider.Shutdown SHOULD provide a way to let the caller know whether it succeeded, failed or timed out.
###### requirement: shutdown_abort
> MeterProvider.Shutdown SHOULD complete or abort within some timeout.
###### requirement: shutdown_blocking_asynchronous
> MeterProvier.Shutdown MAY be implemented as a blocking API or an asynchronous API which notifies the caller via a callback or an event.
###### requirement: shutdown_timeout_configurable
> MeterProvier.Shutdown timeout MAY be configurable.
#### SDK: Instrument Registration

The OpenTelemetry SDK is responsible for ensuring that an individual
Meter implementation cannot report multiple instruments with the same
name and different definitions. To accomplish this, SDKs MUST reject
duplicate registration of an instrument when another instrument has
already been registered with same metric name to the same named Meter.
The requirement applies even for attempts to register an identical
instrument definition. We assume that a single instrumentation
###### requirement: multiple_instruments_same_name_different_definitions
> An individual Meter implementation MUST NOT report multiple instruments with the same name and different definitions.
###### requirement: duplicate_registration
> Duplicate registration of an instrument when another instrument has already been registered with same metric name to the same named Meter MUST be rejected. The requirement applies even for attempts to register an identical instrument definition.
We assume that a single instrumentation
library can arrange to use a single instrument definition rather than
rely on the SDK to support duplicate registration.

Separate Meters, characterized by different instrumentation library
names, are permitted to register instruments by the same name as used
in different instrumentation libraries, in which case the SDK MUST
consider these as separate instruments.
in different instrumentation libraries.

###### requirement: separate_instruments
> Instruments with the same name in different meters are permitted and MUST be implemented as separate instruments.
The SDK is responsible for implementing any syntactic requirements for
metric names included in the API specification. TODO: link to this
Expand All @@ -201,25 +253,28 @@ TODO: _Add functional requirements for RecordBatch()_.

#### SDK: Collect() function

The SDK is responsible for implementing a `Collect()` function that
calls through to one or more Accumulators. This specification
deliberately avoids requiring a specific relationship between the SDK
###### requirement: collect_function
> A Collect function that calls through to one or more Accumulators MUST be implemented.
This specification deliberately avoids requiring a specific relationship between the SDK
and Accumulator; it is considered an implementation detail whether a
the SDK maintains one Accumulator, one Accumulator per instrument, or
some configuration in between.

The SDK `Collect()` function MUST call through to the Processor with
Accumulations from the active synchronous instruments as well as all
the registered asynchronous instruments.
###### requirement: collect_function_through_processor
> Collect MUST call through to the Processor with Accumulations from the active synchronous instruments as well as all the registered asynchronous instruments.
###### requirement: synchronous_metric_instruments_callbacks
> It MUST be permitted that synchronous metric instruments be used during evaluation of asynchronous instrument callbacks.
The SDK MUST permit synchronous metric instruments to be used during
evaluation of asynchronous instrument callbacks. The use of
synchronous instruments from asynchronous instrument callbacks is
considered a side-effect, in this case. SDKs SHOULD process
synchronous instruments after asynchronous instruments, so that
side-effect synchronous measurements are processed as part of the same
collection interval that contains the corresponding asynchronous
observations.
The use of synchronous instruments from asynchronous instrument callbacks is
considered a side-effect, in this case.

###### requirement: processing_order
> Synchronous instruments SHOULD be processed after asynchronous instruments.
This is so that side-effect synchronous measurements are processed as part of the same
collection interval that contains the corresponding asynchronous observations.

### Accumulator

Expand All @@ -236,30 +291,30 @@ For a synchronous instrument, the Accumulator will:
4. Call Aggregator.SynchronizedMove on the current Aggregator instance to: (a) copy its value into the snapshot Aggregator instance and (b) reset the current Aggregator to the zero state
5. Call Processor.Process for every resulting Accumulation (i.e., Instrument, Label Set, Resource, and Aggregator snapshot)

The Accumulator MUST provide the option to associate a
[`Resource`](../resource/sdk.md) with the Accumulations that it
produces.
###### requirement: accumulator_resource_associate
> The Accumulator MUST provide the option to associate a Resource with the Accumulations that it produces.
Synchronous metric instruments are expected to be used concurrently.
Unless concurrency is not a feature of the source language, the SDK
Accumulator component SHOULD be designed with concurrent performance
in mind.

The Accumulator MAY use exclusive locking to maintain a map of
synchronous instrument updates. The Accumulator SHOULD NOT hold an
exclusive lock while calling an Aggregator (see below), since some
Aggregators may have higher concurrency expectations.
###### requirement: accumulator_concurrency
> The Accumulator component SHOULD be designed with concurrent performance in mind, uUnless concurrency is not a feature of the source language.
###### requirement: accumulator_locking_map
> The Accumulator MAY use exclusive locking to maintain a map of synchronous instrument updates.
###### requirement: accumulator_lock_holding
> The Accumulator SHOULD NOT hold an exclusive lock while calling an Aggregator.
This is because some Aggregators may have higher concurrency expectations (see below).

#### Accumulator: Collect() function

The Accumulator MUST implement a Collect method that builds and
processes current Accumulation values for active instruments, meaning
those that were updated since the prior collection. The Collect
method MUST call the Processor to process Accumulations corresponding
to all metric events that happened before the call.
###### requirement: accumulator_collect
> The Accumulator MUST implement a Collect method that builds and processes current Accumulation values for active instruments, meaning those that were updated since the prior collection.
###### requirement: accumulator_collect_call
> The Collect method MUST call the Processor to process Accumulations corresponding to all metric events that happened before the call.
###### requirement: accumulation_computed
> Accumulations MUST be computed during Collect using a _synchronized move_ operation on the Aggregator.
Accumulations MUST be computed during Collect using a _synchronized
move_ operation on the Aggregator. This operation, using some kind of synchronization, copies
This operation, using some kind of synchronization, copies
the current Aggregator and resets it to the zero state, so that each
Aggregator immediately begins accumulating events for the next
collection period while the current one is processed. An Accumulation
Expand All @@ -280,8 +335,8 @@ TODO _Controller functional requirements_

TODO _Aggregator functional requirements_

The Sum Aggregator SHOULD use atomic operations, if possible and where
there is concurrency.
###### requirement: sum_aggregator_atomic
> The Sum Aggregator SHOULD use atomic operations, if possible and where there is concurrency.
## Model Implementation

Expand Down Expand Up @@ -357,8 +412,10 @@ SDK instruments.

The user is generally interested in the [Metric API `Meter`
interface](api.md#meter-interface), obtained through a [Metric API
`MeterProvider` interface](api.md#meter-provider). The `Meter` interface can be
constructed by wrapping the SDK `Meter` implementation:
`MeterProvider` interface](api.md#meter-provider).

###### requirement: meter_interface_construction
> The Meter interface MAY be constructed by wrapping the SDK Meter implementation.
```go
// WrapMeterImpl constructs a named `Meter` implementation from a
Expand All @@ -371,7 +428,7 @@ Optional to this method:

- the instrumentation library version of the named Meter in use.

To help with instrumentat registration:
To help with instrumentation registration:

```go
// NewUniqueInstrumentMeterImpl returns a wrapped metric.MeterImpl with
Expand All @@ -383,8 +440,10 @@ func NewUniqueInstrumentMeterImpl(impl metric.MeterImpl) metric.MeterImpl {
The API `Descriptor` method defines the instrument in terms of
API-level constructs including name, instrument kind, description, and
units of measure. The SDK instrument MUST provide access to the
`Descriptor` that was passed to its constructor.
units of measure.
###### requirement: instrument_descripto_access
> The SDK instrument MUST provide access to the Descriptor that was passed to its constructor.
```go
// InstrumentImpl is a common interface for synchronous and
Expand Down
Loading

0 comments on commit 6f6cbcd

Please sign in to comment.