From 6ca42741178ac2eccf4718b1df78f211d6f94070 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 29 Jul 2019 15:16:38 -0700 Subject: [PATCH 01/41] Create functions Comments for Meter More comments Add more comments Fix typos --- .../distributedcontext/__init__.py | 4 + .../src/opentelemetry/metrics/__init__.py | 511 ++++++++++++++++++ 2 files changed, 515 insertions(+) diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py index d853a7bcf65..b2f19c07443 100644 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py +++ b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py @@ -11,3 +11,7 @@ # 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. + +# TODO +class DistributedContext: + pass diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index d853a7bcf65..a0a49c4ee7e 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -11,3 +11,514 @@ # 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. + +import typing + +from opentelemetry.context import SpanContext +from opentelemetry.distributedcontext import DistributedContext +from opentelemetry.resources import Resource + + +class Meter: + """An interface to allow the recording of measurements and metrics. + + :class:`Measurement`s are used for recording raw values, in which the + aggregation and labels for the exported metric are defered. This should be + used to record measurements like "server_latency" or "received_bytes", + where the value of interest is the recorded value itself. + + :class:`Metric`s are used for recording pre-defined aggregation, or already + aggregated data. This should be used to report metrics like cpu/memory + usage, in which the type of aggregation is already defined, or simple + metrics like "queue_length". + + Initialization of the :class:`Meter` is done through the `meter()` function + (see below). The meter instance has a singleton implementation. + """ + + def create_double_counter(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> CounterDouble: + """Creates a counter type metric that contains double values. + + Args: + name: The name of the counter. + options: An optional :class:`.MetricOptions` used to populate + details about the counter. + + Returns: A new :class:`.CounterDouble` + """ + + def create_long_counter(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> CounterLong: + """Creates a counter type metric that contains long values. + + Args: + name: The name of the counter. + options: An optional :class:`.MetricOptions` used to populate + details about the counter. + + Returns: + A new :class:`.CounterLong` + """ + + def create_double_gauge(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> GaugeDouble: + """Creates a gauge type metric that contains double values. + + Args: + name: The name of the gauge. + options: An optional :class:`.MetricOptions` used to populate + details about the gauge. + + Returns: + A new :class:`.GaugeDouble` + """ + + def create_long_gauge(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> GaugeLong: + """Creates a gauge type metric that contains long values. + + Args: + name: The name of the gauge. + options: An optional :class:`.MetricOptions` used to populate + details about the gauge. + + Returns: + A new :class:`.GaugeLong` + """ + + def create_measure(self, + name: str, + options: typing.Optional[MeasureOptions] = None) \ + -> Measure: + """Creates a Measure used to record raw :class:`.Measurement`s. + + Args: + name: the name of the measure + options: An optional :class:`.MeasureOptions` used to populate + details about the measure + + Returns: + A :class:`.Measure` + """ + + def record(self, + measurements: typing.List[Measurement], + options: typing.Optional[RecordOptions] = None) -> None: + """A function use to record a set of :class:`.Measurement`s. + + The API is built with the idea that measurement aggregation will occur + asynchronously. Typical library records multiple measurements at once, + so this function accepts a collection of measurements so the library + can batch all of them that need to be recorded. + + Args: + measurements: The collection of measurements to record. options: + An optional :class:`.RecordOptions` used to populate details during + recording. + + Returns: None + """ + +_METER: typing.Optional[Meter] = None +_METER_FACTORY: typing.Optional[ + typing.Callable[[typing.Type[Meter]], typing.Optional[Meter]]] = None + + +def meter() -> Meter: + """Gets the current global :class:`.Meter` object. + + If there isn't one set yet, a default will be loaded. + """ + global _METER, _METER_FACTORY # pylint:disable=global-statement + + if _METER is None: + # pylint:disable=protected-access + _METER = loader._load_impl(Meter, _METER_FACTORY) + del _METER_FACTORY + + return _METER + + +def set_preferred_meter_implementation( + factory: typing.Callable[ + [typing.Type[Meter]], typing.Optional[Meter]] + ) -> None: + """Set the factory to be used to create the :class:`.Meter`. + + See :mod:`opentelemetry.loader` for details. + + This function may not be called after a meter is already loaded. + + Args: + factory: Callback that should create a new :class:`.Meter` instance. + """ + global _METER_FACTORY # pylint:disable=global-statement + + if _METER: + raise RuntimeError("Meter already loaded.") + + _METER_FACTORY = factory + + +class MetricOptions: + def __init__(self, + description: str, + unit: str, + label_keys: typing.List[LabelKey], + contstant_labels: typing.Dict[LabelKey, LabelValue], + component: str, + resource: Resource) -> MetricOptions: + """Optional info used when creating a :class:`.Metric`. + + Args: + 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 + label_values: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this + Metric. + """ + self.description = description + self.unit = unit + self.label_keys = label_keys + self.label_values = label_values + self.component = component + self.resource = resource + + +class LabelKey: + + def __init__(self, + key: str, + description: str) -> LabelKey: + self.key = key + self.description = description + + +class LabelValue: + + def __init__(self, + value: str) -> LabelValue: + self.value = value + + +class MeasureOptions: + def __init__(self, + description: str, + unit: str, + measure_type: MeasureType = MeasureType.DOUBLE) -> MeasureOptions: + """Optional info used when creating a :class:`.Measure`. + + Args: + description: Human readable description of this measure. + unit: Unit of the measure values. + measure_type: Type of the measure. Can be one of two values - + `LONG` and `DOUBLE`. Default type is `DOUBLE`. + """ + self.description = description + self.unit = unit + self.measure_type = measure_type + + +class MeasureType(int): + DOUBLE = 0 + LONG = 1 + + +class RecordOptions: + + def __init__(self, + distributed_context: DistributedContext, + span_context: SpanContext) -> RecordOptions: + """Optional info used when recording :class:`.Measurement`s. + + Args: + distributed_context: Explicit :class:`.DistributedContext` to use + instead of the current context. Context is used to add dimensions + for the resulting metric calculated out of the provided + measurements. + span_context: the :class:`.SpanContext` that identified the + :class:`.Span` for which the measurements are associated with. + """ + + +class Measure: + + def __init(self, + name: str, + options: typing.Optional[RecordOptions] = None) -> Measure: + """Used to create raw :class:`.Measurement`s. + + A contract between the API exposing the raw measurement and SDK + aggregating these values into the :class:`.Metric`. Measure is + constructed from the :class:`.Meter` class by providing a set of + :class:`.MeasureOptions`. + """ + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.measure_type = options.measure_type + + def create_double_measurement(self, + value: float) -> Measurement: + """Creates a measurement that contains double values. + + Args: + value: The value of the measurement. + + Returns: + A new :class:`.Measurement` + """ + + def create_long_measurement(self, + value: long) -> Measurement: + """Creates a measurement that contains long values. + + Args: + value: The value of the measurement. + + Returns: + A new :class:`.Measurement` + """ + + +class Measurement: + """An empty interface that represents a single value. + + This single value is recorded for the :class:`.Measure` that created + this measurement. + """ + + +class Metric: + """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 + :class:`.Meter` class, by providing a set of :class:`.MetricOptions`. + """ + + def get_or_create_time_series(self, + label_values: typing.List[LabelValue]) \ + -> None: + """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 map of :class:`.LabelValue`s that will be + associated with the return timeseries. + """ + raise NotImplementedError + + def get_default_time_series(self) -> None: + """Returns a `TimeSeries`, a container for a cumulative value. + + The timeseries will have all its labels not set (default). + """ + raise NotImplementedError + + def set_call_back(self, updater_function: typing.Callable) -> None: + """Sets a callback that gets executed every time prior to exporting. + + This function MUST set the value of the :class:`.Metric` to the + value that will be exported. + + args: + updater_function: The callback function to execute. + """ + + def remove_time_series(self, + label_values: typing.List[LabelValue]) -> None: + """Removes the `TimeSeries` from the :class:`.Metric`, if it is present. + + The timeseries with matching :class:`.LabelValue`s will be removed. + + args: + label_values: The list of label values to match against. + """ + + def clear(self) -> None: + """Removes all `TimeSeries` from the :class:`.Metric`.""" + + +class CounterDouble(Metric): + + def __init__(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> CounterDouble: + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + + def get_or_create_time_series(self, + label_values: typing.List[LabelValue]) \ + -> TimeSeries: + """Gets and returns a `TimeSeries`, for a `CounterDouble` metric.""" + + def get_default_time_series(self) -> TimeSeries: + """Returns a `TimeSeries`, for a `CounterDouble` metric.""" + + + class TimeSeries: + + def add(self, value: float) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: float) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ + + +class CounterLong(Metric): + + def __init__(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> CounterLong: + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + + def get_or_create_time_series(self, + label_values: typing.List[LabelValue]) \ + -> TimeSeries: + """Gets and returns a `TimeSeries`, for a `CounterLong` metric.""" + + def get_default_time_series(self) -> 'TimeSeries': + """Returns a `TimeSeries`, for a `CounterLong` metric.""" + + + class TimeSeries: + + def add(self, value: float) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: float) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ + + +class GaugeDouble(Metric): + + def __init__(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> GaugeDouble: + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + + def get_or_create_time_series(self, + label_values: typing.List[LabelValue]) \ + -> TimeSeries: + """Gets and returns a `TimeSeries`, for a `GaugeDouble` metric.""" + + def get_default_time_series(self) -> TimeSeries: + """Returns a `TimeSeries`, for a `GaugeDouble` metric.""" + + + class TimeSeries: + + def add(self, value: float) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: float) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ + + +class GaugeLong(Metric): + + def __init__(self, + name: str, + options: typing.Optional[MetricOptions] = None) \ + -> GaugeLong: + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + + def get_or_create_time_series(self, + label_values: typing.List[LabelValue]) \ + -> TimeSeries: + """Gets and returns a `TimeSeries`, for a `GaugeLong` metric.""" + + def get_default_time_series(self) -> TimeSeries: + """Returns a `TimeSeries`, for a `GaugeLong` metric.""" + + + class TimeSeries: + + def add(self, value: float) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: float) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ From b23cec1e3bf246b99dd2873e614f6afcdbf496dd Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 30 Jul 2019 17:08:01 -0700 Subject: [PATCH 02/41] fix lint --- .../src/opentelemetry/metrics/__init__.py | 759 +++++++++--------- 1 file changed, 379 insertions(+), 380 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index a0a49c4ee7e..97b83363788 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -14,138 +14,140 @@ import typing +from opentelemetry import loader from opentelemetry.context import SpanContext from opentelemetry.distributedcontext import DistributedContext from opentelemetry.resources import Resource class Meter: - """An interface to allow the recording of measurements and metrics. + """An interface to allow the recording of measurements and metrics. - :class:`Measurement`s are used for recording raw values, in which the - aggregation and labels for the exported metric are defered. This should be - used to record measurements like "server_latency" or "received_bytes", - where the value of interest is the recorded value itself. + :class:`Measurement`s are used for recording raw values, in which the + aggregation and labels for the exported metric are defered. This should be + used to record measurements like "server_latency" or "received_bytes", + where the value of interest is the recorded value itself. - :class:`Metric`s are used for recording pre-defined aggregation, or already - aggregated data. This should be used to report metrics like cpu/memory - usage, in which the type of aggregation is already defined, or simple - metrics like "queue_length". + :class:`Metric`s are used for recording pre-defined aggregation, or already + aggregated data. This should be used to report metrics like cpu/memory + usage, in which the type of aggregation is already defined, or simple + metrics like "queue_length". - Initialization of the :class:`Meter` is done through the `meter()` function - (see below). The meter instance has a singleton implementation. - """ + Initialization of the :class:`Meter` is done through the `meter()` function + (see below). The meter instance has a singleton implementation. + """ - def create_double_counter(self, + def create_double_counter(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'CounterDouble': + """Creates a counter type metric that contains double values. + + Args: + name: The name of the counter. + options: An optional :class:`.MetricOptions` used to populate + details about the counter. + + Returns: A new :class:`.CounterDouble` + """ + + def create_long_counter(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'CounterLong': + """Creates a counter type metric that contains long values. + + Args: + name: The name of the counter. + options: An optional :class:`.MetricOptions` used to populate + details about the counter. + + Returns: + A new :class:`.CounterLong` + """ + + def create_double_gauge(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'GaugeDouble': + """Creates a gauge type metric that contains double values. + + Args: + name: The name of the gauge. + options: An optional :class:`.MetricOptions` used to populate + details about the gauge. + + Returns: + A new :class:`.GaugeDouble` + """ + + def create_long_gauge(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'GaugeLong': + """Creates a gauge type metric that contains long values. + + Args: + name: The name of the gauge. + options: An optional :class:`.MetricOptions` used to populate + details about the gauge. + + Returns: + A new :class:`.GaugeLong` + """ + + def create_measure(self, name: str, - options: typing.Optional[MetricOptions] = None) \ - -> CounterDouble: - """Creates a counter type metric that contains double values. + options: typing.Optional['MeasureOptions'] = None + ) -> 'Measure': + """Creates a Measure used to record raw :class:`.Measurement`s. - Args: - name: The name of the counter. - options: An optional :class:`.MetricOptions` used to populate - details about the counter. + Args: + name: the name of the measure + options: An optional :class:`.MeasureOptions` used to populate + details about the measure - Returns: A new :class:`.CounterDouble` - """ + Returns: + A :class:`.Measure` + """ + + def record(self, + measurements: typing.List['Measurement'], + options: typing.Optional['RecordOptions'] = None) -> None: + """A function use to record a set of :class:`.Measurement`s. + + The API is built with the idea that measurement aggregation will occur + asynchronously. Typical library records multiple measurements at once, + so this function accepts a collection of measurements so the library + can batch all of them that need to be recorded. + + Args: + measurements: The collection of measurements to record. options: + An optional :class:`.RecordOptions` used to populate details during + recording. + + Returns: None + """ - def create_long_counter(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> CounterLong: - """Creates a counter type metric that contains long values. - - Args: - name: The name of the counter. - options: An optional :class:`.MetricOptions` used to populate - details about the counter. - - Returns: - A new :class:`.CounterLong` - """ - - def create_double_gauge(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> GaugeDouble: - """Creates a gauge type metric that contains double values. - - Args: - name: The name of the gauge. - options: An optional :class:`.MetricOptions` used to populate - details about the gauge. - - Returns: - A new :class:`.GaugeDouble` - """ - - def create_long_gauge(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> GaugeLong: - """Creates a gauge type metric that contains long values. - - Args: - name: The name of the gauge. - options: An optional :class:`.MetricOptions` used to populate - details about the gauge. - - Returns: - A new :class:`.GaugeLong` - """ - - def create_measure(self, - name: str, - options: typing.Optional[MeasureOptions] = None) \ - -> Measure: - """Creates a Measure used to record raw :class:`.Measurement`s. - - Args: - name: the name of the measure - options: An optional :class:`.MeasureOptions` used to populate - details about the measure - - Returns: - A :class:`.Measure` - """ - - def record(self, - measurements: typing.List[Measurement], - options: typing.Optional[RecordOptions] = None) -> None: - """A function use to record a set of :class:`.Measurement`s. - - The API is built with the idea that measurement aggregation will occur - asynchronously. Typical library records multiple measurements at once, - so this function accepts a collection of measurements so the library - can batch all of them that need to be recorded. - - Args: - measurements: The collection of measurements to record. options: - An optional :class:`.RecordOptions` used to populate details during - recording. - - Returns: None - """ _METER: typing.Optional[Meter] = None _METER_FACTORY: typing.Optional[ - typing.Callable[[typing.Type[Meter]], typing.Optional[Meter]]] = None + typing.Callable[[typing.Type[Meter]], typing.Optional[Meter]]] = None def meter() -> Meter: - """Gets the current global :class:`.Meter` object. + """Gets the current global :class:`.Meter` object. If there isn't one set yet, a default will be loaded. """ - global _METER, _METER_FACTORY # pylint:disable=global-statement + global _METER, _METER_FACTORY # pylint:disable=global-statement - if _METER is None: + if _METER is None: # pylint:disable=protected-access - _METER = loader._load_impl(Meter, _METER_FACTORY) - del _METER_FACTORY + _METER = loader._load_impl(Meter, _METER_FACTORY) + del _METER_FACTORY - return _METER + return _METER def set_preferred_meter_implementation( @@ -169,356 +171,353 @@ def set_preferred_meter_implementation( _METER_FACTORY = factory -class MetricOptions: - def __init__(self, - description: str, - unit: str, - label_keys: typing.List[LabelKey], - contstant_labels: typing.Dict[LabelKey, LabelValue], - component: str, - resource: Resource) -> MetricOptions: - """Optional info used when creating a :class:`.Metric`. - - Args: - 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 - label_values: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this - Metric. - """ - self.description = description - self.unit = unit - self.label_keys = label_keys - self.label_values = label_values - self.component = component - self.resource = resource - - class LabelKey: - def __init__(self, - key: str, - description: str) -> LabelKey: - self.key = key - self.description = description + def __init__(self, + key: str, + description: str) -> 'LabelKey': + self.key = key + self.description = description class LabelValue: - def __init__(self, - value: str) -> LabelValue: - self.value = value + def __init__(self, + value: str) -> 'LabelValue': + self.value = value -class MeasureOptions: - def __init__(self, - description: str, - unit: str, - measure_type: MeasureType = MeasureType.DOUBLE) -> MeasureOptions: - """Optional info used when creating a :class:`.Measure`. - - Args: - description: Human readable description of this measure. - unit: Unit of the measure values. - measure_type: Type of the measure. Can be one of two values - - `LONG` and `DOUBLE`. Default type is `DOUBLE`. - """ - self.description = description - self.unit = unit - self.measure_type = measure_type +class MetricOptions: + def __init__(self, + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: typing.Dict['LabelKey', 'LabelValue'], + component: str, + resource: 'Resource') -> 'MetricOptions': + """Optional info used when creating a :class:`.Metric`. + + Args: + 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 + constant_labels: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this + Metric. + """ + self.description = description + self.unit = unit + self.label_keys = label_keys + self.constant_labels = constant_labels + self.component = component + self.resource = resource class MeasureType(int): - DOUBLE = 0 - LONG = 1 + DOUBLE = 0 + LONG = 1 + + +class MeasureOptions: + def __init__(self, + description: str, + unit: str, + measure_type: 'MeasureType' = MeasureType.DOUBLE + ) -> 'MeasureOptions': + """Optional info used when creating a :class:`.Measure`. + + Args: + description: Human readable description of this measure. + unit: Unit of the measure values. + measure_type: Type of the measure. Can be one of two values - + `LONG` and `DOUBLE`. Default type is `DOUBLE`. + """ + self.description = description + self.unit = unit + self.measure_type = measure_type class RecordOptions: - def __init__(self, - distributed_context: DistributedContext, - span_context: SpanContext) -> RecordOptions: - """Optional info used when recording :class:`.Measurement`s. - - Args: - distributed_context: Explicit :class:`.DistributedContext` to use - instead of the current context. Context is used to add dimensions - for the resulting metric calculated out of the provided - measurements. - span_context: the :class:`.SpanContext` that identified the - :class:`.Span` for which the measurements are associated with. - """ + def __init__(self, + distributed_context: 'DistributedContext', + span_context: 'SpanContext') -> 'RecordOptions': + """Optional info used when recording :class:`.Measurement`s. + Args: + distributed_context: Explicit :class:`.DistributedContext` to use + instead of the current context. Context is used to add dimensions + for the resulting metric calculated out of the provided + measurements. + span_context: the :class:`.SpanContext` that identified the + :class:`.Span` for which the measurements are associated with. + """ -class Measure: - def __init(self, - name: str, - options: typing.Optional[RecordOptions] = None) -> Measure: - """Used to create raw :class:`.Measurement`s. +class Measurement: + """An empty interface that represents a single value. + + This single value is recorded for the :class:`.Measure` that created + this measurement. + """ - A contract between the API exposing the raw measurement and SDK - aggregating these values into the :class:`.Metric`. Measure is - constructed from the :class:`.Meter` class by providing a set of - :class:`.MeasureOptions`. - """ - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.measure_type = options.measure_type - def create_double_measurement(self, - value: float) -> Measurement: - """Creates a measurement that contains double values. +class Measure: - Args: - value: The value of the measurement. + def __init(self, + name: str, + options: typing.Optional[RecordOptions] = None) -> 'Measure': + """Used to create raw :class:`.Measurement`s. - Returns: - A new :class:`.Measurement` - """ + A contract between the API exposing the raw measurement and SDK + aggregating these values into the :class:`.Metric`. Measure is + constructed from the :class:`.Meter` class by providing a set of + :class:`.MeasureOptions`. + """ + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.measure_type = options.measure_type - def create_long_measurement(self, - value: long) -> Measurement: - """Creates a measurement that contains long values. + def create_double_measurement(self, + value: float) -> 'Measurement': + """Creates a measurement that contains double values. - Args: - value: The value of the measurement. + Args: + value: The value of the measurement. - Returns: - A new :class:`.Measurement` - """ + Returns: + A new :class:`.Measurement` + """ + def create_long_measurement(self, + value: int) -> 'Measurement': + """Creates a measurement that contains long values. -class Measurement: - """An empty interface that represents a single value. + Args: + value: The value of the measurement. - This single value is recorded for the :class:`.Measure` that created - this measurement. - """ + Returns: + A new :class:`.Measurement` + """ class Metric: - """Base class for various types of metrics. + """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 - :class:`.Meter` class, by providing a set of :class:`.MetricOptions`. - """ + Metric class that inherit from this class are specialized with the type of + time series that the metric holds. Metric is constructed from the + :class:`.Meter` class, by providing a set of :class:`.MetricOptions`. + """ - def get_or_create_time_series(self, - label_values: typing.List[LabelValue]) \ - -> None: - """Gets and returns a `TimeSeries`, a container for a cumulative value. + def get_or_create_time_series(self, + label_values: typing.List['LabelValue'] + ) -> None: + """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. + 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 map of :class:`.LabelValue`s that will be - associated with the return timeseries. - """ - raise NotImplementedError + Args: + label_values: A map of :class:`.LabelValue`s that will be + associated with the return timeseries. + """ + raise NotImplementedError - def get_default_time_series(self) -> None: - """Returns a `TimeSeries`, a container for a cumulative value. + def get_default_time_series(self) -> None: + """Returns a `TimeSeries`, a container for a cumulative value. - The timeseries will have all its labels not set (default). - """ - raise NotImplementedError + The timeseries will have all its labels not set (default). + """ + raise NotImplementedError - def set_call_back(self, updater_function: typing.Callable) -> None: - """Sets a callback that gets executed every time prior to exporting. + def set_call_back(self, updater_function: typing.Callable) -> None: + """Sets a callback that gets executed every time prior to exporting. - This function MUST set the value of the :class:`.Metric` to the - value that will be exported. + This function MUST set the value of the :class:`.Metric` to the + value that will be exported. - args: - updater_function: The callback function to execute. - """ - - def remove_time_series(self, - label_values: typing.List[LabelValue]) -> None: - """Removes the `TimeSeries` from the :class:`.Metric`, if it is present. + args: + updater_function: The callback function to execute. + """ - The timeseries with matching :class:`.LabelValue`s will be removed. + def remove_time_series(self, + label_values: typing.List['LabelValue']) -> None: + """Removes the `TimeSeries` from the :class:`.Metric`, if it is present. - args: - label_values: The list of label values to match against. - """ + The timeseries with matching :class:`.LabelValue`s will be removed. - def clear(self) -> None: - """Removes all `TimeSeries` from the :class:`.Metric`.""" - + args: + label_values: The list of label values to match against. + """ -class CounterDouble(Metric): + def clear(self) -> None: + """Removes all `TimeSeries` from the :class:`.Metric`.""" - def __init__(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> CounterDouble: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.label_values = options.label_values - self.component = options.component - self.resource = options.resource - def get_or_create_time_series(self, - label_values: typing.List[LabelValue]) \ - -> TimeSeries: - """Gets and returns a `TimeSeries`, for a `CounterDouble` metric.""" +class CounterDouble(Metric): - def get_default_time_series(self) -> TimeSeries: - """Returns a `TimeSeries`, for a `CounterDouble` metric.""" + def __init__(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'CounterDouble': + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + def get_or_create_time_series(self, + label_values: typing.List['LabelValue'] + ) -> 'CounterDouble.TimeSeries': + """Gets and returns a `TimeSeries`, for a `CounterDouble` metric.""" - class TimeSeries: + def get_default_time_series(self) -> 'CounterDouble.TimeSeries': + """Returns a `TimeSeries`, for a `CounterDouble` metric.""" - def add(self, value: float) -> None: - """Adds the given value to the current value. + class TimeSeries: - The values cannot be negative. - """ + def add(self, value: float) -> None: + """Adds the given value to the current value. - def set(self, value: float) -> None: - """Sets the current value to the given value. + The values cannot be negative. + """ - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + def set(self, value: float) -> None: + """Sets the current value to the given value. + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ -class CounterLong(Metric): - def __init__(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> CounterLong: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.label_values = options.label_values - self.component = options.component - self.resource = options.resource +class CounterLong(Metric): - def get_or_create_time_series(self, - label_values: typing.List[LabelValue]) \ - -> TimeSeries: - """Gets and returns a `TimeSeries`, for a `CounterLong` metric.""" + def __init__(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'CounterLong': + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource - def get_default_time_series(self) -> 'TimeSeries': - """Returns a `TimeSeries`, for a `CounterLong` metric.""" + def get_or_create_time_series(self, + label_values: typing.List['LabelValue'] + ) -> 'CounterLong.TimeSeries': + """Gets and returns a `TimeSeries`, for a `CounterLong` metric.""" + def get_default_time_series(self) -> 'CounterLong.TimeSeries': + """Returns a `TimeSeries`, for a `CounterLong` metric.""" - class TimeSeries: + class TimeSeries: - def add(self, value: float) -> None: - """Adds the given value to the current value. + def add(self, value: float) -> None: + """Adds the given value to the current value. - The values cannot be negative. - """ + The values cannot be negative. + """ - def set(self, value: float) -> None: - """Sets the current value to the given value. + def set(self, value: float) -> None: + """Sets the current value to the given value. - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ class GaugeDouble(Metric): - def __init__(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> GaugeDouble: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.label_values = options.label_values - self.component = options.component - self.resource = options.resource - - def get_or_create_time_series(self, - label_values: typing.List[LabelValue]) \ - -> TimeSeries: - """Gets and returns a `TimeSeries`, for a `GaugeDouble` metric.""" + def __init__(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'GaugeDouble': + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource - def get_default_time_series(self) -> TimeSeries: - """Returns a `TimeSeries`, for a `GaugeDouble` metric.""" + def get_or_create_time_series(self, + label_values: typing.List['LabelValue'] + ) -> 'GaugeDouble.TimeSeries': + """Gets and returns a `TimeSeries`, for a `GaugeDouble` metric.""" + def get_default_time_series(self) -> 'GaugeDouble.TimeSeries': + """Returns a `TimeSeries`, for a `GaugeDouble` metric.""" - class TimeSeries: + class TimeSeries: - def add(self, value: float) -> None: - """Adds the given value to the current value. + def add(self, value: float) -> None: + """Adds the given value to the current value. - The values cannot be negative. - """ + The values cannot be negative. + """ - def set(self, value: float) -> None: - """Sets the current value to the given value. + def set(self, value: float) -> None: + """Sets the current value to the given value. - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ class GaugeLong(Metric): - def __init__(self, - name: str, - options: typing.Optional[MetricOptions] = None) \ - -> GaugeLong: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.label_values = options.label_values - self.component = options.component - self.resource = options.resource - - def get_or_create_time_series(self, - label_values: typing.List[LabelValue]) \ - -> TimeSeries: - """Gets and returns a `TimeSeries`, for a `GaugeLong` metric.""" - - def get_default_time_series(self) -> TimeSeries: - """Returns a `TimeSeries`, for a `GaugeLong` metric.""" - - - class TimeSeries: - - def add(self, value: float) -> None: - """Adds the given value to the current value. - - The values cannot be negative. - """ - - def set(self, value: float) -> None: - """Sets the current value to the given value. - - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + def __init__(self, + name: str, + options: typing.Optional['MetricOptions'] = None + ) -> 'GaugeLong': + self.name = name + if options: + self.description = options.description + self.unit = options.unit + self.label_keys = options.label_keys + self.label_values = options.label_values + self.component = options.component + self.resource = options.resource + + def get_or_create_time_series(self, + label_values: typing.List['LabelValue'] + ) -> 'GaugeLong.TimeSeries': + """Gets and returns a `TimeSeries`, for a `GaugeLong` metric.""" + + def get_default_time_series(self) -> 'GaugeLong.TimeSeries': + """Returns a `TimeSeries`, for a `GaugeLong` metric.""" + + class TimeSeries: + + def add(self, value: float) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: float) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ From 981eecea1ad1a1360acfa5dbf238471c5018b284 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 30 Jul 2019 17:29:42 -0700 Subject: [PATCH 03/41] Fix lint --- .../src/opentelemetry/metrics/__init__.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 97b83363788..579788034f7 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -15,7 +15,7 @@ import typing from opentelemetry import loader -from opentelemetry.context import SpanContext +from opentelemetry.trace import SpanContext from opentelemetry.distributedcontext import DistributedContext from opentelemetry.resources import Resource @@ -175,7 +175,7 @@ class LabelKey: def __init__(self, key: str, - description: str) -> 'LabelKey': + description: str) -> None: self.key = key self.description = description @@ -183,7 +183,7 @@ def __init__(self, class LabelValue: def __init__(self, - value: str) -> 'LabelValue': + value: str) -> None: self.value = value @@ -194,7 +194,7 @@ def __init__(self, label_keys: typing.List['LabelKey'], constant_labels: typing.Dict['LabelKey', 'LabelValue'], component: str, - resource: 'Resource') -> 'MetricOptions': + resource: 'Resource') -> None: """Optional info used when creating a :class:`.Metric`. Args: @@ -217,7 +217,7 @@ def __init__(self, self.resource = resource -class MeasureType(int): +class MeasureType: DOUBLE = 0 LONG = 1 @@ -227,7 +227,7 @@ def __init__(self, description: str, unit: str, measure_type: 'MeasureType' = MeasureType.DOUBLE - ) -> 'MeasureOptions': + ) -> None: """Optional info used when creating a :class:`.Measure`. Args: @@ -245,7 +245,7 @@ class RecordOptions: def __init__(self, distributed_context: 'DistributedContext', - span_context: 'SpanContext') -> 'RecordOptions': + span_context: 'SpanContext') -> None: """Optional info used when recording :class:`.Measurement`s. Args: @@ -268,9 +268,9 @@ class Measurement: class Measure: - def __init(self, - name: str, - options: typing.Optional[RecordOptions] = None) -> 'Measure': + def __init__(self, + name: str, + options: typing.Optional['MeasureOptions'] = None) -> None: """Used to create raw :class:`.Measurement`s. A contract between the API exposing the raw measurement and SDK @@ -317,7 +317,7 @@ class Metric: def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> None: + ) -> 'object': """Gets and returns a `TimeSeries`, a container for a cumulative value. If the provided label values are not already associated with this @@ -332,7 +332,7 @@ def get_or_create_time_series(self, """ raise NotImplementedError - def get_default_time_series(self) -> None: + def get_default_time_series(self) -> 'object': """Returns a `TimeSeries`, a container for a cumulative value. The timeseries will have all its labels not set (default). @@ -351,7 +351,7 @@ def set_call_back(self, updater_function: typing.Callable) -> None: def remove_time_series(self, label_values: typing.List['LabelValue']) -> None: - """Removes the `TimeSeries` from the :class:`.Metric`, if it is present. + """Removes the `TimeSeries` from the :class:`.Metric`, if present. The timeseries with matching :class:`.LabelValue`s will be removed. @@ -368,13 +368,13 @@ class CounterDouble(Metric): def __init__(self, name: str, options: typing.Optional['MetricOptions'] = None - ) -> 'CounterDouble': + ) -> None: self.name = name if options: self.description = options.description self.unit = options.unit self.label_keys = options.label_keys - self.label_values = options.label_values + self.constant_labels = options.constant_labels self.component = options.component self.resource = options.resource @@ -408,13 +408,13 @@ class CounterLong(Metric): def __init__(self, name: str, options: typing.Optional['MetricOptions'] = None - ) -> 'CounterLong': + ) -> None: self.name = name if options: self.description = options.description self.unit = options.unit self.label_keys = options.label_keys - self.label_values = options.label_values + self.constant_labels = options.constant_labels self.component = options.component self.resource = options.resource @@ -448,13 +448,13 @@ class GaugeDouble(Metric): def __init__(self, name: str, options: typing.Optional['MetricOptions'] = None - ) -> 'GaugeDouble': + ) -> None: self.name = name if options: self.description = options.description self.unit = options.unit self.label_keys = options.label_keys - self.label_values = options.label_values + self.constant_labels = options.constant_labels self.component = options.component self.resource = options.resource @@ -488,13 +488,13 @@ class GaugeLong(Metric): def __init__(self, name: str, options: typing.Optional['MetricOptions'] = None - ) -> 'GaugeLong': + ) -> None: self.name = name if options: self.description = options.description self.unit = options.unit self.label_keys = options.label_keys - self.label_values = options.label_values + self.constant_labels = options.constant_labels self.component = options.component self.resource = options.resource From 8ea9709a7774d6a41b2f0c0b0a2f8a282749fc0d Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 30 Jul 2019 17:43:05 -0700 Subject: [PATCH 04/41] fix typing --- .../src/opentelemetry/distributedcontext/__init__.py | 1 + opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py index b2f19c07443..482f81e67c9 100644 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py +++ b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # TODO class DistributedContext: pass diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 579788034f7..3ad216542e4 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -339,7 +339,7 @@ def get_default_time_series(self) -> 'object': """ raise NotImplementedError - def set_call_back(self, updater_function: typing.Callable) -> None: + def set_call_back(self, updater_function: typing.Callable[..., None]) -> None: """Sets a callback that gets executed every time prior to exporting. This function MUST set the value of the :class:`.Metric` to the From 00b4f114e70a9006e98034358557cd90a3c9dc64 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 12:38:39 -0700 Subject: [PATCH 05/41] Remove options, constructors, seperate labels --- .../src/opentelemetry/metrics/__init__.py | 395 ++++++------------ .../src/opentelemetry/metrics/label_key.py | 30 ++ .../src/opentelemetry/metrics/label_value.py | 25 ++ 3 files changed, 192 insertions(+), 258 deletions(-) create mode 100644 opentelemetry-api/src/opentelemetry/metrics/label_key.py create mode 100644 opentelemetry-api/src/opentelemetry/metrics/label_value.py diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3ad216542e4..2be7bb9c3b0 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -15,9 +15,11 @@ import typing from opentelemetry import loader -from opentelemetry.trace import SpanContext from opentelemetry.distributedcontext import DistributedContext +from opentelemetry.metrics.label_key import LabelKey +from opentelemetry.metrics.label_key import LabelValue from opentelemetry.resources import Resource +from opentelemetry.trace import SpanContext class Meter: @@ -32,35 +34,58 @@ class Meter: aggregated data. This should be used to report metrics like cpu/memory usage, in which the type of aggregation is already defined, or simple metrics like "queue_length". - - Initialization of the :class:`Meter` is done through the `meter()` function - (see below). The meter instance has a singleton implementation. """ def create_double_counter(self, name: str, - options: typing.Optional['MetricOptions'] = None + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None ) -> 'CounterDouble': """Creates a counter type metric that contains double values. Args: name: The name of the counter. - options: An optional :class:`.MetricOptions` used to populate - details about 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 + constant_labels: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this metric. Returns: A new :class:`.CounterDouble` """ def create_long_counter(self, name: str, - options: typing.Optional['MetricOptions'] = None + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None ) -> 'CounterLong': """Creates a counter type metric that contains long values. Args: name: The name of the counter. - options: An optional :class:`.MetricOptions` used to populate - details about 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 + constant_labels: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this metric. Returns: A new :class:`.CounterLong` @@ -68,14 +93,27 @@ def create_long_counter(self, def create_double_gauge(self, name: str, - options: typing.Optional['MetricOptions'] = None + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None ) -> 'GaugeDouble': """Creates a gauge type metric that contains double values. Args: name: The name of the gauge. - options: An optional :class:`.MetricOptions` used to populate - details about the gauge. + 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 + constant_labels: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this metric. Returns: A new :class:`.GaugeDouble` @@ -83,14 +121,27 @@ def create_double_gauge(self, def create_long_gauge(self, name: str, - options: typing.Optional['MetricOptions'] = None + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None ) -> 'GaugeLong': """Creates a gauge type metric that contains long values. Args: name: The name of the gauge. - options: An optional :class:`.MetricOptions` used to populate - details about the gauge. + 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 + constant_labels: A map of constant labels that will be used for + all of the TimeSeries created from the Metric. + component: The name of the component that reports this metric. + Resource: Sets the :class:`.Resource` associated with this metric. Returns: A new :class:`.GaugeLong` @@ -98,14 +149,18 @@ def create_long_gauge(self, def create_measure(self, name: str, - options: typing.Optional['MeasureOptions'] = None + description: str, + unit: str, + measure_type: 'MeasureType' = MeasureType.DOUBLE ) -> 'Measure': """Creates a Measure used to record raw :class:`.Measurement`s. Args: name: the name of the measure - options: An optional :class:`.MeasureOptions` used to populate - details about the measure + description: Human readable description of this measure. + unit: Unit of the measure values. + measure_type: Type of the measure. Can be one of two values - + `LONG` and `DOUBLE`. Default type is `DOUBLE`. Returns: A :class:`.Measure` @@ -113,8 +168,9 @@ def create_measure(self, def record(self, measurements: typing.List['Measurement'], - options: typing.Optional['RecordOptions'] = None) -> None: - """A function use to record a set of :class:`.Measurement`s. + span_context: 'SpanContext' = None + ) -> None: + """Records a set of `Measurement`s. The API is built with the idea that measurement aggregation will occur asynchronously. Typical library records multiple measurements at once, @@ -122,140 +178,17 @@ def record(self, can batch all of them that need to be recorded. Args: - measurements: The collection of measurements to record. options: - An optional :class:`.RecordOptions` used to populate details during - recording. + measurements: The collection of measurements to record. + span_context: the :class:`.SpanContext` that identified the + :class:`.Span` for which the measurements are associated with. Returns: None """ -_METER: typing.Optional[Meter] = None -_METER_FACTORY: typing.Optional[ - typing.Callable[[typing.Type[Meter]], typing.Optional[Meter]]] = None - - -def meter() -> Meter: - """Gets the current global :class:`.Meter` object. - - If there isn't one set yet, a default will be loaded. - """ - global _METER, _METER_FACTORY # pylint:disable=global-statement - - if _METER is None: - # pylint:disable=protected-access - _METER = loader._load_impl(Meter, _METER_FACTORY) - del _METER_FACTORY - - return _METER - - -def set_preferred_meter_implementation( - factory: typing.Callable[ - [typing.Type[Meter]], typing.Optional[Meter]] - ) -> None: - """Set the factory to be used to create the :class:`.Meter`. - - See :mod:`opentelemetry.loader` for details. - - This function may not be called after a meter is already loaded. - - Args: - factory: Callback that should create a new :class:`.Meter` instance. - """ - global _METER_FACTORY # pylint:disable=global-statement - - if _METER: - raise RuntimeError("Meter already loaded.") - - _METER_FACTORY = factory - - -class LabelKey: - - def __init__(self, - key: str, - description: str) -> None: - self.key = key - self.description = description - - -class LabelValue: - - def __init__(self, - value: str) -> None: - self.value = value - - -class MetricOptions: - def __init__(self, - description: str, - unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: typing.Dict['LabelKey', 'LabelValue'], - component: str, - resource: 'Resource') -> None: - """Optional info used when creating a :class:`.Metric`. - - Args: - 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 - constant_labels: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this - Metric. - """ - self.description = description - self.unit = unit - self.label_keys = label_keys - self.constant_labels = constant_labels - self.component = component - self.resource = resource - - class MeasureType: - DOUBLE = 0 - LONG = 1 - - -class MeasureOptions: - def __init__(self, - description: str, - unit: str, - measure_type: 'MeasureType' = MeasureType.DOUBLE - ) -> None: - """Optional info used when creating a :class:`.Measure`. - - Args: - description: Human readable description of this measure. - unit: Unit of the measure values. - measure_type: Type of the measure. Can be one of two values - - `LONG` and `DOUBLE`. Default type is `DOUBLE`. - """ - self.description = description - self.unit = unit - self.measure_type = measure_type - - -class RecordOptions: - - def __init__(self, - distributed_context: 'DistributedContext', - span_context: 'SpanContext') -> None: - """Optional info used when recording :class:`.Measurement`s. - - Args: - distributed_context: Explicit :class:`.DistributedContext` to use - instead of the current context. Context is used to add dimensions - for the resulting metric calculated out of the provided - measurements. - span_context: the :class:`.SpanContext` that identified the - :class:`.Span` for which the measurements are associated with. - """ + FLOAT = 0 + INT = 1 class Measurement: @@ -267,26 +200,16 @@ class Measurement: class Measure: + """Used to create raw :class:`.Measurement`s. - def __init__(self, - name: str, - options: typing.Optional['MeasureOptions'] = None) -> None: - """Used to create raw :class:`.Measurement`s. - - A contract between the API exposing the raw measurement and SDK - aggregating these values into the :class:`.Metric`. Measure is - constructed from the :class:`.Meter` class by providing a set of - :class:`.MeasureOptions`. - """ - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.measure_type = options.measure_type + A contract between the API exposing the raw measurement and SDK + aggregating these values into the :class:`.Metric`. Measure is + constructed from the :class:`.Meter` class. + """ - def create_double_measurement(self, - value: float) -> 'Measurement': - """Creates a measurement that contains double values. + def create_float_measurement(self, + value: float) -> 'Measurement': + """Creates a measurement that contains float values. Args: value: The value of the measurement. @@ -295,9 +218,9 @@ def create_double_measurement(self, A new :class:`.Measurement` """ - def create_long_measurement(self, + def create_int_measurement(self, value: int) -> 'Measurement': - """Creates a measurement that contains long values. + """Creates a measurement that contains int values. Args: value: The value of the measurement. @@ -363,28 +286,20 @@ def clear(self) -> None: """Removes all `TimeSeries` from the :class:`.Metric`.""" -class CounterDouble(Metric): - - def __init__(self, - name: str, - options: typing.Optional['MetricOptions'] = None - ) -> None: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.constant_labels = options.constant_labels - self.component = options.component - self.resource = options.resource +class CounterFloat(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: typing.List['LabelValue'] - ) -> 'CounterDouble.TimeSeries': - """Gets and returns a `TimeSeries`, for a `CounterDouble` metric.""" + ) -> 'CounterFloat.TimeSeries': + """Gets and returns a `TimeSeries`, for a `CounterFloat` metric.""" - def get_default_time_series(self) -> 'CounterDouble.TimeSeries': - """Returns a `TimeSeries`, for a `CounterDouble` metric.""" + def get_default_time_series(self) -> 'CounterFloat.TimeSeries': + """Returns a `TimeSeries`, for a `CounterFloat` metric.""" class TimeSeries: @@ -403,38 +318,30 @@ def set(self, value: float) -> None: """ -class CounterLong(Metric): - - def __init__(self, - name: str, - options: typing.Optional['MetricOptions'] = None - ) -> None: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.constant_labels = options.constant_labels - self.component = options.component - self.resource = options.resource +class CounterInt(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: typing.List['LabelValue'] - ) -> 'CounterLong.TimeSeries': - """Gets and returns a `TimeSeries`, for a `CounterLong` metric.""" + ) -> 'CounterInt.TimeSeries': + """Gets and returns a `TimeSeries`, for a `CounterInt` metric.""" - def get_default_time_series(self) -> 'CounterLong.TimeSeries': - """Returns a `TimeSeries`, for a `CounterLong` metric.""" + def get_default_time_series(self) -> 'CounterInt.TimeSeries': + """Returns a `TimeSeries`, for a `CounterInt` metric.""" class TimeSeries: - def add(self, value: float) -> None: + def add(self, value: int) -> None: """Adds the given value to the current value. The values cannot be negative. """ - def set(self, value: float) -> None: + def set(self, value: int) -> None: """Sets the current value to the given value. The given value must be larger than the current recorded value. In @@ -443,81 +350,53 @@ def set(self, value: float) -> None: """ -class GaugeDouble(Metric): - - def __init__(self, - name: str, - options: typing.Optional['MetricOptions'] = None - ) -> None: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.constant_labels = options.constant_labels - self.component = options.component - self.resource = options.resource +class GaugeFloat(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: typing.List['LabelValue'] - ) -> 'GaugeDouble.TimeSeries': - """Gets and returns a `TimeSeries`, for a `GaugeDouble` metric.""" + ) -> 'GaugeFloat.TimeSeries': + """Gets and returns a `TimeSeries`, for a `GaugeFloat` metric.""" - def get_default_time_series(self) -> 'GaugeDouble.TimeSeries': - """Returns a `TimeSeries`, for a `GaugeDouble` metric.""" + def get_default_time_series(self) -> 'GaugeFloat.TimeSeries': + """Returns a `TimeSeries`, for a `GaugeFloat` metric.""" class TimeSeries: def add(self, value: float) -> None: """Adds the given value to the current value. - The values cannot be negative. + The values can be negative. """ def set(self, value: float) -> None: - """Sets the current value to the given value. + """Sets the current value to the given value.""" - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ +class GaugeInt(Metric): + """A gauge type metric that holds int values. -class GaugeLong(Metric): - - def __init__(self, - name: str, - options: typing.Optional['MetricOptions'] = None - ) -> None: - self.name = name - if options: - self.description = options.description - self.unit = options.unit - self.label_keys = options.label_keys - self.constant_labels = options.constant_labels - self.component = options.component - self.resource = options.resource + Cumulative value can go both up and down. Values can be negative. + """ def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> 'GaugeLong.TimeSeries': - """Gets and returns a `TimeSeries`, for a `GaugeLong` metric.""" + ) -> 'GaugeInt.TimeSeries': + """Gets and returns a `TimeSeries`, for a `GaugeInt` metric.""" - def get_default_time_series(self) -> 'GaugeLong.TimeSeries': - """Returns a `TimeSeries`, for a `GaugeLong` metric.""" + def get_default_time_series(self) -> 'GaugeInt.TimeSeries': + """Returns a `TimeSeries`, for a `GaugeInt` metric.""" class TimeSeries: - def add(self, value: float) -> None: + def add(self, value: int) -> None: """Adds the given value to the current value. - The values cannot be negative. + The values can be negative. """ - def set(self, value: float) -> None: - """Sets the current value to the given value. - - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + def set(self, value: int) -> None: + """Sets the current value to the given value.""" diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_key.py b/opentelemetry-api/src/opentelemetry/metrics/label_key.py new file mode 100644 index 00000000000..baa5618aa80 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/label_key.py @@ -0,0 +1,30 @@ +# 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. + + +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 + diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_value.py b/opentelemetry-api/src/opentelemetry/metrics/label_value.py new file mode 100644 index 00000000000..0006129f046 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/label_value.py @@ -0,0 +1,25 @@ +# 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. + + +class LabelValue(object): + """The label values associated with a TimeSeries. + + :type value: str + :param value: the value for the label + """ + def __init__(self, + value: str) -> None: + self.value = value + From 34c87ce9bc42f7142d399f140c648220296748f3 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 13:07:50 -0700 Subject: [PATCH 06/41] Consistent naming for float and int --- .../src/opentelemetry/metrics/__init__.py | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 2be7bb9c3b0..363a7ce30bc 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -36,7 +36,7 @@ class Meter: metrics like "queue_length". """ - def create_double_counter(self, + def create_float_counter(self, name: str, description: str, unit: str, @@ -45,8 +45,8 @@ def create_double_counter(self, typing.Dict['LabelKey', 'LabelValue'] = None, component: str = None, resource: 'Resource' = None - ) -> 'CounterDouble': - """Creates a counter type metric that contains double values. + ) -> 'CounterFloat': + """Creates a counter type metric that contains float values. Args: name: The name of the counter. @@ -60,10 +60,10 @@ def create_double_counter(self, component: The name of the component that reports this metric. Resource: Sets the :class:`.Resource` associated with this metric. - Returns: A new :class:`.CounterDouble` + Returns: A new :class:`.CounterFloat` """ - def create_long_counter(self, + def create_int_counter(self, name: str, description: str, unit: str, @@ -72,8 +72,8 @@ def create_long_counter(self, typing.Dict['LabelKey', 'LabelValue'] = None, component: str = None, resource: 'Resource' = None - ) -> 'CounterLong': - """Creates a counter type metric that contains long values. + ) -> 'CounterInt': + """Creates a counter type metric that contains int values. Args: name: The name of the counter. @@ -88,10 +88,10 @@ def create_long_counter(self, Resource: Sets the :class:`.Resource` associated with this metric. Returns: - A new :class:`.CounterLong` + A new :class:`.CounterInt` """ - def create_double_gauge(self, + def create_float_gauge(self, name: str, description: str, unit: str, @@ -100,8 +100,8 @@ def create_double_gauge(self, typing.Dict['LabelKey', 'LabelValue'] = None, component: str = None, resource: 'Resource' = None - ) -> 'GaugeDouble': - """Creates a gauge type metric that contains double values. + ) -> 'GaugeFloat': + """Creates a gauge type metric that contains float values. Args: name: The name of the gauge. @@ -116,10 +116,10 @@ def create_double_gauge(self, Resource: Sets the :class:`.Resource` associated with this metric. Returns: - A new :class:`.GaugeDouble` + A new :class:`.GaugeFloat` """ - def create_long_gauge(self, + def create_int_gauge(self, name: str, description: str, unit: str, @@ -128,8 +128,8 @@ def create_long_gauge(self, typing.Dict['LabelKey', 'LabelValue'] = None, component: str = None, resource: 'Resource' = None - ) -> 'GaugeLong': - """Creates a gauge type metric that contains long values. + ) -> 'GaugeInt': + """Creates a gauge type metric that contains int values. Args: name: The name of the gauge. @@ -144,7 +144,7 @@ def create_long_gauge(self, Resource: Sets the :class:`.Resource` associated with this metric. Returns: - A new :class:`.GaugeLong` + A new :class:`.GaugeInt` """ def create_measure(self, From df8ae342de92c06bb1a11b45415006d3bf44b81b Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 13:48:50 -0700 Subject: [PATCH 07/41] Abstract time series --- .../src/opentelemetry/metrics/__init__.py | 116 +++++------------- .../src/opentelemetry/metrics/time_series.py | 44 +++++++ 2 files changed, 77 insertions(+), 83 deletions(-) create mode 100644 opentelemetry-api/src/opentelemetry/metrics/time_series.py diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 363a7ce30bc..22b7304f070 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -12,12 +12,27 @@ # 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 :class:`.Meter` class is used to construct ::class`.Measure`s to +record raw measurements and :class`.Metric`s to record metrics with +predefined aggregation. + +See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-metrics.md +for the specifications. + + +""" + import typing from opentelemetry import loader from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics.label_key import LabelKey from opentelemetry.metrics.label_key import LabelValue +from opentelemetry.metrics.time_series import CounterTimeSeries from opentelemetry.resources import Resource from opentelemetry.trace import SpanContext @@ -207,8 +222,8 @@ class Measure: constructed from the :class:`.Meter` class. """ - def create_float_measurement(self, - value: float) -> 'Measurement': + def create_measurement(self, + value: typing.Union[float, int]) -> 'Measurement': """Creates a measurement that contains float values. Args: @@ -218,17 +233,6 @@ def create_float_measurement(self, A new :class:`.Measurement` """ - def create_int_measurement(self, - value: int) -> 'Measurement': - """Creates a measurement that contains int values. - - Args: - value: The value of the measurement. - - Returns: - A new :class:`.Measurement` - """ - class Metric: """Base class for various types of metrics. @@ -295,27 +299,11 @@ class CounterFloat(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> 'CounterFloat.TimeSeries': - """Gets and returns a `TimeSeries`, for a `CounterFloat` metric.""" - - def get_default_time_series(self) -> 'CounterFloat.TimeSeries': - """Returns a `TimeSeries`, for a `CounterFloat` metric.""" - - class TimeSeries: - - def add(self, value: float) -> None: - """Adds the given value to the current value. + ) -> 'CounterTimeSeries': + """Gets a `CounterTimeSeries' with a cumulated float value.""" - The values cannot be negative. - """ - - def set(self, value: float) -> None: - """Sets the current value to the given value. - - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + def get_default_time_series(self) -> 'CounterTimeSeries': + """Returns a `CounterTimeSeries' with a cumulated float value.""" class CounterInt(Metric): @@ -327,28 +315,11 @@ class CounterInt(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> 'CounterInt.TimeSeries': - """Gets and returns a `TimeSeries`, for a `CounterInt` metric.""" - - def get_default_time_series(self) -> 'CounterInt.TimeSeries': - """Returns a `TimeSeries`, for a `CounterInt` metric.""" - - class TimeSeries: - - def add(self, value: int) -> None: - """Adds the given value to the current value. - - The values cannot be negative. - """ - - def set(self, value: int) -> None: - """Sets the current value to the given value. - - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. - """ + ) -> 'CounterTimeSeries': + """Gets a `CounterTimeSeries' with a cumulated int value.""" + def get_default_time_series(self) -> 'CounterTimeSeries': + """Returns a `CounterTimeSeries' with a cumulated int value.""" class GaugeFloat(Metric): """A gauge type metric that holds float values. @@ -358,22 +329,11 @@ class GaugeFloat(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> 'GaugeFloat.TimeSeries': - """Gets and returns a `TimeSeries`, for a `GaugeFloat` metric.""" + ) -> 'GaugeTimeSeries': + """Gets a `GaugeTimeSeries` with a cumulated float value.""" - def get_default_time_series(self) -> 'GaugeFloat.TimeSeries': - """Returns a `TimeSeries`, for a `GaugeFloat` metric.""" - - class TimeSeries: - - def add(self, value: float) -> None: - """Adds the given value to the current value. - - The values can be negative. - """ - - def set(self, value: float) -> None: - """Sets the current value to the given value.""" + def get_default_time_series(self) -> 'GaugeTimeSeries': + """Returns a `GaugeTimeSeries` with a cumulated float value.""" class GaugeInt(Metric): @@ -384,19 +344,9 @@ class GaugeInt(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] - ) -> 'GaugeInt.TimeSeries': - """Gets and returns a `TimeSeries`, for a `GaugeInt` metric.""" - - def get_default_time_series(self) -> 'GaugeInt.TimeSeries': - """Returns a `TimeSeries`, for a `GaugeInt` metric.""" - - class TimeSeries: - - def add(self, value: int) -> None: - """Adds the given value to the current value. + ) -> 'GaugeTimeSeries': + """Gets a `GaugeTimeSeries` with a cumulated int value.""" - The values can be negative. - """ + def get_default_time_series(self) -> 'GaugeTimeSeries': + """Returns a `GaugeTimeSeries with a cumulated int value.""" - def set(self, value: int) -> None: - """Sets the current value to the given value.""" diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py new file mode 100644 index 00000000000..1a294543761 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -0,0 +1,44 @@ +# 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. + +import typing + + +class CounterTimeSeries: + + def add(self, value: typing.Union[float, int]) -> None: + """Adds the given value to the current value. + + The values cannot be negative. + """ + + def set(self, value: typing.Union[float, int]) -> None: + """Sets the current value to the given value. + + The given value must be larger than the current recorded value. In + general should be used in combination with `SetCallback` where the + recorded value is guaranteed to be monotonically increasing. + """ + + +class GaugeTimeSeries: + + def add(self, value: typing.Union[float, int]) -> None: + """Adds the given value to the current value. + + The values can be negative. + """ + + def set(self, value: typing.Union[float, int]) -> None: + """Sets the current value to the given value.""" From a2561acdc85c67c46ec31c6afca648140e948917 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 15:19:36 -0700 Subject: [PATCH 08/41] Use ABC --- .../src/opentelemetry/metrics/__init__.py | 87 ++++++++++--------- 1 file changed, 44 insertions(+), 43 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 22b7304f070..95fd8533e92 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -23,9 +23,9 @@ See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-metrics.md for the specifications. - """ +import abc import typing from opentelemetry import loader @@ -52,15 +52,15 @@ class Meter: """ def create_float_counter(self, - name: str, - description: str, - unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None - ) -> 'CounterFloat': + name: str, + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None + ) -> 'CounterFloat': """Creates a counter type metric that contains float values. Args: @@ -79,15 +79,15 @@ def create_float_counter(self, """ def create_int_counter(self, - name: str, - description: str, - unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None - ) -> 'CounterInt': + name: str, + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None + ) -> 'CounterInt': """Creates a counter type metric that contains int values. Args: @@ -107,15 +107,15 @@ def create_int_counter(self, """ def create_float_gauge(self, - name: str, - description: str, - unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None - ) -> 'GaugeFloat': + name: str, + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + comonent: str = None, + resource: 'Resource' = None + ) -> 'GaugeFloat': """Creates a gauge type metric that contains float values. Args: @@ -135,15 +135,15 @@ def create_float_gauge(self, """ def create_int_gauge(self, - name: str, - description: str, - unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None - ) -> 'GaugeInt': + name: str, + description: str, + unit: str, + label_keys: typing.List['LabelKey'], + constant_labels: \ + typing.Dict['LabelKey', 'LabelValue'] = None, + component: str = None, + resource: 'Resource' = None + ) -> 'GaugeInt': """Creates a gauge type metric that contains int values. Args: @@ -166,7 +166,7 @@ def create_measure(self, name: str, description: str, unit: str, - measure_type: 'MeasureType' = MeasureType.DOUBLE + measure_type: 'MeasureType', ) -> 'Measure': """Creates a Measure used to record raw :class:`.Measurement`s. @@ -175,7 +175,7 @@ def create_measure(self, description: Human readable description of this measure. unit: Unit of the measure values. measure_type: Type of the measure. Can be one of two values - - `LONG` and `DOUBLE`. Default type is `DOUBLE`. + `FLOAT` and `INT`. Default type is `FLOAT`. Returns: A :class:`.Measure` @@ -183,6 +183,7 @@ def create_measure(self, def record(self, measurements: typing.List['Measurement'], + distributed_context = 'DistributedContext' = None span_context: 'SpanContext' = None ) -> None: """Records a set of `Measurement`s. @@ -224,7 +225,7 @@ class Measure: def create_measurement(self, value: typing.Union[float, int]) -> 'Measurement': - """Creates a measurement that contains float values. + """Creates a measurement with type corresponding to the `measure`'s type. Args: value: The value of the measurement. @@ -234,7 +235,7 @@ def create_measurement(self, """ -class Metric: +class Metric(abc.ABC): """Base class for various types of metrics. Metric class that inherit from this class are specialized with the type of @@ -242,6 +243,7 @@ class Metric: :class:`.Meter` class, by providing a set of :class:`.MetricOptions`. """ + @abc.abstractmethod def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'object': @@ -257,14 +259,13 @@ def get_or_create_time_series(self, label_values: A map of :class:`.LabelValue`s that will be associated with the return timeseries. """ - raise NotImplementedError + @abc.abstractmethod def get_default_time_series(self) -> 'object': """Returns a `TimeSeries`, a container for a cumulative value. The timeseries will have all its labels not set (default). """ - raise NotImplementedError def set_call_back(self, updater_function: typing.Callable[..., None]) -> None: """Sets a callback that gets executed every time prior to exporting. From 1ece493e8fdc18af63cb016e822943fd9c5dc3d7 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 15:22:06 -0700 Subject: [PATCH 09/41] Fix typo --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 95fd8533e92..b13a9ce5240 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -183,7 +183,7 @@ def create_measure(self, def record(self, measurements: typing.List['Measurement'], - distributed_context = 'DistributedContext' = None + distributed_context: 'DistributedContext' = None, span_context: 'SpanContext' = None ) -> None: """Records a set of `Measurement`s. From ce9268a6a4b4f2bc770422352603e7fa1b9b602d Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 6 Aug 2019 16:13:53 -0700 Subject: [PATCH 10/41] Fix docs --- .../src/opentelemetry/metrics/__init__.py | 98 ++++++++++--------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index b13a9ce5240..4ec648bcd34 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -16,23 +16,26 @@ The OpenTelemetry metrics API describes the classes used to report raw measurements, as well as metrics with known aggregation and labels. -The :class:`.Meter` class is used to construct ::class`.Measure`s to -record raw measurements and :class`.Metric`s to record metrics with +The :class:`.Meter` class is used to construct :class:`.Measure` s to +record raw measurements and :class:`.Metric` s to record metrics with predefined aggregation. -See https://github.com/open-telemetry/opentelemetry-specification/blob/master/specification/api-metrics.md -for the specifications. +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 + """ import abc import typing -from opentelemetry import loader from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics.label_key import LabelKey -from opentelemetry.metrics.label_key import LabelValue +from opentelemetry.metrics.label_value import LabelValue from opentelemetry.metrics.time_series import CounterTimeSeries +from opentelemetry.metrics.time_series import GaugeTimeSeries from opentelemetry.resources import Resource from opentelemetry.trace import SpanContext @@ -40,12 +43,12 @@ class Meter: """An interface to allow the recording of measurements and metrics. - :class:`Measurement`s are used for recording raw values, in which the + :class:`.Measurement` s are used for recording raw values, in which the aggregation and labels for the exported metric are defered. This should be used to record measurements like "server_latency" or "received_bytes", where the value of interest is the recorded value itself. - :class:`Metric`s are used for recording pre-defined aggregation, or already + :class:`.Metric` s are used for recording pre-defined aggregation, or already aggregated data. This should be used to report metrics like cpu/memory usage, in which the type of aggregation is already defined, or simple metrics like "queue_length". @@ -67,11 +70,11 @@ def create_float_counter(self, 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 + 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 - constant_labels: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. + constant_labels: A map of constant labels that will be used for \ + all of the TimeSeries created from the Metric. \ component: The name of the component that reports this metric. Resource: Sets the :class:`.Resource` associated with this metric. @@ -94,11 +97,11 @@ def create_int_counter(self, 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 + 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 - constant_labels: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. + constant_labels: A map of constant labels that will be used for \ + all of the TimeSeries created from the Metric. \ component: The name of the component that reports this metric. Resource: Sets the :class:`.Resource` associated with this metric. @@ -119,14 +122,14 @@ def create_float_gauge(self, """Creates a gauge type metric that contains float values. Args: - name: The name of the gauge. + 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 + 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 - constant_labels: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. + constant_labels: A map of constant labels that will be used for \ + all of the TimeSeries created from the Metric. \ component: The name of the component that reports this metric. Resource: Sets the :class:`.Resource` associated with this metric. @@ -147,14 +150,14 @@ def create_int_gauge(self, """Creates a gauge type metric that contains int values. Args: - name: The name of the gauge. + 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 + 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 - constant_labels: A map of constant labels that will be used for - all of the TimeSeries created from the Metric. + constant_labels: A map of constant labels that will be used for \ + all of the TimeSeries created from the Metric. \ component: The name of the component that reports this metric. Resource: Sets the :class:`.Resource` associated with this metric. @@ -168,13 +171,13 @@ def create_measure(self, unit: str, measure_type: 'MeasureType', ) -> 'Measure': - """Creates a Measure used to record raw :class:`.Measurement`s. + """Creates a Measure used to record raw :class:`.Measurement` s. Args: name: the name of the measure description: Human readable description of this measure. unit: Unit of the measure values. - measure_type: Type of the measure. Can be one of two values - + measure_type: Type of the measure. Can be one of two values - \ `FLOAT` and `INT`. Default type is `FLOAT`. Returns: @@ -186,7 +189,7 @@ def record(self, distributed_context: 'DistributedContext' = None, span_context: 'SpanContext' = None ) -> None: - """Records a set of `Measurement`s. + """Records a set of :class:`.Measurement` s. The API is built with the idea that measurement aggregation will occur asynchronously. Typical library records multiple measurements at once, @@ -216,7 +219,7 @@ class Measurement: class Measure: - """Used to create raw :class:`.Measurement`s. + """Used to create raw :class:`.Measurement` s. A contract between the API exposing the raw measurement and SDK aggregating these values into the :class:`.Metric`. Measure is @@ -224,8 +227,9 @@ class Measure: """ def create_measurement(self, - value: typing.Union[float, int]) -> 'Measurement': - """Creates a measurement with type corresponding to the `measure`'s type. + value: typing.Union[float, int] + ) -> 'Measurement': + """Creates a measurement with type corresponding to the measure's type. Args: value: The value of the measurement. @@ -240,14 +244,14 @@ class Metric(abc.ABC): Metric class that inherit from this class are specialized with the type of time series that the metric holds. Metric is constructed from the - :class:`.Meter` class, by providing a set of :class:`.MetricOptions`. + :class:`.Meter` class. """ @abc.abstractmethod def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'object': - """Gets and returns a `TimeSeries`, a container for a cumulative value. + """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 @@ -256,13 +260,13 @@ def get_or_create_time_series(self, overrides this function. Args: - label_values: A map of :class:`.LabelValue`s that will be + label_values: A map of :class:`.LabelValue` s that will be \ associated with the return timeseries. """ @abc.abstractmethod def get_default_time_series(self) -> 'object': - """Returns a `TimeSeries`, a container for a cumulative value. + """Returns a timeseries, a container for a cumulative value. The timeseries will have all its labels not set (default). """ @@ -279,16 +283,16 @@ def set_call_back(self, updater_function: typing.Callable[..., None]) -> None: def remove_time_series(self, label_values: typing.List['LabelValue']) -> None: - """Removes the `TimeSeries` from the :class:`.Metric`, if present. + """Removes the timeseries from the :class:`.Metric`, if present. - The timeseries with matching :class:`.LabelValue`s will be removed. + The timeseries with matching :class:`.LabelValue` s will be removed. args: label_values: The list of label values to match against. """ def clear(self) -> None: - """Removes all `TimeSeries` from the :class:`.Metric`.""" + """Removes all timeseries from the :class:`.Metric`.""" class CounterFloat(Metric): @@ -301,10 +305,10 @@ class CounterFloat(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'CounterTimeSeries': - """Gets a `CounterTimeSeries' with a cumulated float value.""" + """Gets a :class:`.CounterTimeSeries` with a cumulated float value.""" def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a `CounterTimeSeries' with a cumulated float value.""" + """Returns a :class:`.CounterTimeSeries` with a cumulated float value.""" class CounterInt(Metric): @@ -317,10 +321,10 @@ class CounterInt(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'CounterTimeSeries': - """Gets a `CounterTimeSeries' with a cumulated int value.""" + """Gets a :class:`.CounterTimeSeries` with a cumulated int value.""" def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a `CounterTimeSeries' with a cumulated int value.""" + """Returns a :class:`.CounterTimeSeries` with a cumulated int value.""" class GaugeFloat(Metric): """A gauge type metric that holds float values. @@ -331,10 +335,10 @@ class GaugeFloat(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'GaugeTimeSeries': - """Gets a `GaugeTimeSeries` with a cumulated float value.""" + """Gets a :class:`.GaugeTimeSeries` with a cumulated float value.""" def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a `GaugeTimeSeries` with a cumulated float value.""" + """Returns a :class:`.GaugeTimeSeries` with a cumulated float value.""" class GaugeInt(Metric): @@ -346,8 +350,8 @@ class GaugeInt(Metric): def get_or_create_time_series(self, label_values: typing.List['LabelValue'] ) -> 'GaugeTimeSeries': - """Gets a `GaugeTimeSeries` with a cumulated int value.""" + """Gets a :class:`.GaugeTimeSeries` with a cumulated int value.""" def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a `GaugeTimeSeries with a cumulated int value.""" + """Returns a :class:`.GaugeTimeSeries` with a cumulated int value.""" From f5f9f016f3c1255426453d9d3a0f5f3a95b8eb64 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 7 Aug 2019 21:51:08 -0700 Subject: [PATCH 11/41] seperate measure classes --- .../src/opentelemetry/metrics/__init__.py | 89 +++++++++++++++---- 1 file changed, 70 insertions(+), 19 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 4ec648bcd34..539c16de3f7 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -165,23 +165,38 @@ def create_int_gauge(self, A new :class:`.GaugeInt` """ - def create_measure(self, - name: str, - description: str, - unit: str, - measure_type: 'MeasureType', - ) -> 'Measure': - """Creates a Measure used to record raw :class:`.Measurement` s. + def create_int_measure(self, + name: str, + description: str, + unit: str + ) -> 'IntMeasure': + """Creates a measure used to record raw :class:`.Measurement` s. + The measurements created from this measure will have type INT. Args: name: the name of the measure description: Human readable description of this measure. unit: Unit of the measure values. - measure_type: Type of the measure. Can be one of two values - \ - `FLOAT` and `INT`. Default type is `FLOAT`. Returns: - A :class:`.Measure` + A :class:`.IntMeasure` + """ + + def create_float_measure(self, + name: str, + description: str, + unit: str + ) -> 'FloatMeasure': + """Creates a Measure used to record raw :class:`.Measurement` s. + The measurements created from this measure will have type INT. + + Args: + name: the name of the measure + description: Human readable description of this measure. + unit: Unit of the measure values. + + Returns: + A :class:`.FloatMeasure` """ def record(self, @@ -205,11 +220,6 @@ def record(self, """ -class MeasureType: - FLOAT = 0 - INT = 1 - - class Measurement: """An empty interface that represents a single value. @@ -218,24 +228,65 @@ class Measurement: """ -class Measure: +class FloatMeasurement(Measurement): + """A :class:`.Measurement` with an INT value.""" + + +class IntMeasurement(Measurement): + """A :class:`.Measurement` with an INT value.""" + + +class Measure(abc.ABC): """Used to create raw :class:`.Measurement` s. A contract between the API exposing the raw measurement and SDK aggregating these values into the :class:`.Metric`. Measure is constructed from the :class:`.Meter` class. """ - + @abc.abstractmethod def create_measurement(self, value: typing.Union[float, int] ) -> 'Measurement': - """Creates a measurement with type corresponding to the measure's type. + """Creates a measurement. + + The type of the value in the measurement will correspond to the type + of measure that overrides this method. + + Args: + value: The value of the measurement. + + Returns: + A new :class:`.Measurement` + """ + +class FloatMeasure(Measure): + """Used to create raw :class:`.FloatMeasurement` s.""" + + def create_measurement(self, + value: int, + ) -> 'FloatMeasurement': + """Creates a measurement with a FLOAT type. + + Args: + value: The value of the measurement. + + Returns: + A new :class:`.FloatMeasurement` + """ + +class IntMeasure(Measure): + """Used to create raw :class:`.IntMeasurement` s.""" + + def create_measurement(self, + value: int, + ) -> 'IntMeasurement': + """Creates a measurement with an INT type. Args: value: The value of the measurement. Returns: - A new :class:`.Measurement` + A new :class:`.IntMeasurement` """ From 74a181537dbab71bcf127ba80703903d532f4860 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 7 Aug 2019 22:01:59 -0700 Subject: [PATCH 12/41] Add examples --- .../metrics/examples/aggregated.py | 25 ++++++++++++++++ .../metrics/examples/pre_aggregated.py | 27 +++++++++++++++++ .../src/opentelemetry/metrics/examples/raw.py | 29 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py create mode 100644 opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py create mode 100644 opentelemetry-api/src/opentelemetry/metrics/examples/raw.py diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py new file mode 100644 index 00000000000..0103e9f2d7f --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py @@ -0,0 +1,25 @@ +# 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. + +import psutil + +from opentelemetry.distributedcontext import DistributedContext +from opentelemetry.metrics import Meter +from opentelemetry.metrics.label_key import LabelKey + +meter = Meter() +label_keys = [LabelKey("environment", "the environment the application is running in")] +memory_metric = meter.create_int_gauge("available_memory", "available memory over time", "bytes", label_keys) +label_values = ["Testing"] +memory_metric.setCallBack(lambda: memory_metric.getOrCreateTimeSeries(label_values).set(psutil.virtual_memory().available)) \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py new file mode 100644 index 00000000000..c40da359268 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -0,0 +1,27 @@ +# 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. + + +from opentelemetry.distributedcontext import DistributedContext +from opentelemetry.metrics import Meter +from opentelemetry.metrics.label_key import LabelKey + +meter = Meter() +label_keys = [LabelKey("environment", "the environment the application is running in")] +sum_metric = meter.create_int_counter("sum numbers", "sum numbers over time", "number", label_keys) +label_values = ["Testing"] +sum_time_series = sum_metric.getOrCreateTimeSeries(label_values) + +for i in range(100): + sum_time_series.add(i) \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py new file mode 100644 index 00000000000..1c394147ef7 --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -0,0 +1,29 @@ +# 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. + +import psutil +import time + +from opentelemetry.distributedcontext import DistributedContext +from opentelemetry.metrics import Meter + +meter = Meter() +measure = meter.create_float_measure("cpu_usage", "cpu usage over time", "percentage") + +measurements = [] +for i in range(100): + measurements.append(measure.createMeasurement(psutil.cpu_percent())) + time.sleep(1) + + meter.record(measurements, distributed_context=DistributedContext.get_current()) \ No newline at end of file From 0a0b8eef0b2181a52f86d938b735c209662a6417 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 8 Aug 2019 09:23:33 -0700 Subject: [PATCH 13/41] fix lint --- .../distributedcontext/__init__.py | 18 ----------- .../src/opentelemetry/metrics/__init__.py | 30 +++++++++---------- .../metrics/examples/aggregated.py | 17 +++++++---- .../metrics/examples/pre_aggregated.py | 17 ++++++----- .../src/opentelemetry/metrics/examples/raw.py | 15 +++++----- .../src/opentelemetry/metrics/label_key.py | 1 - .../src/opentelemetry/metrics/label_value.py | 3 +- .../src/opentelemetry/metrics/time_series.py | 2 +- 8 files changed, 46 insertions(+), 57 deletions(-) delete mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py deleted file mode 100644 index 482f81e67c9..00000000000 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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. - - -# TODO -class DistributedContext: - pass diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 539c16de3f7..db93964a0e6 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -31,7 +31,6 @@ import abc import typing -from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics.label_key import LabelKey from opentelemetry.metrics.label_value import LabelValue from opentelemetry.metrics.time_series import CounterTimeSeries @@ -48,10 +47,10 @@ class Meter: used to record measurements like "server_latency" or "received_bytes", where the value of interest is the recorded value itself. - :class:`.Metric` s are used for recording pre-defined aggregation, or already - aggregated data. This should be used to report metrics like cpu/memory - usage, in which the type of aggregation is already defined, or simple - metrics like "queue_length". + :class:`.Metric` s are used for recording pre-defined aggregation, or + already aggregated data. This should be used to report metrics like + cpu/memory usage, in which the type of aggregation is already defined, or + simple metrics like "queue_length". """ def create_float_counter(self, @@ -201,7 +200,6 @@ def create_float_measure(self, def record(self, measurements: typing.List['Measurement'], - distributed_context: 'DistributedContext' = None, span_context: 'SpanContext' = None ) -> None: """Records a set of :class:`.Measurement` s. @@ -214,6 +212,7 @@ def record(self, Args: measurements: The collection of measurements to record. span_context: the :class:`.SpanContext` that identified the + # TODO: DistributedContext :class:`.Span` for which the measurements are associated with. Returns: None @@ -245,7 +244,7 @@ class Measure(abc.ABC): """ @abc.abstractmethod def create_measurement(self, - value: typing.Union[float, int] + value: typing.Any ) -> 'Measurement': """Creates a measurement. @@ -263,8 +262,8 @@ class FloatMeasure(Measure): """Used to create raw :class:`.FloatMeasurement` s.""" def create_measurement(self, - value: int, - ) -> 'FloatMeasurement': + value: int, + ) -> 'FloatMeasurement': """Creates a measurement with a FLOAT type. Args: @@ -322,7 +321,9 @@ def get_default_time_series(self) -> 'object': The timeseries will have all its labels not set (default). """ - def set_call_back(self, updater_function: typing.Callable[..., None]) -> None: + def set_call_back(self, + updater_function: typing.Callable[..., None] + ) -> None: """Sets a callback that gets executed every time prior to exporting. This function MUST set the value of the :class:`.Metric` to the @@ -348,7 +349,7 @@ def clear(self) -> None: class CounterFloat(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. """ @@ -359,12 +360,12 @@ def get_or_create_time_series(self, """Gets a :class:`.CounterTimeSeries` with a cumulated float value.""" def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a :class:`.CounterTimeSeries` with a cumulated float value.""" + """Returns a :class:`.CounterTimeSeries` with a float value.""" class CounterInt(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. """ @@ -379,7 +380,7 @@ def get_default_time_series(self) -> 'CounterTimeSeries': class GaugeFloat(Metric): """A gauge type metric that holds float values. - + Cumulative value can go both up and down. Values can be negative. """ @@ -405,4 +406,3 @@ def get_or_create_time_series(self, def get_default_time_series(self) -> 'GaugeTimeSeries': """Returns a :class:`.GaugeTimeSeries` with a cumulated int value.""" - diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py index 0103e9f2d7f..7c627ea8424 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py @@ -14,12 +14,17 @@ import psutil -from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics import Meter from opentelemetry.metrics.label_key import LabelKey -meter = Meter() -label_keys = [LabelKey("environment", "the environment the application is running in")] -memory_metric = meter.create_int_gauge("available_memory", "available memory over time", "bytes", label_keys) -label_values = ["Testing"] -memory_metric.setCallBack(lambda: memory_metric.getOrCreateTimeSeries(label_values).set(psutil.virtual_memory().available)) \ No newline at end of file +METER = Meter() +LABEL_KEYS = [LabelKey("environment", + "the environment the application is running in")] +MEMORY_METRIC = METER.create_int_gauge("available_memory", + "available memory over time", + "bytes", + LABEL_KEYS) +LABEL_VALUES = ["Testing"] +MEMORY_METRIC.setCallBack(lambda: MEMORY_METRIC \ + .getOrCreateTimeSeries(LABEL_VALUES) \ + .set(psutil.virtual_memory().available)) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index c40da359268..ba76fcc5c20 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -13,15 +13,18 @@ # limitations under the License. -from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics import Meter from opentelemetry.metrics.label_key import LabelKey -meter = Meter() -label_keys = [LabelKey("environment", "the environment the application is running in")] -sum_metric = meter.create_int_counter("sum numbers", "sum numbers over time", "number", label_keys) -label_values = ["Testing"] -sum_time_series = sum_metric.getOrCreateTimeSeries(label_values) +METER = Meter() +LABEL_KEYS = [LabelKey("environment", + "the environment the application is running in")] +SUM_METRIC = METER.create_int_counter("sum numbers", + "sum numbers over time", + "number", + LABEL_KEYS) +LABEL_VALUES = ["Testing"] +SUM_TIME_SERIES = SUM_METRIC.getOrCreateTimeSeries(LABEL_VALUES) for i in range(100): - sum_time_series.add(i) \ No newline at end of file + SUM_TIME_SERIES.add(i) \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 1c394147ef7..c61f5d2b312 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -12,18 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -import psutil import time +import psutil -from opentelemetry.distributedcontext import DistributedContext from opentelemetry.metrics import Meter -meter = Meter() -measure = meter.create_float_measure("cpu_usage", "cpu usage over time", "percentage") +METER = Meter() +MEASURE = METER.create_float_measure("cpu_usage", + "cpu usage over time", + "percentage") -measurements = [] +MEASUREMENTS = [] for i in range(100): - measurements.append(measure.createMeasurement(psutil.cpu_percent())) + MEASUREMENTS.append(MEASURE.createMeasurement(psutil.cpu_percent())) time.sleep(1) - meter.record(measurements, distributed_context=DistributedContext.get_current()) \ No newline at end of file + METER.record(MEASUREMENTS) diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_key.py b/opentelemetry-api/src/opentelemetry/metrics/label_key.py index baa5618aa80..8c351d83384 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/label_key.py +++ b/opentelemetry-api/src/opentelemetry/metrics/label_key.py @@ -27,4 +27,3 @@ def __init__(self, description: str) -> None: self.key = key self.description = description - diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_value.py b/opentelemetry-api/src/opentelemetry/metrics/label_value.py index 0006129f046..c9dc9654b1a 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/label_value.py +++ b/opentelemetry-api/src/opentelemetry/metrics/label_value.py @@ -13,7 +13,7 @@ # limitations under the License. -class LabelValue(object): +class LabelValue: """The label values associated with a TimeSeries. :type value: str @@ -22,4 +22,3 @@ class LabelValue(object): def __init__(self, value: str) -> None: self.value = value - diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index 1a294543761..dcd32e94398 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -33,7 +33,7 @@ def set(self, value: typing.Union[float, int]) -> None: class GaugeTimeSeries: - + def add(self, value: typing.Union[float, int]) -> None: """Adds the given value to the current value. From 555bf50783e62b049d770274084e1e109fa2de49 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 14 Aug 2019 15:35:27 -0700 Subject: [PATCH 14/41] Update to RFC 0003 --- .../src/opentelemetry/metrics/__init__.py | 330 +++++++----------- .../metrics/{label_key.py => aggregation.py} | 24 +- .../metrics/examples/aggregated.py | 30 -- .../metrics/examples/pre_aggregated.py | 15 +- .../src/opentelemetry/metrics/examples/raw.py | 24 +- .../src/opentelemetry/metrics/label_value.py | 24 -- .../src/opentelemetry/metrics/time_series.py | 25 +- 7 files changed, 183 insertions(+), 289 deletions(-) rename opentelemetry-api/src/opentelemetry/metrics/{label_key.py => aggregation.py} (55%) delete mode 100644 opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py delete mode 100644 opentelemetry-api/src/opentelemetry/metrics/label_value.py diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index db93964a0e6..55c27980cb5 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,40 +28,31 @@ """ -import abc -import typing +from abc import ABC, abstractmethod +from typing import Any, Callable, Dict, List -from opentelemetry.metrics.label_key import LabelKey -from opentelemetry.metrics.label_value import LabelValue +from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries from opentelemetry.metrics.time_series import GaugeTimeSeries -from opentelemetry.resources import Resource -from opentelemetry.trace import SpanContext +from opentelemetry.metrics.time_series import MeasureTimeSeries +LabelKeys = List['LabelKey'] +LabelValues = List['LabelValue'] -class Meter: - """An interface to allow the recording of measurements and metrics. - :class:`.Measurement` s are used for recording raw values, in which the - aggregation and labels for the exported metric are defered. This should be - used to record measurements like "server_latency" or "received_bytes", - where the value of interest is the recorded value itself. +class Meter: + """An interface to allow the recording of metrics. - :class:`.Metric` s are used for recording pre-defined aggregation, or - already aggregated data. This should be used to report metrics like - cpu/memory usage, in which the type of aggregation is already defined, or - simple metrics like "queue_length". + `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: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None + label_keys: LabelKeys, ) -> 'CounterFloat': """Creates a counter type metric that contains float values. @@ -69,26 +60,18 @@ def create_float_counter(self, 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 - constant_labels: A map of constant labels that will be used for \ - all of the TimeSeries created from the Metric. \ - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this metric. - - Returns: A new :class:`.CounterFloat` + 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. + + Returns: A new `CounterFloat` """ def create_int_counter(self, name: str, description: str, unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None + label_keys: LabelKeys, ) -> 'CounterInt': """Creates a counter type metric that contains int values. @@ -96,27 +79,19 @@ def create_int_counter(self, 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 - constant_labels: A map of constant labels that will be used for \ - all of the TimeSeries created from the Metric. \ - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this metric. + 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. Returns: - A new :class:`.CounterInt` + A new `CounterInt` """ def create_float_gauge(self, name: str, description: str, unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - comonent: str = None, - resource: 'Resource' = None + label_keys: LabelKeys, ) -> 'GaugeFloat': """Creates a gauge type metric that contains float values. @@ -124,27 +99,19 @@ def create_float_gauge(self, 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 - constant_labels: A map of constant labels that will be used for \ - all of the TimeSeries created from the Metric. \ - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this metric. + 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. Returns: - A new :class:`.GaugeFloat` + A new `GaugeFloat` """ def create_int_gauge(self, name: str, description: str, unit: str, - label_keys: typing.List['LabelKey'], - constant_labels: \ - typing.Dict['LabelKey', 'LabelValue'] = None, - component: str = None, - resource: 'Resource' = None + label_keys: LabelKeys ) -> 'GaugeInt': """Creates a gauge type metric that contains int values. @@ -152,144 +119,59 @@ def create_int_gauge(self, 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 - constant_labels: A map of constant labels that will be used for \ - all of the TimeSeries created from the Metric. \ - component: The name of the component that reports this metric. - Resource: Sets the :class:`.Resource` associated with this metric. + 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. + Returns: - A new :class:`.GaugeInt` + A new `GaugeInt` """ def create_int_measure(self, name: str, description: str, - unit: str - ) -> 'IntMeasure': - """Creates a measure used to record raw :class:`.Measurement` s. - The measurements created from this measure will have type INT. + unit: str, + label_keys: LabelKeys, + aggregation: 'Aggregation' + ) -> 'MeasureInt': + """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. Returns: - A :class:`.IntMeasure` + A new `MeasureInt` """ def create_float_measure(self, name: str, description: str, - unit: str - ) -> 'FloatMeasure': - """Creates a Measure used to record raw :class:`.Measurement` s. - The measurements created from this measure will have type INT. - - Args: - name: the name of the measure - description: Human readable description of this measure. - unit: Unit of the measure values. - - Returns: - A :class:`.FloatMeasure` - """ - - def record(self, - measurements: typing.List['Measurement'], - span_context: 'SpanContext' = None - ) -> None: - """Records a set of :class:`.Measurement` s. - - The API is built with the idea that measurement aggregation will occur - asynchronously. Typical library records multiple measurements at once, - so this function accepts a collection of measurements so the library - can batch all of them that need to be recorded. - - Args: - measurements: The collection of measurements to record. - span_context: the :class:`.SpanContext` that identified the - # TODO: DistributedContext - :class:`.Span` for which the measurements are associated with. - - Returns: None - """ - - -class Measurement: - """An empty interface that represents a single value. - - This single value is recorded for the :class:`.Measure` that created - this measurement. - """ - - -class FloatMeasurement(Measurement): - """A :class:`.Measurement` with an INT value.""" - - -class IntMeasurement(Measurement): - """A :class:`.Measurement` with an INT value.""" - - -class Measure(abc.ABC): - """Used to create raw :class:`.Measurement` s. - - A contract between the API exposing the raw measurement and SDK - aggregating these values into the :class:`.Metric`. Measure is - constructed from the :class:`.Meter` class. - """ - @abc.abstractmethod - def create_measurement(self, - value: typing.Any - ) -> 'Measurement': - """Creates a measurement. - - The type of the value in the measurement will correspond to the type - of measure that overrides this method. - - Args: - value: The value of the measurement. - - Returns: - A new :class:`.Measurement` - """ - -class FloatMeasure(Measure): - """Used to create raw :class:`.FloatMeasurement` s.""" - - def create_measurement(self, - value: int, - ) -> 'FloatMeasurement': - """Creates a measurement with a FLOAT type. - - Args: - value: The value of the measurement. - - Returns: - A new :class:`.FloatMeasurement` - """ - -class IntMeasure(Measure): - """Used to create raw :class:`.IntMeasurement` s.""" - - def create_measurement(self, - value: int, - ) -> 'IntMeasurement': - """Creates a measurement with an INT type. + unit: str, + label_keys: LabelKeys, + aggregation: 'Aggregation' + ) -> 'MeasureFloat': + """Creates a Measure used to record raw float values. Args: - value: The value of the measurement. + 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. Returns: - A new :class:`.IntMeasurement` + A new `MeasureFloat` """ -class Metric(abc.ABC): +class Metric(ABC): """Base class for various types of metrics. Metric class that inherit from this class are specialized with the type of @@ -297,9 +179,9 @@ class Metric(abc.ABC): :class:`.Meter` class. """ - @abc.abstractmethod + @abstractmethod def get_or_create_time_series(self, - label_values: typing.List['LabelValue'] + label_values: LabelValues ) -> 'object': """Gets and returns a timeseries, a container for a cumulative value. @@ -310,11 +192,11 @@ def get_or_create_time_series(self, overrides this function. Args: - label_values: A map of :class:`.LabelValue` s that will be \ - associated with the return timeseries. + label_values: A map of `LabelValue` s that will be associated + with the return timeseries. """ - @abc.abstractmethod + @abstractmethod def get_default_time_series(self) -> 'object': """Returns a timeseries, a container for a cumulative value. @@ -326,25 +208,25 @@ def set_call_back(self, ) -> None: """Sets a callback that gets executed every time prior to exporting. - This function MUST set the value of the :class:`.Metric` to the - value that will be exported. + This function MUST set the value of the `Metric` to the value that + that will be exported. args: updater_function: The callback function to execute. """ def remove_time_series(self, - label_values: typing.List['LabelValue']) -> None: - """Removes the timeseries from the :class:`.Metric`, if present. + label_values: LabelValues) -> None: + """Removes the timeseries from the Metric, if present. - The timeseries with matching :class:`.LabelValue` s will be removed. + The timeseries with matching `LabelValue` s will be removed. args: label_values: The list of label values to match against. """ def clear(self) -> None: - """Removes all timeseries from the :class:`.Metric`.""" + """Removes all timeseries from the `Metric`.""" class CounterFloat(Metric): @@ -355,12 +237,12 @@ class CounterFloat(Metric): """ def get_or_create_time_series(self, - label_values: typing.List['LabelValue'] + label_values: LabelValues ) -> 'CounterTimeSeries': - """Gets a :class:`.CounterTimeSeries` with a cumulated float value.""" + """Gets a CounterTimeSeries with a cumulative float value.""" def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a :class:`.CounterTimeSeries` with a float value.""" + """Returns a `CounterTimeSeries` with a cumulative float value.""" class CounterInt(Metric): @@ -371,12 +253,12 @@ class CounterInt(Metric): """ def get_or_create_time_series(self, - label_values: typing.List['LabelValue'] + label_values: LabelValues ) -> 'CounterTimeSeries': - """Gets a :class:`.CounterTimeSeries` with a cumulated int value.""" + """Gets a `CounterTimeSeries` with a cumulative int value.""" def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a :class:`.CounterTimeSeries` with a cumulated int value.""" + """Returns a `CounterTimeSeries` with a cumulative int value.""" class GaugeFloat(Metric): """A gauge type metric that holds float values. @@ -385,12 +267,12 @@ class GaugeFloat(Metric): """ def get_or_create_time_series(self, - label_values: typing.List['LabelValue'] + label_values: LabelValues ) -> 'GaugeTimeSeries': - """Gets a :class:`.GaugeTimeSeries` with a cumulated float value.""" + """Gets a `GaugeTimeSeries` with a cumulative float value.""" def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a :class:`.GaugeTimeSeries` with a cumulated float value.""" + """Returns a `GaugeTimeSeries` with a cumulative float value.""" class GaugeInt(Metric): @@ -400,9 +282,65 @@ class GaugeInt(Metric): """ def get_or_create_time_series(self, - label_values: typing.List['LabelValue'] + label_values: LabelValues ) -> 'GaugeTimeSeries': - """Gets a :class:`.GaugeTimeSeries` with a cumulated int value.""" + """Gets a `GaugeTimeSeries` with a cumulative int value.""" def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a :class:`.GaugeTimeSeries` with a cumulated int value.""" + """Returns a `GaugeTimeSeries` with a cumulative int value.""" + + +class MeasureFloat(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.""" + + def get_default_time_series(self) -> 'MeasureTimeSeries': + """Returns a `MeasureTimeSeries` with a cumulated float value.""" + + +class MeasureInt(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.""" + + def get_default_time_series(self) -> 'MeasureTimeSeries': + """Returns 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 + +class LabelValue: + """The label values associated with a TimeSeries. + + :type value: str + :param value: the value for the label + """ + def __init__(self, + value: str) -> None: + self.value = value \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_key.py b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py similarity index 55% rename from opentelemetry-api/src/opentelemetry/metrics/label_key.py rename to opentelemetry-api/src/opentelemetry/metrics/aggregation.py index 8c351d83384..5bd8b2f27dd 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/label_key.py +++ b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py @@ -12,18 +12,18 @@ # See the License for the specific language governing permissions and # limitations under the License. +#TODO +class BaseAggregation: + """The base class for all aggregation types.""" -class LabelKey: - """The label keys associated with the metric. +class CountAggregation(BaseAggregation): + """An aggregation representing a count of values.""" - :type key: str - :param key: the key for the label +class DistributonAggregation(BaseAggregation): + """An aggregation representing a distribution.""" - :type description: str - :param description: description of the label - """ - def __init__(self, - key: str, - description: str) -> None: - self.key = key - self.description = description +class LastValueAggregation(BaseAggregation): + """An aggregation representing the last value.""" + +class SumAggregation(BaseAggregation): + """An aggregation representing a sum of values.""" diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py deleted file mode 100644 index 7c627ea8424..00000000000 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/aggregated.py +++ /dev/null @@ -1,30 +0,0 @@ -# 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. - -import psutil - -from opentelemetry.metrics import Meter -from opentelemetry.metrics.label_key import LabelKey - -METER = Meter() -LABEL_KEYS = [LabelKey("environment", - "the environment the application is running in")] -MEMORY_METRIC = METER.create_int_gauge("available_memory", - "available memory over time", - "bytes", - LABEL_KEYS) -LABEL_VALUES = ["Testing"] -MEMORY_METRIC.setCallBack(lambda: MEMORY_METRIC \ - .getOrCreateTimeSeries(LABEL_VALUES) \ - .set(psutil.virtual_memory().available)) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index ba76fcc5c20..004d2943b30 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -13,18 +13,23 @@ # limitations under the License. +from opentelemetry.metrics import LabelKey +from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter -from opentelemetry.metrics.label_key import LabelKey METER = Meter() LABEL_KEYS = [LabelKey("environment", "the environment the application is running in")] -SUM_METRIC = METER.create_int_counter("sum numbers", +COUNTER = METER.create_int_counter("sum numbers", "sum numbers over time", "number", LABEL_KEYS) -LABEL_VALUES = ["Testing"] -SUM_TIME_SERIES = SUM_METRIC.getOrCreateTimeSeries(LABEL_VALUES) +LABEL_VALUE_TESTING = [LabelValue("Testing")] +LABEL_VALUE_STAGING = [LabelValue("Staging")] + +# Metrics sent to some exporter +COUNTER_METRIC_TESTING = COUNTER.get_or_create_time_series(LABEL_VALUE_TESTING) +COUNTER_METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_STAGING) for i in range(100): - SUM_TIME_SERIES.add(i) \ No newline at end of file + COUNTER_METRIC_STAGING.add(i) \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index c61f5d2b312..66f5fe55f3c 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -12,19 +12,25 @@ # See the License for the specific language governing permissions and # limitations under the License. -import time import psutil +from opentelemetry.metrics import LabelKey +from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter +from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() -MEASURE = METER.create_float_measure("cpu_usage", - "cpu usage over time", - "percentage") +LABEL_KEYS = [LabelKey("environment", + "the environment the application is running in")] +MEASURE = METER.create_float_measure("idle_cpu_percentage", + "cpu idle over time", + "percentage", + LastValueAggregation) +LABEL_VALUE_TESTING = [LabelValue("Testing")] +LABEL_VALUE_STAGING = [LabelValue("Staging")] -MEASUREMENTS = [] -for i in range(100): - MEASUREMENTS.append(MEASURE.createMeasurement(psutil.cpu_percent())) - time.sleep(1) +# Metrics sent to some exporter +MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) +MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) - METER.record(MEASUREMENTS) +MEASURE_METRIC_STAGING.record(psutil.cpu_times_percent().idle) diff --git a/opentelemetry-api/src/opentelemetry/metrics/label_value.py b/opentelemetry-api/src/opentelemetry/metrics/label_value.py deleted file mode 100644 index c9dc9654b1a..00000000000 --- a/opentelemetry-api/src/opentelemetry/metrics/label_value.py +++ /dev/null @@ -1,24 +0,0 @@ -# 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. - - -class LabelValue: - """The label values associated with a TimeSeries. - - :type value: str - :param value: the value for the label - """ - def __init__(self, - value: str) -> None: - self.value = value diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index dcd32e94398..e0e8eba22ac 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -18,27 +18,26 @@ class CounterTimeSeries: def add(self, value: typing.Union[float, int]) -> None: - """Adds the given value to the current value. - - The values cannot be negative. - """ + """Adds the given value to the current value. Cannot be negative.""" def set(self, value: typing.Union[float, int]) -> None: """Sets the current value to the given value. - The given value must be larger than the current recorded value. In - general should be used in combination with `SetCallback` where the - recorded value is guaranteed to be monotonically increasing. + The given value must be larger than the current recorded value. """ class GaugeTimeSeries: - def add(self, value: typing.Union[float, int]) -> None: - """Adds the given value to the current value. + def set(self, value: typing.Union[float, int]) -> None: + """Sets the current value to the given value. Can be negative.""" - The values can be negative. - """ - def set(self, value: typing.Union[float, int]) -> None: - """Sets the current value to the given value.""" +class MeasureTimeSeries: + + def record(self, value: typing.Union[float, int]) -> None: + """Records the given value to this measure. + + Logic depends on type of aggregation used for this measure. + """ + \ No newline at end of file From d6b1113e19cbaf7f95f2b34eaebf5a72faae75d1 Mon Sep 17 00:00:00 2001 From: Leighton Date: Wed, 14 Aug 2019 15:59:18 -0700 Subject: [PATCH 15/41] Add spancontext, measurebatch --- .../src/opentelemetry/metrics/__init__.py | 46 +++++++++++++++---- .../src/opentelemetry/metrics/examples/raw.py | 9 +++- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 55c27980cb5..128da5775d2 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -35,6 +35,7 @@ from opentelemetry.metrics.time_series import CounterTimeSeries from opentelemetry.metrics.time_series import GaugeTimeSeries from opentelemetry.metrics.time_series import MeasureTimeSeries +from opentelemetry.trace import SpanContext LabelKeys = List['LabelKey'] LabelValues = List['LabelValue'] @@ -53,6 +54,7 @@ def create_float_counter(self, description: str, unit: str, label_keys: LabelKeys, + span_context: SpanContext = None ) -> 'CounterFloat': """Creates a counter type metric that contains float values. @@ -63,6 +65,8 @@ def create_float_counter(self, 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 identified the `Span` + for which the metrics are associated with. Returns: A new `CounterFloat` """ @@ -72,6 +76,7 @@ def create_int_counter(self, description: str, unit: str, label_keys: LabelKeys, + span_context: SpanContext = None ) -> 'CounterInt': """Creates a counter type metric that contains int values. @@ -82,6 +87,8 @@ def create_int_counter(self, 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 identified the `Span` + for which the metrics are associated with. Returns: A new `CounterInt` @@ -92,6 +99,7 @@ def create_float_gauge(self, description: str, unit: str, label_keys: LabelKeys, + span_context: SpanContext = None ) -> 'GaugeFloat': """Creates a gauge type metric that contains float values. @@ -102,6 +110,8 @@ def create_float_gauge(self, 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 identified the `Span` + for which the metrics are associated with. Returns: A new `GaugeFloat` @@ -111,7 +121,8 @@ def create_int_gauge(self, name: str, description: str, unit: str, - label_keys: LabelKeys + label_keys: LabelKeys, + span_context: SpanContext = None ) -> 'GaugeInt': """Creates a gauge type metric that contains int values. @@ -122,7 +133,8 @@ def create_int_gauge(self, 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 identified the `Span` + for which the metrics are associated with. Returns: A new `GaugeInt` @@ -133,17 +145,21 @@ def create_int_measure(self, description: str, unit: str, label_keys: LabelKeys, - aggregation: 'Aggregation' + aggregation: 'Aggregation', + span_context: SpanContext = None, ) -> 'MeasureInt': """Creates a measure used to record raw int values. Args: - name: the name of the measure + 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. + aggregation: The type of aggregation to use for this measure metric. + span_context: The `SpanContext` that identified the `Span` + for which the metrics are associated with. Returns: A new `MeasureInt` @@ -154,7 +170,8 @@ def create_float_measure(self, description: str, unit: str, label_keys: LabelKeys, - aggregation: 'Aggregation' + aggregation: 'Aggregation', + span_context: SpanContext = None, ) -> 'MeasureFloat': """Creates a Measure used to record raw float values. @@ -165,6 +182,9 @@ def create_float_measure(self, 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. + aggregation: The type of aggregation to use for this measure metric. + span_context: The `SpanContext` that identified the `Span` + for which the metrics are associated with. Returns: A new `MeasureFloat` @@ -175,8 +195,7 @@ 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 - :class:`.Meter` class. + time series that the metric holds. Metric is constructed from the meter. """ @abstractmethod @@ -204,7 +223,7 @@ def get_default_time_series(self) -> 'object': """ def set_call_back(self, - updater_function: typing.Callable[..., None] + updater_function: Callable[..., None] ) -> None: """Sets a callback that gets executed every time prior to exporting. @@ -320,6 +339,17 @@ def get_default_time_series(self) -> 'MeasureTimeSeries': """Returns a `.MeasureTimeSeries` with a cumulated int value.""" +class MeasureBatch: + + def record(metric_pairs): + """Records multiple observed values simultaneously. + + Args: + metric_pairs: A list of tuples containing the `Metric` and value + to be recorded. + """ + + class LabelKey: """The label keys associated with the metric. diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 66f5fe55f3c..2e2c84d21a0 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -17,6 +17,7 @@ from opentelemetry.metrics import LabelKey from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter +from opentelemetry.metrics import MeasureBatch from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() @@ -33,4 +34,10 @@ MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) -MEASURE_METRIC_STAGING.record(psutil.cpu_times_percent().idle) +# record individual measures +idle = psutil.cpu_times_percent().idle +MEASURE_METRIC_STAGING.record(idle) + +# record multiple observed values +batch = MeasureBatch() +batch.record([(MEASURE_METRIC_TESTING, idle), (MEASURE_METRIC_STAGING, idle)]) From 18cfc7162cf62be7e19f9d150be133e0e390c01d Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 15 Aug 2019 11:04:23 -0700 Subject: [PATCH 16/41] Fix docs --- docs/index.rst | 1 + docs/opentelemetry.metrics.aggregation.rst | 7 +++++ docs/opentelemetry.metrics.rst | 15 +++++++++ docs/opentelemetry.metrics.time_series.rst | 7 +++++ .../src/opentelemetry/metrics/__init__.py | 31 +++++++++---------- .../src/opentelemetry/metrics/aggregation.py | 10 +++--- 6 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 docs/opentelemetry.metrics.aggregation.rst create mode 100644 docs/opentelemetry.metrics.rst create mode 100644 docs/opentelemetry.metrics.time_series.rst diff --git a/docs/index.rst b/docs/index.rst index 8991f2b5df5..4d968ccd64f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -17,6 +17,7 @@ abstract types for OpenTelemetry implementations. opentelemetry.context opentelemetry.loader + opentelemetry.metrics opentelemetry.trace diff --git a/docs/opentelemetry.metrics.aggregation.rst b/docs/opentelemetry.metrics.aggregation.rst new file mode 100644 index 00000000000..c97f1bf72e2 --- /dev/null +++ b/docs/opentelemetry.metrics.aggregation.rst @@ -0,0 +1,7 @@ +opentelemetry.metrics.aggregation module +========================================== + +.. automodule:: opentelemetry.metrics.aggregation + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/opentelemetry.metrics.rst b/docs/opentelemetry.metrics.rst new file mode 100644 index 00000000000..b3886271335 --- /dev/null +++ b/docs/opentelemetry.metrics.rst @@ -0,0 +1,15 @@ +opentelemetry.metrics package +============================= + +Submodules +---------- + +.. toctree:: + + opentelemetry.metrics.aggregation + opentelemetry.metrics.time_series + +Module contents +--------------- + +.. automodule:: opentelemetry.metrics diff --git a/docs/opentelemetry.metrics.time_series.rst b/docs/opentelemetry.metrics.time_series.rst new file mode 100644 index 00000000000..976a81a8210 --- /dev/null +++ b/docs/opentelemetry.metrics.time_series.rst @@ -0,0 +1,7 @@ +opentelemetry.metrics.time\_series module +========================================== + +.. automodule:: opentelemetry.metrics.time_series + :members: + :undoc-members: + :show-inheritance: diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 128da5775d2..444f2b79a25 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -16,9 +16,8 @@ The OpenTelemetry metrics API describes the classes used to report raw measurements, as well as metrics with known aggregation and labels. -The :class:`.Meter` class is used to construct :class:`.Measure` s to -record raw measurements and :class:`.Metric` s to record metrics with -predefined aggregation. +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. @@ -212,7 +211,7 @@ def get_or_create_time_series(self, Args: label_values: A map of `LabelValue` s that will be associated - with the return timeseries. + with the return timeseries. """ @abstractmethod @@ -258,7 +257,7 @@ class CounterFloat(Metric): def get_or_create_time_series(self, label_values: LabelValues ) -> 'CounterTimeSeries': - """Gets a CounterTimeSeries with a cumulative float value.""" + """Gets a `CounterTimeSeries` with a cumulative float value.""" def get_default_time_series(self) -> 'CounterTimeSeries': """Returns a `CounterTimeSeries` with a cumulative float value.""" @@ -316,8 +315,8 @@ class MeasureFloat(Metric): """ def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'MeasureTimeSeries': + label_values: LabelValues + ) -> 'MeasureTimeSeries': """Gets a `MeasureTimeSeries` with a cumulated float value.""" def get_default_time_series(self) -> 'MeasureTimeSeries': @@ -331,22 +330,22 @@ class MeasureInt(Metric): """ def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'MeasureTimeSeries': - """Gets a `.MeasureTimeSeries` with a cumulated int value.""" + label_values: LabelValues + ) -> 'MeasureTimeSeries': + """Gets a `MeasureTimeSeries` with a cumulated int value.""" def get_default_time_series(self) -> 'MeasureTimeSeries': - """Returns a `.MeasureTimeSeries` with a cumulated int value.""" + """Returns a `MeasureTimeSeries` with a cumulated int value.""" class MeasureBatch: - def record(metric_pairs): + def record(self, metric_pairs): """Records multiple observed values simultaneously. Args: metric_pairs: A list of tuples containing the `Metric` and value - to be recorded. + to be recorded. """ @@ -360,8 +359,8 @@ class LabelKey: :param description: description of the label """ def __init__(self, - key: str, - description: str) -> None: + key: str, + description: str) -> None: self.key = key self.description = description @@ -372,5 +371,5 @@ class LabelValue: :param value: the value for the label """ def __init__(self, - value: str) -> None: + value: str) -> None: self.value = value \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py index 5bd8b2f27dd..e2c1fd5e8b3 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py +++ b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py @@ -13,17 +13,17 @@ # limitations under the License. #TODO -class BaseAggregation: +class Aggregation: """The base class for all aggregation types.""" -class CountAggregation(BaseAggregation): +class CountAggregation(Aggregation): """An aggregation representing a count of values.""" -class DistributonAggregation(BaseAggregation): +class DistributonAggregation(Aggregation): """An aggregation representing a distribution.""" -class LastValueAggregation(BaseAggregation): +class LastValueAggregation(Aggregation): """An aggregation representing the last value.""" -class SumAggregation(BaseAggregation): +class SumAggregation(Aggregation): """An aggregation representing a sum of values.""" From a44cb478d4967b3fcc0ff4c90ff8e0662862faa4 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 12:47:21 -0700 Subject: [PATCH 17/41] Fix comments --- docs/opentelemetry.metrics.aggregation.rst | 4 +- docs/opentelemetry.metrics.time_series.rst | 4 +- .../distributedcontext/__init__.py | 13 ++++ .../src/opentelemetry/metrics/__init__.py | 61 ++++--------------- 4 files changed, 28 insertions(+), 54 deletions(-) create mode 100644 opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py diff --git a/docs/opentelemetry.metrics.aggregation.rst b/docs/opentelemetry.metrics.aggregation.rst index c97f1bf72e2..99848381e3e 100644 --- a/docs/opentelemetry.metrics.aggregation.rst +++ b/docs/opentelemetry.metrics.aggregation.rst @@ -2,6 +2,4 @@ opentelemetry.metrics.aggregation module ========================================== .. automodule:: opentelemetry.metrics.aggregation - :members: - :undoc-members: - :show-inheritance: + diff --git a/docs/opentelemetry.metrics.time_series.rst b/docs/opentelemetry.metrics.time_series.rst index 976a81a8210..16297d7eacd 100644 --- a/docs/opentelemetry.metrics.time_series.rst +++ b/docs/opentelemetry.metrics.time_series.rst @@ -2,6 +2,4 @@ opentelemetry.metrics.time\_series module ========================================== .. automodule:: opentelemetry.metrics.time_series - :members: - :undoc-members: - :show-inheritance: + diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py new file mode 100644 index 00000000000..ee1b702864f --- /dev/null +++ b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py @@ -0,0 +1,13 @@ +# 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. \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 444f2b79a25..65cf358bd3c 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -64,8 +64,8 @@ def create_float_counter(self, 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 identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `CounterFloat` """ @@ -86,8 +86,8 @@ def create_int_counter(self, 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 identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `CounterInt` @@ -109,8 +109,8 @@ def create_float_gauge(self, 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 identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `GaugeFloat` @@ -132,8 +132,8 @@ def create_int_gauge(self, 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 identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `GaugeInt` @@ -157,8 +157,8 @@ def create_int_measure(self, Order of the list is important as the same order MUST be used on recording when suppling values for these labels. aggregation: The type of aggregation to use for this measure metric. - span_context: The `SpanContext` that identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `MeasureInt` @@ -182,8 +182,8 @@ def create_float_measure(self, Order of the list is important as the same order MUST be used on recording when suppling values for these labels. aggregation: The type of aggregation to use for this measure metric. - span_context: The `SpanContext` that identified the `Span` - for which the metrics are associated with. + span_context: The `SpanContext` that identifies the `Span` + that the metric is associated with. Returns: A new `MeasureFloat` @@ -214,25 +214,6 @@ def get_or_create_time_series(self, with the return timeseries. """ - @abstractmethod - def get_default_time_series(self) -> 'object': - """Returns a timeseries, a container for a cumulative value. - - The timeseries will have all its labels not set (default). - """ - - def set_call_back(self, - updater_function: Callable[..., None] - ) -> None: - """Sets a callback that gets executed every time prior to exporting. - - This function MUST set the value of the `Metric` to the value that - that will be exported. - - args: - updater_function: The callback function to execute. - """ - def remove_time_series(self, label_values: LabelValues) -> None: """Removes the timeseries from the Metric, if present. @@ -259,9 +240,6 @@ def get_or_create_time_series(self, ) -> 'CounterTimeSeries': """Gets a `CounterTimeSeries` with a cumulative float value.""" - def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a `CounterTimeSeries` with a cumulative float value.""" - class CounterInt(Metric): """A counter type metric that holds int values. @@ -275,8 +253,6 @@ def get_or_create_time_series(self, ) -> 'CounterTimeSeries': """Gets a `CounterTimeSeries` with a cumulative int value.""" - def get_default_time_series(self) -> 'CounterTimeSeries': - """Returns a `CounterTimeSeries` with a cumulative int value.""" class GaugeFloat(Metric): """A gauge type metric that holds float values. @@ -289,9 +265,6 @@ def get_or_create_time_series(self, ) -> 'GaugeTimeSeries': """Gets a `GaugeTimeSeries` with a cumulative float value.""" - def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a `GaugeTimeSeries` with a cumulative float value.""" - class GaugeInt(Metric): """A gauge type metric that holds int values. @@ -304,9 +277,6 @@ def get_or_create_time_series(self, ) -> 'GaugeTimeSeries': """Gets a `GaugeTimeSeries` with a cumulative int value.""" - def get_default_time_series(self) -> 'GaugeTimeSeries': - """Returns a `GaugeTimeSeries` with a cumulative int value.""" - class MeasureFloat(Metric): """A measure type metric that holds float values. @@ -319,9 +289,6 @@ def get_or_create_time_series(self, ) -> 'MeasureTimeSeries': """Gets a `MeasureTimeSeries` with a cumulated float value.""" - def get_default_time_series(self) -> 'MeasureTimeSeries': - """Returns a `MeasureTimeSeries` with a cumulated float value.""" - class MeasureInt(Metric): """A measure type metric that holds int values. @@ -334,9 +301,6 @@ def get_or_create_time_series(self, ) -> 'MeasureTimeSeries': """Gets a `MeasureTimeSeries` with a cumulated int value.""" - def get_default_time_series(self) -> 'MeasureTimeSeries': - """Returns a `MeasureTimeSeries` with a cumulated int value.""" - class MeasureBatch: @@ -364,6 +328,7 @@ def __init__(self, self.key = key self.description = description + class LabelValue: """The label values associated with a TimeSeries. From 94eaad904412f4716d864f8813978c77c47dc7f8 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:01:42 -0700 Subject: [PATCH 18/41] fix lint --- .../opentelemetry/distributedcontext/__init__.py | 2 +- .../src/opentelemetry/metrics/__init__.py | 8 ++++---- .../metrics/examples/pre_aggregated.py | 12 ++++++------ .../src/opentelemetry/metrics/examples/raw.py | 13 ++++++------- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py index ee1b702864f..d853a7bcf65 100644 --- a/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py +++ b/opentelemetry-api/src/opentelemetry/distributedcontext/__init__.py @@ -10,4 +10,4 @@ # 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. \ No newline at end of file +# limitations under the License. diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 65cf358bd3c..eae913ecfb1 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -156,7 +156,7 @@ def create_int_measure(self, 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. - aggregation: The type of aggregation to use for this measure metric. + aggregation: The type of aggregation to use for this metric. span_context: The `SpanContext` that identifies the `Span` that the metric is associated with. @@ -181,7 +181,7 @@ def create_float_measure(self, 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. - aggregation: The type of aggregation to use for this measure metric. + aggregation: The type of aggregation to use for this metric. span_context: The `SpanContext` that identifies the `Span` that the metric is associated with. @@ -304,7 +304,7 @@ def get_or_create_time_series(self, class MeasureBatch: - def record(self, metric_pairs): + def record(self, metric_pairs) -> None: """Records multiple observed values simultaneously. Args: @@ -337,4 +337,4 @@ class LabelValue: """ def __init__(self, value: str) -> None: - self.value = value \ No newline at end of file + self.value = value diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index 004d2943b30..f6ad137b39c 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -18,12 +18,12 @@ from opentelemetry.metrics import Meter METER = Meter() -LABEL_KEYS = [LabelKey("environment", +LABEL_KEYS = [LabelKey("environment", "the environment the application is running in")] -COUNTER = METER.create_int_counter("sum numbers", - "sum numbers over time", - "number", - LABEL_KEYS) +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")] @@ -32,4 +32,4 @@ COUNTER_METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_STAGING) for i in range(100): - COUNTER_METRIC_STAGING.add(i) \ No newline at end of file + COUNTER_METRIC_STAGING.add(i) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 2e2c84d21a0..0c72ccb3fd8 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -import psutil - from opentelemetry.metrics import LabelKey from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter @@ -23,9 +21,10 @@ METER = Meter() LABEL_KEYS = [LabelKey("environment", "the environment the application is running in")] -MEASURE = METER.create_float_measure("idle_cpu_percentage", +MEASURE = METER.create_float_measure("idle_cpu_percentage", # pragma: no cover "cpu idle over time", "percentage", + LABEL_KEYS, LastValueAggregation) LABEL_VALUE_TESTING = [LabelValue("Testing")] LABEL_VALUE_STAGING = [LabelValue("Staging")] @@ -35,9 +34,9 @@ MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) # record individual measures -idle = psutil.cpu_times_percent().idle -MEASURE_METRIC_STAGING.record(idle) +STATISTIC = 100 +MEASURE_METRIC_STAGING.record(STATISTIC) # record multiple observed values -batch = MeasureBatch() -batch.record([(MEASURE_METRIC_TESTING, idle), (MEASURE_METRIC_STAGING, idle)]) +BATCH = MeasureBatch() +BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), (MEASURE_METRIC_STAGING, STATISTIC)]) From fc251b2c47ac30101dc61e96bbd93636936ec8fb Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:15:04 -0700 Subject: [PATCH 19/41] fix lint --- .../src/opentelemetry/metrics/__init__.py | 4 +- .../metrics/examples/pre_aggregated.py | 26 ++++++------- .../src/opentelemetry/metrics/examples/raw.py | 37 ++++++++++--------- 3 files changed, 34 insertions(+), 33 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index eae913ecfb1..3cc635c19d3 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,7 +28,7 @@ """ from abc import ABC, abstractmethod -from typing import Any, Callable, Dict, List +from typing import Any, Callable, Dict, List, Tuple from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries @@ -304,7 +304,7 @@ def get_or_create_time_series(self, class MeasureBatch: - def record(self, metric_pairs) -> None: + def record(self, metric_pairs: List[Tuple]) -> None: """Records multiple observed values simultaneously. Args: diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index f6ad137b39c..ec019a16f31 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -18,18 +18,18 @@ from opentelemetry.metrics import 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")] +# 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 -COUNTER_METRIC_TESTING = COUNTER.get_or_create_time_series(LABEL_VALUE_TESTING) -COUNTER_METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_STAGING) +# # Metrics sent to some exporter +# COUNTER_METRIC_TESTING = COUNTER.get_or_create_time_series(LABEL_VALUE_TESTING) +# COUNTER_METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_STAGING) -for i in range(100): - COUNTER_METRIC_STAGING.add(i) +# for i in range(100): +# COUNTER_METRIC_STAGING.add(i) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 0c72ccb3fd8..9bdc704a6db 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -19,24 +19,25 @@ from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() -LABEL_KEYS = [LabelKey("environment", - "the environment the application is running in")] -MEASURE = METER.create_float_measure("idle_cpu_percentage", # pragma: no cover - "cpu idle over time", - "percentage", - LABEL_KEYS, - LastValueAggregation) -LABEL_VALUE_TESTING = [LabelValue("Testing")] -LABEL_VALUE_STAGING = [LabelValue("Staging")] +# LABEL_KEYS = [LabelKey("environment", +# "the environment the application is running in")] +# MEASURE = METER.create_float_measure("idle_cpu_percentage", +# "cpu idle over time", +# "percentage", +# LABEL_KEYS, +# LastValueAggregation) +# LABEL_VALUE_TESTING = [LabelValue("Testing")] +# LABEL_VALUE_STAGING = [LabelValue("Staging")] -# Metrics sent to some exporter -MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) -MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) +# # Metrics sent to some exporter +# MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) +# MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) -# record individual measures -STATISTIC = 100 -MEASURE_METRIC_STAGING.record(STATISTIC) +# # record individual measures +# STATISTIC = 100 +# MEASURE_METRIC_STAGING.record(STATISTIC) -# record multiple observed values -BATCH = MeasureBatch() -BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), (MEASURE_METRIC_STAGING, STATISTIC)]) +# # record multiple observed values +# BATCH = MeasureBatch() +# BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), \ +# (MEASURE_METRIC_STAGING, STATISTIC)]) From 262f312eafe65577423151acbf3b53b8432615fa Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:21:06 -0700 Subject: [PATCH 20/41] fix lint --- .../src/opentelemetry/metrics/__init__.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3cc635c19d3..a9cda035961 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,7 +28,7 @@ """ from abc import ABC, abstractmethod -from typing import Any, Callable, Dict, List, Tuple +from typing import Any, Callable, Dict, List, Tuple, Union from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries @@ -304,12 +304,14 @@ def get_or_create_time_series(self, class MeasureBatch: - def record(self, metric_pairs: List[Tuple]) -> None: + def record(self, + metrics: List['Metric'], + values: List[Union[float, int]]) -> None: """Records multiple observed values simultaneously. Args: - metric_pairs: A list of tuples containing the `Metric` and value - to be recorded. + metric: A list containing the `Metric` s to be recorded + values: A list containing the values to record """ From 66c0a56ac333d91bb71c714c64c3f9fe9e887ccb Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:26:38 -0700 Subject: [PATCH 21/41] skip examples --- .../metrics/examples/pre_aggregated.py | 2 +- .../src/opentelemetry/metrics/examples/raw.py | 39 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index ec019a16f31..c175815999d 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. - +# pylint: skip-file from opentelemetry.metrics import LabelKey from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 9bdc704a6db..95a1be9eaab 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: skip-file from opentelemetry.metrics import LabelKey from opentelemetry.metrics import LabelValue from opentelemetry.metrics import Meter @@ -19,25 +20,25 @@ from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() -# LABEL_KEYS = [LabelKey("environment", -# "the environment the application is running in")] -# MEASURE = METER.create_float_measure("idle_cpu_percentage", -# "cpu idle over time", -# "percentage", -# LABEL_KEYS, -# LastValueAggregation) -# LABEL_VALUE_TESTING = [LabelValue("Testing")] -# LABEL_VALUE_STAGING = [LabelValue("Staging")] +LABEL_KEYS = [LabelKey("environment", + "the environment the application is running in")] +MEASURE = METER.create_float_measure("idle_cpu_percentage", + "cpu idle over time", + "percentage", + LABEL_KEYS, + LastValueAggregation) +LABEL_VALUE_TESTING = [LabelValue("Testing")] +LABEL_VALUE_STAGING = [LabelValue("Staging")] -# # Metrics sent to some exporter -# MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) -# MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) +# Metrics sent to some exporter +MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) +MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) -# # record individual measures -# STATISTIC = 100 -# MEASURE_METRIC_STAGING.record(STATISTIC) +# record individual measures +STATISTIC = 100 +MEASURE_METRIC_STAGING.record(STATISTIC) -# # record multiple observed values -# BATCH = MeasureBatch() -# BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), \ -# (MEASURE_METRIC_STAGING, STATISTIC)]) +# record multiple observed values +BATCH = MeasureBatch() +BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), \ + (MEASURE_METRIC_STAGING, STATISTIC)]) From e2c4a7eb646191b591a75a0c842f7917e27a39ce Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:32:24 -0700 Subject: [PATCH 22/41] white space --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index a9cda035961..3c0a08c9076 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -304,7 +304,7 @@ def get_or_create_time_series(self, class MeasureBatch: - def record(self, + def record(self, metrics: List['Metric'], values: List[Union[float, int]]) -> None: """Records multiple observed values simultaneously. From 2fb76468ad2ae8b5186ab392fe05c7c54c1f7262 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 13:41:38 -0700 Subject: [PATCH 23/41] fix spacing --- .../src/opentelemetry/metrics/__init__.py | 2 +- .../src/opentelemetry/metrics/aggregation.py | 6 ++++- .../metrics/examples/pre_aggregated.py | 26 +++++++++---------- .../src/opentelemetry/metrics/examples/raw.py | 4 +-- .../src/opentelemetry/metrics/time_series.py | 1 - 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3c0a08c9076..5b349e4d818 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,7 +28,7 @@ """ from abc import ABC, abstractmethod -from typing import Any, Callable, Dict, List, Tuple, Union +from typing import List, Union from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries diff --git a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py index e2c1fd5e8b3..36f744b6146 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py +++ b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py @@ -12,18 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -#TODO + class Aggregation: """The base class for all aggregation types.""" + class CountAggregation(Aggregation): """An aggregation representing a count of values.""" + class DistributonAggregation(Aggregation): """An aggregation representing a distribution.""" + class LastValueAggregation(Aggregation): """An aggregation representing the last value.""" + class SumAggregation(Aggregation): """An aggregation representing a sum of values.""" diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index c175815999d..61feb2d239f 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -18,18 +18,18 @@ from opentelemetry.metrics import 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")] +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 -# COUNTER_METRIC_TESTING = COUNTER.get_or_create_time_series(LABEL_VALUE_TESTING) -# COUNTER_METRIC_STAGING = COUNTER.get_or_create_time_series(LABEL_VALUE_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): -# COUNTER_METRIC_STAGING.add(i) +for i in range(100): + METRIC_STAGING.add(i) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 95a1be9eaab..dc9840b53ca 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -40,5 +40,5 @@ # record multiple observed values BATCH = MeasureBatch() -BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), \ - (MEASURE_METRIC_STAGING, STATISTIC)]) +BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), + (MEASURE_METRIC_STAGING, STATISTIC)]) diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index e0e8eba22ac..b6cc5af5ccd 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -40,4 +40,3 @@ def record(self, value: typing.Union[float, int]) -> None: Logic depends on type of aggregation used for this measure. """ - \ No newline at end of file From eb711cb806ee766c97f9d7d28edc1ecf1e163662 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 16:25:12 -0700 Subject: [PATCH 24/41] fix imports --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 3 +-- opentelemetry-api/src/opentelemetry/metrics/examples/raw.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 5b349e4d818..3e63f40ff9b 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,13 +28,12 @@ """ from abc import ABC, abstractmethod -from typing import List, Union - from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries from opentelemetry.metrics.time_series import GaugeTimeSeries from opentelemetry.metrics.time_series import MeasureTimeSeries from opentelemetry.trace import SpanContext +from typing import List, Union LabelKeys = List['LabelKey'] LabelValues = List['LabelValue'] diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index dc9840b53ca..930523e0014 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -15,8 +15,8 @@ # pylint: skip-file from opentelemetry.metrics import LabelKey from opentelemetry.metrics import LabelValue -from opentelemetry.metrics import Meter from opentelemetry.metrics import MeasureBatch +from opentelemetry.metrics import Meter from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() From baa3a323f8e19e5d17f3b8c1da00c23d75eec3a7 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 22 Aug 2019 16:39:08 -0700 Subject: [PATCH 25/41] fix imports --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3e63f40ff9b..8edf0efa203 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -27,13 +27,16 @@ """ -from abc import ABC, abstractmethod +from abc import ABC +from abc import abstractmethod +from typing import List +from typing import Union + from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import CounterTimeSeries from opentelemetry.metrics.time_series import GaugeTimeSeries from opentelemetry.metrics.time_series import MeasureTimeSeries from opentelemetry.trace import SpanContext -from typing import List, Union LabelKeys = List['LabelKey'] LabelValues = List['LabelValue'] From 211b20cdcd98a7f9d9cfd615b3a91e90b8776156 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 3 Sep 2019 11:22:07 -0700 Subject: [PATCH 26/41] LabelValues to str --- .../src/opentelemetry/metrics/__init__.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 8edf0efa203..48c6d3f4694 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -39,7 +39,7 @@ from opentelemetry.trace import SpanContext LabelKeys = List['LabelKey'] -LabelValues = List['LabelValue'] +LabelValues = List[str] class Meter: @@ -212,7 +212,7 @@ def get_or_create_time_series(self, overrides this function. Args: - label_values: A map of `LabelValue` s that will be associated + label_values: A list of label values that will be associated with the return timeseries. """ @@ -220,7 +220,7 @@ def remove_time_series(self, label_values: LabelValues) -> None: """Removes the timeseries from the Metric, if present. - The timeseries with matching `LabelValue` s will be removed. + The timeseries with matching label values will be removed. args: label_values: The list of label values to match against. @@ -332,13 +332,3 @@ def __init__(self, self.key = key self.description = description - -class LabelValue: - """The label values associated with a TimeSeries. - - :type value: str - :param value: the value for the label - """ - def __init__(self, - value: str) -> None: - self.value = value From bffe040b3e1400b58b2e2a042d647204e01006af Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 3 Sep 2019 11:35:51 -0700 Subject: [PATCH 27/41] Black formatting --- .../src/opentelemetry/metrics/__init__.py | 152 +++++++++--------- .../metrics/examples/pre_aggregated.py | 15 +- .../src/opentelemetry/metrics/examples/raw.py | 22 +-- .../src/opentelemetry/metrics/time_series.py | 3 - 4 files changed, 98 insertions(+), 94 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 48c6d3f4694..3ec69159939 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -38,7 +38,7 @@ from opentelemetry.metrics.time_series import MeasureTimeSeries from opentelemetry.trace import SpanContext -LabelKeys = List['LabelKey'] +LabelKeys = List["LabelKey"] LabelValues = List[str] @@ -50,13 +50,14 @@ class Meter: for the exported metric are deferred. """ - def create_float_counter(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - span_context: SpanContext = None - ) -> 'CounterFloat': + def create_float_counter( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + span_context: SpanContext = None, + ) -> "CounterFloat": """Creates a counter type metric that contains float values. Args: @@ -72,13 +73,14 @@ def create_float_counter(self, Returns: A new `CounterFloat` """ - def create_int_counter(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - span_context: SpanContext = None - ) -> 'CounterInt': + def create_int_counter( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + span_context: SpanContext = None, + ) -> "CounterInt": """Creates a counter type metric that contains int values. Args: @@ -95,13 +97,14 @@ def create_int_counter(self, A new `CounterInt` """ - def create_float_gauge(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - span_context: SpanContext = None - ) -> 'GaugeFloat': + def create_float_gauge( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + span_context: SpanContext = None, + ) -> "GaugeFloat": """Creates a gauge type metric that contains float values. Args: @@ -118,13 +121,14 @@ def create_float_gauge(self, A new `GaugeFloat` """ - def create_int_gauge(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - span_context: SpanContext = None - ) -> 'GaugeInt': + def create_int_gauge( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + span_context: SpanContext = None, + ) -> "GaugeInt": """Creates a gauge type metric that contains int values. Args: @@ -141,14 +145,15 @@ def create_int_gauge(self, A new `GaugeInt` """ - def create_int_measure(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - aggregation: 'Aggregation', - span_context: SpanContext = None, - ) -> 'MeasureInt': + def create_int_measure( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + aggregation: "Aggregation", + span_context: SpanContext = None, + ) -> "MeasureInt": """Creates a measure used to record raw int values. Args: @@ -166,14 +171,15 @@ def create_int_measure(self, A new `MeasureInt` """ - def create_float_measure(self, - name: str, - description: str, - unit: str, - label_keys: LabelKeys, - aggregation: 'Aggregation', - span_context: SpanContext = None, - ) -> 'MeasureFloat': + def create_float_measure( + self, + name: str, + description: str, + unit: str, + label_keys: LabelKeys, + aggregation: "Aggregation", + span_context: SpanContext = None, + ) -> "MeasureFloat": """Creates a Measure used to record raw float values. Args: @@ -200,9 +206,7 @@ class Metric(ABC): """ @abstractmethod - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'object': + 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 @@ -216,8 +220,7 @@ def get_or_create_time_series(self, with the return timeseries. """ - def remove_time_series(self, - label_values: LabelValues) -> None: + 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. @@ -237,9 +240,9 @@ class CounterFloat(Metric): Cumulative values cannot be negative. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'CounterTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "CounterTimeSeries": """Gets a `CounterTimeSeries` with a cumulative float value.""" @@ -250,9 +253,9 @@ class CounterInt(Metric): Cumulative values cannot be negative. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'CounterTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "CounterTimeSeries": """Gets a `CounterTimeSeries` with a cumulative int value.""" @@ -262,9 +265,9 @@ class GaugeFloat(Metric): Cumulative value can go both up and down. Values can be negative. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'GaugeTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "GaugeTimeSeries": """Gets a `GaugeTimeSeries` with a cumulative float value.""" @@ -274,9 +277,9 @@ class GaugeInt(Metric): Cumulative value can go both up and down. Values can be negative. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'GaugeTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "GaugeTimeSeries": """Gets a `GaugeTimeSeries` with a cumulative int value.""" @@ -286,9 +289,9 @@ class MeasureFloat(Metric): Measure metrics represent raw statistics that are recorded. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'MeasureTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "MeasureTimeSeries": """Gets a `MeasureTimeSeries` with a cumulated float value.""" @@ -298,17 +301,16 @@ class MeasureInt(Metric): Measure metrics represent raw statistics that are recorded. """ - def get_or_create_time_series(self, - label_values: LabelValues - ) -> 'MeasureTimeSeries': + def get_or_create_time_series( + self, label_values: LabelValues + ) -> "MeasureTimeSeries": """Gets a `MeasureTimeSeries` with a cumulated int value.""" class MeasureBatch: - - def record(self, - metrics: List['Metric'], - values: List[Union[float, int]]) -> None: + def record( + self, metrics: List["Metric"], values: List[Union[float, int]] + ) -> None: """Records multiple observed values simultaneously. Args: @@ -326,9 +328,7 @@ class LabelKey: :type description: str :param description: description of the label """ - def __init__(self, - key: str, - description: str) -> None: + + def __init__(self, key: str, description: str) -> None: self.key = key self.description = description - diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index 61feb2d239f..1f48d56f825 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -18,12 +18,15 @@ from opentelemetry.metrics import 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_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")] diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 930523e0014..6eac549d095 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -20,13 +20,16 @@ from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() -LABEL_KEYS = [LabelKey("environment", - "the environment the application is running in")] -MEASURE = METER.create_float_measure("idle_cpu_percentage", - "cpu idle over time", - "percentage", - LABEL_KEYS, - LastValueAggregation) +LABEL_KEYS = [ + LabelKey("environment", "the environment the application is running in") +] +MEASURE = METER.create_float_measure( + "idle_cpu_percentage", + "cpu idle over time", + "percentage", + LABEL_KEYS, + LastValueAggregation, +) LABEL_VALUE_TESTING = [LabelValue("Testing")] LABEL_VALUE_STAGING = [LabelValue("Staging")] @@ -40,5 +43,6 @@ # record multiple observed values BATCH = MeasureBatch() -BATCH.record([(MEASURE_METRIC_TESTING, STATISTIC), - (MEASURE_METRIC_STAGING, STATISTIC)]) +BATCH.record( + [(MEASURE_METRIC_TESTING, STATISTIC), (MEASURE_METRIC_STAGING, STATISTIC)] +) diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index b6cc5af5ccd..b14ef973ad4 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -16,7 +16,6 @@ class CounterTimeSeries: - def add(self, value: typing.Union[float, int]) -> None: """Adds the given value to the current value. Cannot be negative.""" @@ -28,13 +27,11 @@ def set(self, value: typing.Union[float, int]) -> None: class GaugeTimeSeries: - def set(self, value: typing.Union[float, int]) -> None: """Sets the current value to the given value. Can be negative.""" class MeasureTimeSeries: - def record(self, value: typing.Union[float, int]) -> None: """Records the given value to this measure. From 0759b9afdc3536aec24303a430ecaa87988b5b45 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 3 Sep 2019 11:44:01 -0700 Subject: [PATCH 28/41] fix isort --- .../src/opentelemetry/metrics/__init__.py | 14 +++++++------- .../metrics/examples/pre_aggregated.py | 4 +--- .../src/opentelemetry/metrics/examples/raw.py | 5 +---- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 3ec69159939..d6e03f77419 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -27,15 +27,15 @@ """ -from abc import ABC -from abc import abstractmethod -from typing import List -from typing import Union +from abc import ABC, abstractmethod +from typing import List, Union from opentelemetry.metrics.aggregation import Aggregation -from opentelemetry.metrics.time_series import CounterTimeSeries -from opentelemetry.metrics.time_series import GaugeTimeSeries -from opentelemetry.metrics.time_series import MeasureTimeSeries +from opentelemetry.metrics.time_series import ( + CounterTimeSeries, + GaugeTimeSeries, + MeasureTimeSeries, +) from opentelemetry.trace import SpanContext LabelKeys = List["LabelKey"] diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index 1f48d56f825..c9c55f01b81 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -13,9 +13,7 @@ # limitations under the License. # pylint: skip-file -from opentelemetry.metrics import LabelKey -from opentelemetry.metrics import LabelValue -from opentelemetry.metrics import Meter +from opentelemetry.metrics import LabelKey, LabelValue, Meter METER = Meter() LABEL_KEYS = [ diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 6eac549d095..3c82e14d536 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -13,10 +13,7 @@ # limitations under the License. # pylint: skip-file -from opentelemetry.metrics import LabelKey -from opentelemetry.metrics import LabelValue -from opentelemetry.metrics import MeasureBatch -from opentelemetry.metrics import Meter +from opentelemetry.metrics import LabelKey, LabelValue, MeasureBatch, Meter from opentelemetry.metrics.aggregation import LastValueAggregation METER = Meter() From 44d62f8fe60fe7437bfa6d87c4c0e67311136b7c Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 12 Sep 2019 14:00:33 -0700 Subject: [PATCH 29/41] Remove aggregation --- .../src/opentelemetry/metrics/__init__.py | 5 --- .../src/opentelemetry/metrics/aggregation.py | 33 ------------------- 2 files changed, 38 deletions(-) delete mode 100644 opentelemetry-api/src/opentelemetry/metrics/aggregation.py diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index d6e03f77419..75f56f05457 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -30,7 +30,6 @@ from abc import ABC, abstractmethod from typing import List, Union -from opentelemetry.metrics.aggregation import Aggregation from opentelemetry.metrics.time_series import ( CounterTimeSeries, GaugeTimeSeries, @@ -151,7 +150,6 @@ def create_int_measure( description: str, unit: str, label_keys: LabelKeys, - aggregation: "Aggregation", span_context: SpanContext = None, ) -> "MeasureInt": """Creates a measure used to record raw int values. @@ -163,7 +161,6 @@ def create_int_measure( 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. - aggregation: The type of aggregation to use for this metric. span_context: The `SpanContext` that identifies the `Span` that the metric is associated with. @@ -177,7 +174,6 @@ def create_float_measure( description: str, unit: str, label_keys: LabelKeys, - aggregation: "Aggregation", span_context: SpanContext = None, ) -> "MeasureFloat": """Creates a Measure used to record raw float values. @@ -189,7 +185,6 @@ def create_float_measure( 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. - aggregation: The type of aggregation to use for this metric. span_context: The `SpanContext` that identifies the `Span` that the metric is associated with. diff --git a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py b/opentelemetry-api/src/opentelemetry/metrics/aggregation.py deleted file mode 100644 index 36f744b6146..00000000000 --- a/opentelemetry-api/src/opentelemetry/metrics/aggregation.py +++ /dev/null @@ -1,33 +0,0 @@ -# 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. - - -class Aggregation: - """The base class for all aggregation types.""" - - -class CountAggregation(Aggregation): - """An aggregation representing a count of values.""" - - -class DistributonAggregation(Aggregation): - """An aggregation representing a distribution.""" - - -class LastValueAggregation(Aggregation): - """An aggregation representing the last value.""" - - -class SumAggregation(Aggregation): - """An aggregation representing a sum of values.""" From c5ab2df38927c07774749789d356a8985d60a09b Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 12 Sep 2019 14:09:59 -0700 Subject: [PATCH 30/41] Fix names --- .../src/opentelemetry/metrics/__init__.py | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 75f56f05457..45e12f2b74b 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -56,7 +56,7 @@ def create_float_counter( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "CounterFloat": + ) -> "FloatCounter": """Creates a counter type metric that contains float values. Args: @@ -69,7 +69,7 @@ def create_float_counter( span_context: The `SpanContext` that identifies the `Span` that the metric is associated with. - Returns: A new `CounterFloat` + Returns: A new `FloatCounter` """ def create_int_counter( @@ -79,7 +79,7 @@ def create_int_counter( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "CounterInt": + ) -> "IntCounter": """Creates a counter type metric that contains int values. Args: @@ -93,7 +93,7 @@ def create_int_counter( that the metric is associated with. Returns: - A new `CounterInt` + A new `IntCounter` """ def create_float_gauge( @@ -103,7 +103,7 @@ def create_float_gauge( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "GaugeFloat": + ) -> "FloatGauge": """Creates a gauge type metric that contains float values. Args: @@ -117,7 +117,7 @@ def create_float_gauge( that the metric is associated with. Returns: - A new `GaugeFloat` + A new `FloatGauge` """ def create_int_gauge( @@ -127,7 +127,7 @@ def create_int_gauge( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "GaugeInt": + ) -> "IntGauge": """Creates a gauge type metric that contains int values. Args: @@ -141,7 +141,7 @@ def create_int_gauge( that the metric is associated with. Returns: - A new `GaugeInt` + A new `IntGauge` """ def create_int_measure( @@ -151,7 +151,7 @@ def create_int_measure( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "MeasureInt": + ) -> "IntMeasure": """Creates a measure used to record raw int values. Args: @@ -165,7 +165,7 @@ def create_int_measure( that the metric is associated with. Returns: - A new `MeasureInt` + A new `IntMeasure` """ def create_float_measure( @@ -175,7 +175,7 @@ def create_float_measure( unit: str, label_keys: LabelKeys, span_context: SpanContext = None, - ) -> "MeasureFloat": + ) -> "FloatMeasure": """Creates a Measure used to record raw float values. Args: @@ -189,7 +189,7 @@ def create_float_measure( that the metric is associated with. Returns: - A new `MeasureFloat` + A new `FloatMeasure` """ @@ -228,7 +228,7 @@ def clear(self) -> None: """Removes all timeseries from the `Metric`.""" -class CounterFloat(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. @@ -241,7 +241,7 @@ def get_or_create_time_series( """Gets a `CounterTimeSeries` with a cumulative float value.""" -class CounterInt(Metric): +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. @@ -254,7 +254,7 @@ def get_or_create_time_series( """Gets a `CounterTimeSeries` with a cumulative int value.""" -class GaugeFloat(Metric): +class FloatGauge(Metric): """A gauge type metric that holds float values. Cumulative value can go both up and down. Values can be negative. @@ -266,7 +266,7 @@ def get_or_create_time_series( """Gets a `GaugeTimeSeries` with a cumulative float value.""" -class GaugeInt(Metric): +class IntGauge(Metric): """A gauge type metric that holds int values. Cumulative value can go both up and down. Values can be negative. @@ -278,7 +278,7 @@ def get_or_create_time_series( """Gets a `GaugeTimeSeries` with a cumulative int value.""" -class MeasureFloat(Metric): +class FloatMeasure(Metric): """A measure type metric that holds float values. Measure metrics represent raw statistics that are recorded. @@ -290,7 +290,7 @@ def get_or_create_time_series( """Gets a `MeasureTimeSeries` with a cumulated float value.""" -class MeasureInt(Metric): +class IntMeasure(Metric): """A measure type metric that holds int values. Measure metrics represent raw statistics that are recorded. @@ -302,18 +302,6 @@ def get_or_create_time_series( """Gets a `MeasureTimeSeries` with a cumulated int value.""" -class MeasureBatch: - def record( - self, metrics: List["Metric"], values: List[Union[float, int]] - ) -> None: - """Records multiple observed values simultaneously. - - Args: - metric: A list containing the `Metric` s to be recorded - values: A list containing the values to record - """ - - class LabelKey: """The label keys associated with the metric. From 50d2de55ce6c1b7b6179c31d8883729b105702eb Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 12 Sep 2019 14:12:21 -0700 Subject: [PATCH 31/41] Remove aggregation from docs --- docs/opentelemetry.metrics.aggregation.rst | 5 ----- docs/opentelemetry.metrics.rst | 1 - 2 files changed, 6 deletions(-) delete mode 100644 docs/opentelemetry.metrics.aggregation.rst diff --git a/docs/opentelemetry.metrics.aggregation.rst b/docs/opentelemetry.metrics.aggregation.rst deleted file mode 100644 index 99848381e3e..00000000000 --- a/docs/opentelemetry.metrics.aggregation.rst +++ /dev/null @@ -1,5 +0,0 @@ -opentelemetry.metrics.aggregation module -========================================== - -.. automodule:: opentelemetry.metrics.aggregation - diff --git a/docs/opentelemetry.metrics.rst b/docs/opentelemetry.metrics.rst index b3886271335..2d025d3197f 100644 --- a/docs/opentelemetry.metrics.rst +++ b/docs/opentelemetry.metrics.rst @@ -6,7 +6,6 @@ Submodules .. toctree:: - opentelemetry.metrics.aggregation opentelemetry.metrics.time_series Module contents From d79bc7d8eb4b01ee4c0c98faec91fa478699fa23 Mon Sep 17 00:00:00 2001 From: Leighton Date: Thu, 12 Sep 2019 14:20:30 -0700 Subject: [PATCH 32/41] Fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 45e12f2b74b..68563bd4928 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -28,7 +28,7 @@ """ from abc import ABC, abstractmethod -from typing import List, Union +from typing import List from opentelemetry.metrics.time_series import ( CounterTimeSeries, From 7fb7cdfacda9b66e5fce44ecc5d0345173dd1b75 Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 10:29:02 -0700 Subject: [PATCH 33/41] metric changes --- .../src/opentelemetry/metrics/__init__.py | 321 +++++++----------- .../metrics/examples/pre_aggregated.py | 16 +- .../src/opentelemetry/metrics/examples/raw.py | 25 +- .../src/opentelemetry/metrics/time_series.py | 14 +- 4 files changed, 138 insertions(+), 238 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 68563bd4928..f496b838a31 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -26,9 +26,9 @@ """ - from abc import ABC, abstractmethod -from typing import List +from enum import Enum +from typing import List, Union from opentelemetry.metrics.time_series import ( CounterTimeSeries, @@ -37,9 +37,6 @@ ) from opentelemetry.trace import SpanContext -LabelKeys = List["LabelKey"] -LabelValues = List[str] - class Meter: """An interface to allow the recording of metrics. @@ -48,149 +45,107 @@ class Meter: counter), or raw values (measure) in which the aggregation and labels for the exported metric are deferred. """ + # TODO: RecordBatch + + +class ValueType(Enum): + FLOAT = 0 + INT = 1 + + +def create_counter( + name: str, + description: str, + unit: str, + value_type: "ValueType", + bidirectional: bool = False, + label_keys: List[str] = None, + span_context: SpanContext = None, +) -> Union[FloatCounter, IntCounter]: + """Creates a counter metric with type value_type. + + By default, counter values can only go up (unidirectional). The API + should reject negative inputs to unidirectional counter metric. + Counter metrics have a bidirectional option to allow for negative + inputs. + + Args: + name: The name of the counter. + description: Human readable description of the metric. + unit: Unit of the metric values. + value_type: The type of values being recorded by the metric. + bidirectional: Set to true to allow negative inputs. + 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 counter metric with corresponding value_type. + """ - 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. +def create_gauge( + self, + name: str, + description: str, + unit: str, + value_type: "ValueType", + unidirectional: bool = False, + label_keys: List[str] = None, + span_context: SpanContext = None, +) -> Union[FloatGauge, IntGauge]: + """Creates a gauge metric with type value_type. + + By default, gauge values can go both up and down (bidirectional). The API + allows for an optional unidirectional flag, in which when set will reject + descending update values. + + Args: + name: The name of the gauge. + description: Human readable description of the metric. + unit: Unit of the metric values. + value_type: The type of values being recorded by the metric. + unidirectional: Set to true to reject negative inputs. + 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 gauge metric with corresponding value_type. + """ - 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` - """ +def create_measure( + self, + name: str, + description: str, + unit: str, + value_type: "ValueType", + non_negative: bool = False, + label_keys: List[str] = None, + span_context: SpanContext = None, +) -> Union[FloatMeasure, IntMeasure]: + """Creates a measure metric with type value_type. + + Measure metrics represent raw statistics that are recorded. As an option, + measure metrics can be declared as non-negative. The API will reject + negative metric events for non-negative measures. + + Args: + name: The name of the measure. + description: Human readable description of the metric. + unit: Unit of the metric values. + value_type: The type of values being recorded by the metric. + non_negative: Set to true to reject negative inputs. + 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 measure metric with corresponding value_type. + """ class Metric(ABC): @@ -201,8 +156,8 @@ class Metric(ABC): """ @abstractmethod - def get_or_create_time_series(self, label_values: LabelValues) -> "object": - """Gets and returns a timeseries, a container for a cumulative value. + def get_or_create_time_series(self, label_values: List[str]) -> "object": + """Gets and returns a timeseries, a container for a counter value. If the provided label values are not already associated with this metric, a new timeseries is returned, otherwise it returns the existing @@ -215,7 +170,7 @@ def get_or_create_time_series(self, label_values: LabelValues) -> "object": with the return timeseries. """ - def remove_time_series(self, label_values: LabelValues) -> None: + def remove_time_series(self, label_values: List[str]) -> None: """Removes the timeseries from the Metric, if present. The timeseries with matching label values will be removed. @@ -229,89 +184,55 @@ def clear(self) -> None: 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. - """ + """A counter type metric that holds float values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str] ) -> "CounterTimeSeries": - """Gets a `CounterTimeSeries` with a cumulative float value.""" + """Gets a `CounterTimeSeries` with a 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. - """ + """A counter type metric that holds int values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str], ) -> "CounterTimeSeries": - """Gets a `CounterTimeSeries` with a cumulative int value.""" + """Gets a `CounterTimeSeries` with an 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. - """ + """A gauge type metric that holds float values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str] ) -> "GaugeTimeSeries": - """Gets a `GaugeTimeSeries` with a cumulative float value.""" + """Gets a `GaugeTimeSeries` with a 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. - """ + """A gauge type metric that holds int values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str] ) -> "GaugeTimeSeries": - """Gets a `GaugeTimeSeries` with a cumulative int value.""" + """Gets a `GaugeTimeSeries` with an int value.""" class FloatMeasure(Metric): - """A measure type metric that holds float values. - - Measure metrics represent raw statistics that are recorded. - """ + """A measure type metric that holds float values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str] ) -> "MeasureTimeSeries": - """Gets a `MeasureTimeSeries` with a cumulated float value.""" + """Gets a `MeasureTimeSeries` with a float value.""" class IntMeasure(Metric): - """A measure type metric that holds int values. - - Measure metrics represent raw statistics that are recorded. - """ + """A measure type metric that holds int values.""" def get_or_create_time_series( - self, label_values: LabelValues + self, label_values: List[str] ) -> "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 - """ + """Gets a `MeasureTimeSeries` with an int value.""" - def __init__(self, key: str, description: str) -> None: - self.key = key - self.description = description diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index c9c55f01b81..065c8e62bbb 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -13,24 +13,20 @@ # limitations under the License. # pylint: skip-file -from opentelemetry.metrics import LabelKey, LabelValue, Meter +from opentelemetry import metrics 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", "sum numbers over time", "number", - LABEL_KEYS, + metrics.ValueType.FLOAT, + ["environment"], ) -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) +METRIC_TESTING = COUNTER.get_or_create_time_series("Testing") +METRIC_STAGING = COUNTER.get_or_create_time_series("Staging") for i in range(100): METRIC_STAGING.add(i) diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py index 3c82e14d536..e4035972c05 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/raw.py @@ -13,33 +13,22 @@ # limitations under the License. # pylint: skip-file -from opentelemetry.metrics import LabelKey, LabelValue, MeasureBatch, Meter -from opentelemetry.metrics.aggregation import LastValueAggregation +from opentelemetry import metrics -METER = Meter() -LABEL_KEYS = [ - LabelKey("environment", "the environment the application is running in") -] -MEASURE = METER.create_float_measure( +METER = metrics.Meter() +MEASURE = metrics.create_measure( "idle_cpu_percentage", "cpu idle over time", "percentage", - LABEL_KEYS, - LastValueAggregation, + metrics.ValueType.FLOAT, + ["environment"], ) -LABEL_VALUE_TESTING = [LabelValue("Testing")] -LABEL_VALUE_STAGING = [LabelValue("Staging")] # Metrics sent to some exporter -MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series(LABEL_VALUE_TESTING) -MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series(LABEL_VALUE_STAGING) +MEASURE_METRIC_TESTING = MEASURE.get_or_create_time_series("Testing") +MEASURE_METRIC_STAGING = MEASURE.get_or_create_time_series("Staging") # record individual measures STATISTIC = 100 MEASURE_METRIC_STAGING.record(STATISTIC) -# record multiple observed values -BATCH = MeasureBatch() -BATCH.record( - [(MEASURE_METRIC_TESTING, STATISTIC), (MEASURE_METRIC_STAGING, STATISTIC)] -) diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index b14ef973ad4..22ddf71ad11 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -17,12 +17,9 @@ class CounterTimeSeries: def add(self, value: typing.Union[float, int]) -> None: - """Adds the given value to the current value. Cannot be negative.""" - - def set(self, value: typing.Union[float, int]) -> None: - """Sets the current value to the given value. - - The given value must be larger than the current recorded value. + """Adds the given value to the current value. + + The input value cannot be negative if not bidirectional. """ @@ -33,7 +30,4 @@ def set(self, value: typing.Union[float, int]) -> None: class MeasureTimeSeries: def record(self, value: typing.Union[float, int]) -> None: - """Records the given value to this measure. - - Logic depends on type of aggregation used for this measure. - """ + """Records the given value to this measure.""" From 79322f5558d78e37f89f26d99a46145c17567abc Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 11:40:06 -0700 Subject: [PATCH 34/41] Typing --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index f496b838a31..4700d33983d 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -61,7 +61,7 @@ def create_counter( bidirectional: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, -) -> Union[FloatCounter, IntCounter]: +) -> Union["FloatCounter", "IntCounter"]: """Creates a counter metric with type value_type. By default, counter values can only go up (unidirectional). The API @@ -94,7 +94,7 @@ def create_gauge( unidirectional: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, -) -> Union[FloatGauge, IntGauge]: +) -> Union["FloatGauge", "IntGauge"]: """Creates a gauge metric with type value_type. By default, gauge values can go both up and down (bidirectional). The API @@ -125,7 +125,7 @@ def create_measure( non_negative: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, -) -> Union[FloatMeasure, IntMeasure]: +) -> Union["FloatMeasure", "IntMeasure"]: """Creates a measure metric with type value_type. Measure metrics represent raw statistics that are recorded. As an option, From f9c7cc3830946760ed8b2c10e0d21ea888ca4a80 Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 14:08:07 -0700 Subject: [PATCH 35/41] Fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index e597c7eee35..9a46e5e2348 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -45,6 +45,7 @@ class Meter: counter), or raw values (measure) in which the aggregation and labels for the exported metric are deferred. """ + # TODO: RecordBatch @@ -86,7 +87,6 @@ def create_counter( def create_gauge( - self, name: str, description: str, unit: str, @@ -116,8 +116,8 @@ def create_gauge( Returns: A new gauge metric with corresponding value_type. """ + def create_measure( - self, name: str, description: str, unit: str, @@ -196,7 +196,7 @@ class IntCounter(Metric): """A counter type metric that holds int values.""" def get_or_create_time_series( - self, label_values: List[str], + self, label_values: List[str] ) -> "CounterTimeSeries": """Gets a `CounterTimeSeries` with an int value.""" From 44659294737c5cd835eb564f7d2c4f4ce3e10350 Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 14:19:11 -0700 Subject: [PATCH 36/41] Fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- opentelemetry-api/src/opentelemetry/metrics/time_series.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 9a46e5e2348..1213c7abc93 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -37,7 +37,7 @@ ) from opentelemetry.trace import SpanContext - +#pylint: disable=unused-argument class Meter: """An interface to allow the recording of metrics. diff --git a/opentelemetry-api/src/opentelemetry/metrics/time_series.py b/opentelemetry-api/src/opentelemetry/metrics/time_series.py index 22ddf71ad11..25ad9efe775 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/time_series.py +++ b/opentelemetry-api/src/opentelemetry/metrics/time_series.py @@ -18,7 +18,7 @@ class CounterTimeSeries: def add(self, value: typing.Union[float, int]) -> None: """Adds the given value to the current value. - + The input value cannot be negative if not bidirectional. """ From 695e596449066e667d6c142aaf274d6d57095ea2 Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 14:25:47 -0700 Subject: [PATCH 37/41] Add space --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 1213c7abc93..5e080b0d040 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -37,7 +37,7 @@ ) from opentelemetry.trace import SpanContext -#pylint: disable=unused-argument +# pylint: disable=unused-argument class Meter: """An interface to allow the recording of metrics. From ee43e3945e05c40d813e254e0beec3a538bb77f3 Mon Sep 17 00:00:00 2001 From: Leighton Date: Fri, 13 Sep 2019 14:32:34 -0700 Subject: [PATCH 38/41] Fix lint --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 1 + .../src/opentelemetry/metrics/examples/pre_aggregated.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 5e080b0d040..a17d48e218f 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -37,6 +37,7 @@ ) from opentelemetry.trace import SpanContext + # pylint: disable=unused-argument class Meter: """An interface to allow the recording of metrics. diff --git a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py index 065c8e62bbb..a07610b2ea9 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py +++ b/opentelemetry-api/src/opentelemetry/metrics/examples/pre_aggregated.py @@ -15,7 +15,7 @@ # pylint: skip-file from opentelemetry import metrics -METER = Meter() +METER = metrics.Meter() COUNTER = METER.create_int_counter( "sum numbers", "sum numbers over time", From e59f7c4981b4592fde09de481f9597e65a985ea6 Mon Sep 17 00:00:00 2001 From: Leighton Date: Mon, 16 Sep 2019 12:07:26 -0700 Subject: [PATCH 39/41] fix comments --- opentelemetry-api/src/opentelemetry/metrics/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index a17d48e218f..af0da981bc7 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -153,12 +153,12 @@ 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. + time series that the metric holds. """ @abstractmethod def get_or_create_time_series(self, label_values: List[str]) -> "object": - """Gets and returns a timeseries, a container for a counter value. + """Gets a timeseries, used for repeated-use of metrics instruments. If the provided label values are not already associated with this metric, a new timeseries is returned, otherwise it returns the existing From f0cff872f161117f516edfceb1179f710d5eac93 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 17 Sep 2019 09:13:07 -0700 Subject: [PATCH 40/41] address comments --- .../src/opentelemetry/metrics/__init__.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index af0da981bc7..45a50b46fd9 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -67,7 +67,7 @@ def create_counter( """Creates a counter metric with type value_type. By default, counter values can only go up (unidirectional). The API - should reject negative inputs to unidirectional counter metric. + should reject negative inputs to unidirectional counter metrics. Counter metrics have a bidirectional option to allow for negative inputs. @@ -78,12 +78,12 @@ def create_counter( value_type: The type of values being recorded by the metric. bidirectional: Set to true to allow negative inputs. label_keys: list of keys for the labels with dynamic values. - Order of the list is important as the same order MUST be used + 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 counter metric with corresponding value_type. + Returns: A new counter metric for values of the given value_type. """ @@ -109,12 +109,12 @@ def create_gauge( value_type: The type of values being recorded by the metric. unidirectional: Set to true to reject negative inputs. label_keys: list of keys for the labels with dynamic values. - Order of the list is important as the same order MUST be used + 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 gauge metric with corresponding value_type. + Returns: A new gauge metric for values of the given value_type. """ @@ -140,12 +140,12 @@ def create_measure( value_type: The type of values being recorded by the metric. non_negative: Set to true to reject negative inputs. label_keys: list of keys for the labels with dynamic values. - Order of the list is important as the same order MUST be used + 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 measure metric with corresponding value_type. + Returns: A new measure metric for values of the given value_type. """ From 06fc1371e0c4a4fd67110c1be12ee14305e1a475 Mon Sep 17 00:00:00 2001 From: Leighton Date: Tue, 17 Sep 2019 13:37:39 -0700 Subject: [PATCH 41/41] fix comments --- .../src/opentelemetry/metrics/__init__.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/opentelemetry-api/src/opentelemetry/metrics/__init__.py b/opentelemetry-api/src/opentelemetry/metrics/__init__.py index 45a50b46fd9..94a7dc0e312 100644 --- a/opentelemetry-api/src/opentelemetry/metrics/__init__.py +++ b/opentelemetry-api/src/opentelemetry/metrics/__init__.py @@ -60,7 +60,7 @@ def create_counter( description: str, unit: str, value_type: "ValueType", - bidirectional: bool = False, + is_bidirectional: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, ) -> Union["FloatCounter", "IntCounter"]: @@ -76,7 +76,7 @@ def create_counter( description: Human readable description of the metric. unit: Unit of the metric values. value_type: The type of values being recorded by the metric. - bidirectional: Set to true to allow negative inputs. + is_bidirectional: Set to true to allow negative inputs. 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. @@ -92,7 +92,7 @@ def create_gauge( description: str, unit: str, value_type: "ValueType", - unidirectional: bool = False, + is_unidirectional: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, ) -> Union["FloatGauge", "IntGauge"]: @@ -107,7 +107,7 @@ def create_gauge( description: Human readable description of the metric. unit: Unit of the metric values. value_type: The type of values being recorded by the metric. - unidirectional: Set to true to reject negative inputs. + is_unidirectional: Set to true to reject negative inputs. 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. @@ -123,7 +123,7 @@ def create_measure( description: str, unit: str, value_type: "ValueType", - non_negative: bool = False, + is_non_negative: bool = False, label_keys: List[str] = None, span_context: SpanContext = None, ) -> Union["FloatMeasure", "IntMeasure"]: @@ -138,7 +138,7 @@ def create_measure( description: Human readable description of the metric. unit: Unit of the metric values. value_type: The type of values being recorded by the metric. - non_negative: Set to true to reject negative inputs. + is_non_negative: Set to true to reject negative inputs. 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.