Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Metrics API with RFC 0003 #87

Merged
merged 35 commits into from
Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
6ca4274
Create functions
lzchen Jul 29, 2019
b23cec1
fix lint
lzchen Jul 31, 2019
981eece
Fix lint
lzchen Jul 31, 2019
8ea9709
fix typing
lzchen Jul 31, 2019
00b4f11
Remove options, constructors, seperate labels
lzchen Aug 6, 2019
34c87ce
Consistent naming for float and int
lzchen Aug 6, 2019
df8ae34
Abstract time series
lzchen Aug 6, 2019
a2561ac
Use ABC
lzchen Aug 6, 2019
1ece493
Fix typo
lzchen Aug 6, 2019
ce9268a
Fix docs
lzchen Aug 6, 2019
f5f9f01
seperate measure classes
lzchen Aug 8, 2019
74a1815
Add examples
lzchen Aug 8, 2019
0a0b8ee
fix lint
lzchen Aug 8, 2019
555bf50
Update to RFC 0003
lzchen Aug 14, 2019
d6b1113
Add spancontext, measurebatch
lzchen Aug 14, 2019
c819109
Merge branch 'master' of https://github.com/open-telemetry/openteleme…
lzchen Aug 15, 2019
18cfc71
Fix docs
lzchen Aug 15, 2019
f646555
Merge branch 'master' of https://github.com/open-telemetry/openteleme…
lzchen Aug 19, 2019
a44cb47
Fix comments
lzchen Aug 22, 2019
94eaad9
fix lint
lzchen Aug 22, 2019
fc251b2
fix lint
lzchen Aug 22, 2019
262f312
fix lint
lzchen Aug 22, 2019
66c0a56
skip examples
lzchen Aug 22, 2019
e2c4a7e
white space
lzchen Aug 22, 2019
2fb7646
fix spacing
lzchen Aug 22, 2019
eb711cb
fix imports
lzchen Aug 22, 2019
baa3a32
fix imports
lzchen Aug 22, 2019
5c30a9c
Merge branch 'master' of https://github.com/open-telemetry/openteleme…
lzchen Sep 3, 2019
211b20c
LabelValues to str
lzchen Sep 3, 2019
bffe040
Black formatting
lzchen Sep 3, 2019
0759b9a
fix isort
lzchen Sep 3, 2019
44d62f8
Remove aggregation
lzchen Sep 12, 2019
c5ab2df
Fix names
lzchen Sep 12, 2019
50d2de5
Remove aggregation from docs
lzchen Sep 12, 2019
d79bc7d
Fix lint
lzchen Sep 12, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ abstract types for OpenTelemetry implementations.

opentelemetry.context
opentelemetry.loader
opentelemetry.metrics
opentelemetry.trace


Expand Down
14 changes: 14 additions & 0 deletions docs/opentelemetry.metrics.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
opentelemetry.metrics package
=============================

Submodules
----------

.. toctree::

opentelemetry.metrics.time_series

Module contents
---------------

.. automodule:: opentelemetry.metrics
5 changes: 5 additions & 0 deletions docs/opentelemetry.metrics.time_series.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
opentelemetry.metrics.time\_series module
==========================================

.. automodule:: opentelemetry.metrics.time_series

304 changes: 304 additions & 0 deletions opentelemetry-api/src/opentelemetry/metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,307 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
The OpenTelemetry metrics API describes the classes used to report raw
measurements, as well as metrics with known aggregation and labels.

The `Meter` class is used to construct `Metric` s to record raw statistics
as well as metrics with predefined aggregation.

See the `metrics api`_ spec for terminology and context clarification.

.. _metrics api:
https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-metrics.md


"""

from abc import ABC, abstractmethod
from typing import List

from opentelemetry.metrics.time_series import (
CounterTimeSeries,
GaugeTimeSeries,
MeasureTimeSeries,
)
from opentelemetry.trace import SpanContext

LabelKeys = List["LabelKey"]
LabelValues = List[str]


class Meter:
"""An interface to allow the recording of metrics.

`Metric` s are used for recording pre-defined aggregation (gauge and
counter), or raw values (measure) in which the aggregation and labels
for the exported metric are deferred.
"""

def create_float_counter(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "FloatCounter":
"""Creates a counter type metric that contains float values.

Args:
name: The name of the counter.
description: Human readable description of the metric.
unit: Unit of the metric values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns: A new `FloatCounter`
"""

def create_int_counter(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "IntCounter":
"""Creates a counter type metric that contains int values.

Args:
name: The name of the counter.
description: Human readable description of the metric.
unit: Unit of the metric values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns:
A new `IntCounter`
"""

def create_float_gauge(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "FloatGauge":
"""Creates a gauge type metric that contains float values.

