Skip to content

Commit

Permalink
Instrument instances are always created through a Meter (#2844)
Browse files Browse the repository at this point in the history
* Instrument instances are always created through a Meter

* Fix lint and add changelog

* fix lint
  • Loading branch information
srikanthccv authored Aug 1, 2022
1 parent c9222bf commit 43288ca
Show file tree
Hide file tree
Showing 9 changed files with 309 additions and 185 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([#2754](https://github.com/open-telemetry/opentelemetry-python/pull/2754))
- Fix --insecure of CLI argument
([#2696](https://github.com/open-telemetry/opentelemetry-python/pull/2696))
- Instrument instances are always created through a Meter
([#2844](https://github.com/open-telemetry/opentelemetry-python/pull/2844))

## [1.12.0rc2-0.32b0](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v1.12.0rc2) - 2022-07-04

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@
)
from opentelemetry.metrics import UpDownCounter as APIUpDownCounter
from opentelemetry.sdk.metrics._internal.instrument import (
Counter,
Histogram,
ObservableCounter,
ObservableGauge,
ObservableUpDownCounter,
UpDownCounter,
_Counter,
_Histogram,
_ObservableCounter,
_ObservableGauge,
_ObservableUpDownCounter,
_UpDownCounter,
)
from opentelemetry.sdk.metrics._internal.measurement_consumer import (
MeasurementConsumer,
Expand Down Expand Up @@ -72,7 +72,7 @@ def create_counter(self, name, unit="", description="") -> APICounter:
(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(name, Counter, unit, description)
) = self._is_instrument_registered(name, _Counter, unit, description)

if is_instrument_registered:
# FIXME #2558 go through all views here and check if this
Expand All @@ -89,7 +89,7 @@ def create_counter(self, name, unit="", description="") -> APICounter:
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = Counter(
instrument = _Counter(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand All @@ -109,7 +109,7 @@ def create_up_down_counter(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(
name, UpDownCounter, unit, description
name, _UpDownCounter, unit, description
)

if is_instrument_registered:
Expand All @@ -127,7 +127,7 @@ def create_up_down_counter(
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = UpDownCounter(
instrument = _UpDownCounter(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand All @@ -147,7 +147,7 @@ def create_observable_counter(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(
name, ObservableCounter, unit, description
name, _ObservableCounter, unit, description
)

if is_instrument_registered:
Expand All @@ -165,7 +165,7 @@ def create_observable_counter(
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = ObservableCounter(
instrument = _ObservableCounter(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand All @@ -185,7 +185,7 @@ def create_histogram(self, name, unit="", description="") -> APIHistogram:
(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(name, Histogram, unit, description)
) = self._is_instrument_registered(name, _Histogram, unit, description)

if is_instrument_registered:
# FIXME #2558 go through all views here and check if this
Expand All @@ -202,7 +202,7 @@ def create_histogram(self, name, unit="", description="") -> APIHistogram:
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = Histogram(
instrument = _Histogram(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand All @@ -221,7 +221,7 @@ def create_observable_gauge(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(
name, ObservableGauge, unit, description
name, _ObservableGauge, unit, description
)

if is_instrument_registered:
Expand All @@ -239,7 +239,7 @@ def create_observable_gauge(
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = ObservableGauge(
instrument = _ObservableGauge(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand All @@ -261,7 +261,9 @@ def create_observable_up_down_counter(
(
is_instrument_registered,
instrument_id,
) = self._is_instrument_registered(name, Counter, unit, description)
) = self._is_instrument_registered(
name, _ObservableUpDownCounter, unit, description
)

if is_instrument_registered:
# FIXME #2558 go through all views here and check if this
Expand All @@ -278,7 +280,7 @@ def create_observable_up_down_counter(
with self._instrument_id_instrument_lock:
return self._instrument_id_instrument[instrument_id]

instrument = ObservableUpDownCounter(
instrument = _ObservableUpDownCounter(
name,
self._instrumentation_scope,
self._measurement_consumer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@
ObservableGauge,
ObservableUpDownCounter,
UpDownCounter,
_Counter,
_Histogram,
_ObservableCounter,
_ObservableGauge,
_ObservableUpDownCounter,
_UpDownCounter,
)
from opentelemetry.sdk.metrics._internal.point import MetricsData
from opentelemetry.util._once import Once
Expand Down Expand Up @@ -164,6 +170,7 @@ class MetricReader(ABC):
# FIXME add :std:envvar:`OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE`
# to the end of the documentation paragraph above.

# pylint: disable=too-many-branches
def __init__(
self,
preferred_temporality: Dict[type, AggregationTemporality] = None,
Expand All @@ -189,22 +196,22 @@ def __init__(
== "DELTA"
):
self._instrument_class_temporality = {
Counter: AggregationTemporality.DELTA,
UpDownCounter: AggregationTemporality.CUMULATIVE,
Histogram: AggregationTemporality.DELTA,
ObservableCounter: AggregationTemporality.DELTA,
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
ObservableGauge: AggregationTemporality.CUMULATIVE,
_Counter: AggregationTemporality.DELTA,
_UpDownCounter: AggregationTemporality.CUMULATIVE,
_Histogram: AggregationTemporality.DELTA,
_ObservableCounter: AggregationTemporality.DELTA,
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
_ObservableGauge: AggregationTemporality.CUMULATIVE,
}

else:
self._instrument_class_temporality = {
Counter: AggregationTemporality.CUMULATIVE,
UpDownCounter: AggregationTemporality.CUMULATIVE,
Histogram: AggregationTemporality.CUMULATIVE,
ObservableCounter: AggregationTemporality.CUMULATIVE,
ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
ObservableGauge: AggregationTemporality.CUMULATIVE,
_Counter: AggregationTemporality.CUMULATIVE,
_UpDownCounter: AggregationTemporality.CUMULATIVE,
_Histogram: AggregationTemporality.CUMULATIVE,
_ObservableCounter: AggregationTemporality.CUMULATIVE,
_ObservableUpDownCounter: AggregationTemporality.CUMULATIVE,
_ObservableGauge: AggregationTemporality.CUMULATIVE,
}

if preferred_temporality is not None:
Expand All @@ -217,18 +224,69 @@ def __init__(
f"Invalid temporality value found {temporality}"
)

self._instrument_class_temporality.update(preferred_temporality or {})
if preferred_temporality is not None:
for typ, temporality in preferred_temporality.items():
if typ is Counter:
self._instrument_class_temporality[_Counter] = temporality
elif typ is UpDownCounter:
self._instrument_class_temporality[
_UpDownCounter
] = temporality
elif typ is Histogram:
self._instrument_class_temporality[
_Histogram
] = temporality
elif typ is ObservableCounter:
self._instrument_class_temporality[
_ObservableCounter
] = temporality
elif typ is ObservableUpDownCounter:
self._instrument_class_temporality[
_ObservableUpDownCounter
] = temporality
elif typ is ObservableGauge:
self._instrument_class_temporality[
_ObservableGauge
] = temporality
else:
raise Exception(f"Invalid instrument class found {typ}")

self._preferred_temporality = preferred_temporality
self._instrument_class_aggregation = {
Counter: DefaultAggregation(),
UpDownCounter: DefaultAggregation(),
Histogram: DefaultAggregation(),
ObservableCounter: DefaultAggregation(),
ObservableUpDownCounter: DefaultAggregation(),
ObservableGauge: DefaultAggregation(),
_Counter: DefaultAggregation(),
_UpDownCounter: DefaultAggregation(),
_Histogram: DefaultAggregation(),
_ObservableCounter: DefaultAggregation(),
_ObservableUpDownCounter: DefaultAggregation(),
_ObservableGauge: DefaultAggregation(),
}

self._instrument_class_aggregation.update(preferred_aggregation or {})
if preferred_aggregation is not None:
for typ, aggregation in preferred_aggregation.items():
if typ is Counter:
self._instrument_class_aggregation[_Counter] = aggregation
elif typ is UpDownCounter:
self._instrument_class_aggregation[
_UpDownCounter
] = aggregation
elif typ is Histogram:
self._instrument_class_aggregation[
_Histogram
] = aggregation
elif typ is ObservableCounter:
self._instrument_class_aggregation[
_ObservableCounter
] = aggregation
elif typ is ObservableUpDownCounter:
self._instrument_class_aggregation[
_ObservableUpDownCounter
] = aggregation
elif typ is ObservableGauge:
self._instrument_class_aggregation[
_ObservableGauge
] = aggregation
else:
raise Exception(f"Invalid instrument class found {typ}")

@final
def collect(self, timeout_millis: float = 10_000) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ def callback(


class Counter(_Synchronous, APICounter):
def __new__(cls, *args, **kwargs):
if cls is Counter:
raise TypeError("Counter must be instantiated via a meter.")
return super().__new__(cls)

def add(
self, amount: Union[int, float], attributes: Dict[str, str] = None
):
Expand All @@ -146,6 +151,11 @@ def add(


class UpDownCounter(_Synchronous, APIUpDownCounter):
def __new__(cls, *args, **kwargs):
if cls is UpDownCounter:
raise TypeError("UpDownCounter must be instantiated via a meter.")
return super().__new__(cls)

def add(
self, amount: Union[int, float], attributes: Dict[str, str] = None
):
Expand All @@ -155,14 +165,29 @@ def add(


class ObservableCounter(_Asynchronous, APIObservableCounter):
pass
def __new__(cls, *args, **kwargs):
if cls is ObservableCounter:
raise TypeError(
"ObservableCounter must be instantiated via a meter."
)
return super().__new__(cls)


class ObservableUpDownCounter(_Asynchronous, APIObservableUpDownCounter):
pass
def __new__(cls, *args, **kwargs):
if cls is ObservableUpDownCounter:
raise TypeError(
"ObservableUpDownCounter must be instantiated via a meter."
)
return super().__new__(cls)


class Histogram(_Synchronous, APIHistogram):
def __new__(cls, *args, **kwargs):
if cls is Histogram:
raise TypeError("Histogram must be instantiated via a meter.")
return super().__new__(cls)

def record(
self, amount: Union[int, float], attributes: Dict[str, str] = None
):
Expand All @@ -178,4 +203,34 @@ def record(


class ObservableGauge(_Asynchronous, APIObservableGauge):
def __new__(cls, *args, **kwargs):
if cls is ObservableGauge:
raise TypeError(
"ObservableGauge must be instantiated via a meter."
)
return super().__new__(cls)


# Below classes exist to prevent the direct instantiation
class _Counter(Counter):
pass


class _UpDownCounter(UpDownCounter):
pass


class _ObservableCounter(ObservableCounter):
pass


class _ObservableUpDownCounter(ObservableUpDownCounter):
pass


class _Histogram(Histogram):
pass


class _ObservableGauge(ObservableGauge):
pass
Loading

0 comments on commit 43288ca

Please sign in to comment.