Args:
name: The name of the counter.
description: Human readable description of the metric.
unit: Unit of the metric values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns:
A new `FloatGauge`
"""

def create_int_gauge(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "IntGauge":
"""Creates a gauge type metric that contains int values.

Args:
name: The name of the counter.
description: Human readable description of the metric.
unit: Unit of the metric values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns:
A new `IntGauge`
"""

def create_int_measure(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "IntMeasure":
"""Creates a measure used to record raw int values.

Args:
name: The name of the measure.
description: Human readable description of this measure.
unit: Unit of the measure values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns:
A new `IntMeasure`
"""

def create_float_measure(
self,
name: str,
description: str,
unit: str,
label_keys: LabelKeys,
span_context: SpanContext = None,
) -> "FloatMeasure":
"""Creates a Measure used to record raw float values.

Args:
name: the name of the measure
description: Human readable description of this measure.
unit: Unit of the measure values.
label_keys: list of keys for the labels with dynamic values.
Order of the list is important as the same order MUST be used
on recording when suppling values for these labels.
span_context: The `SpanContext` that identifies the `Span`
that the metric is associated with.

Returns:
A new `FloatMeasure`
"""


class Metric(ABC):
"""Base class for various types of metrics.

Metric class that inherit from this class are specialized with the type of
time series that the metric holds. Metric is constructed from the meter.
"""

@abstractmethod
def get_or_create_time_series(self, label_values: LabelValues) -> "object":
"""Gets and returns a timeseries, a container for a cumulative value.

If the provided label values are not already associated with this
metric, a new timeseries is returned, otherwise it returns the existing
timeseries with the exact label values. The timeseries returned
contains logic and behaviour specific to the type of metric that
overrides this function.

Args:
label_values: A list of label values that will be associated
with the return timeseries.
"""

def remove_time_series(self, label_values: LabelValues) -> None:
"""Removes the timeseries from the Metric, if present.

The timeseries with matching label values will be removed.

args:
label_values: The list of label values to match against.
"""

def clear(self) -> None:
"""Removes all timeseries from the `Metric`."""


class FloatCounter(Metric):
"""A counter type metric that holds float values.

Cumulative values can go up or stay the same, but can never go down.
Cumulative values cannot be negative.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "CounterTimeSeries":
"""Gets a `CounterTimeSeries` with a cumulative float value."""


class IntCounter(Metric):
"""A counter type metric that holds int values.

Cumulative values can go up or stay the same, but can never go down.
Cumulative values cannot be negative.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "CounterTimeSeries":
"""Gets a `CounterTimeSeries` with a cumulative int value."""


class FloatGauge(Metric):
"""A gauge type metric that holds float values.

Cumulative value can go both up and down. Values can be negative.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "GaugeTimeSeries":
"""Gets a `GaugeTimeSeries` with a cumulative float value."""


class IntGauge(Metric):
"""A gauge type metric that holds int values.

Cumulative value can go both up and down. Values can be negative.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "GaugeTimeSeries":
"""Gets a `GaugeTimeSeries` with a cumulative int value."""


class FloatMeasure(Metric):
"""A measure type metric that holds float values.

Measure metrics represent raw statistics that are recorded.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "MeasureTimeSeries":
"""Gets a `MeasureTimeSeries` with a cumulated float value."""


class IntMeasure(Metric):
"""A measure type metric that holds int values.

Measure metrics represent raw statistics that are recorded.
"""

def get_or_create_time_series(
self, label_values: LabelValues
) -> "MeasureTimeSeries":
"""Gets a `MeasureTimeSeries` with a cumulated int value."""


class LabelKey:
"""The label keys associated with the metric.

:type key: str
:param key: the key for the label

:type description: str
:param description: description of the label
"""

def __init__(self, key: str, description: str) -> None:
self.key = key
self.description = description
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2019, OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: skip-file
from opentelemetry.metrics import LabelKey, LabelValue, Meter

METER = Meter()
LABEL_KEYS = [
LabelKey("environment", "the environment the application is running in")
]
COUNTER = METER.create_int_counter(
"sum numbers", # pragma: no cover
"sum numbers over time",
"number",
LABEL_KEYS,
)
LABEL_VALUE_TESTING = [LabelValue("Testing")]
LABEL_VALUE_STAGING = [LabelValue("Staging")]

# Metrics sent to some exporter
METRIC_TESTING = COUNTER.get_or_create_time_series(LABEL_VALUE_TESTING)
METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_STAGING)

for i in range(100):
METRIC_STAGING.add(i)
Loading