Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Refactor Meter and MeterProvider #2296

Merged
merged 13 commits into from
Dec 8, 2021
1 change: 0 additions & 1 deletion opentelemetry-api/src/opentelemetry/util/_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
def _time_ns() -> int:
return int(time() * 1e9)


ocelotl marked this conversation as resolved.
Show resolved Hide resolved
else:
from time import time_ns

Expand Down
177 changes: 76 additions & 101 deletions opentelemetry-sdk/src/opentelemetry/sdk/_metrics/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,36 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable=function-redefined,too-many-ancestors

from abc import ABC, abstractmethod
from atexit import register, unregister
from logging import getLogger
from typing import Optional
from threading import Lock
from typing import Optional, Sequence

from opentelemetry._metrics import Meter as APIMeter
from opentelemetry._metrics import MeterProvider as APIMeterProvider
from opentelemetry._metrics import _DefaultMeter
from opentelemetry._metrics.instrument import Counter as APICounter
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
from opentelemetry._metrics.instrument import Histogram as APIHistogram
from opentelemetry._metrics.instrument import (
ObservableCounter as APIObservableCounter,
)
from opentelemetry._metrics.instrument import (
ObservableGauge as APIObservableGauge,
)
from opentelemetry._metrics.instrument import (
ObservableUpDownCounter as APIObservableUpDownCounter,
)
from opentelemetry._metrics.instrument import UpDownCounter as APIUpDownCounter
from opentelemetry.sdk._metrics.export.metric_exporter import MetricExporter
from opentelemetry.sdk._metrics.instrument import (
Counter,
Histogram,
ObservableCounter,
ObservableGauge,
ObservableUpDownCounter,
UpDownCounter,
)
from opentelemetry.sdk._metrics.metric_reader import MetricReader
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.util.instrumentation import InstrumentationInfo

Expand All @@ -46,95 +58,68 @@ def __init__(
self._instrumentation_info = instrumentation_info
self._meter_provider = meter_provider

def create_counter(self, name, unit=None, description=None) -> Counter:
# FIXME implement this method
pass
def create_counter(self, name, unit=None, description=None) -> APICounter:
return Counter(self._instrumentation_info, name, unit, description)

def create_up_down_counter(
self, name, unit=None, description=None
) -> UpDownCounter:
# FIXME implement this method
pass
) -> APIUpDownCounter:
return UpDownCounter(
self._instrumentation_info, name, unit, description
)

def create_observable_counter(
self, name, callback, unit=None, description=None
) -> ObservableCounter:
# FIXME implement this method
pass
) -> APIObservableCounter:
return ObservableCounter(
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
self._instrumentation_info, name, callback, unit, description
)

def create_histogram(self, name, unit=None, description=None) -> Histogram:
# FIXME implement this method
pass
def create_histogram(
self, name, unit=None, description=None
) -> APIHistogram:
return Histogram(self._instrumentation_info, name, unit, description)

def create_observable_gauge(
self, name, callback, unit=None, description=None
) -> ObservableGauge:
# FIXME implement this method
pass
) -> APIObservableGauge:
return ObservableGauge(
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
self._instrumentation_info, name, callback, unit, description
)

def create_observable_up_down_counter(
self, name, callback, unit=None, description=None
) -> ObservableUpDownCounter:
# FIXME implement this method
pass
) -> APIObservableUpDownCounter:
return ObservableUpDownCounter(
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
self._instrumentation_info, name, callback, unit, description
)


class MeterProvider(APIMeterProvider):
"""See `opentelemetry._metrics.MeterProvider`."""

def __init__(
self,
metric_exporters: Sequence[MetricExporter] = (),
lzchen marked this conversation as resolved.
Show resolved Hide resolved
metric_readers: Sequence[MetricReader] = (),
ocelotl marked this conversation as resolved.
Show resolved Hide resolved
resource: Resource = Resource.create({}),
shutdown_on_exit: bool = True,
):
self._resource = resource
self._lock = Lock()
self._atexit_handler = None

if shutdown_on_exit:
self._atexit_handler = register(self.shutdown)

self._metric_readers = []
self._metric_exporters = []
self._views = []
self._shutdown = False

def get_meter(
self,
name: str,
version: Optional[str] = None,
schema_url: Optional[str] = None,
) -> Meter:

if self._shutdown:
_logger.warning(
"A shutdown `MeterProvider` can not provide a `Meter`"
)
return _DefaultMeter(name, version=version, schema_url=schema_url)

return Meter(InstrumentationInfo(name, version, schema_url), self)

def shutdown(self):
# FIXME implement a timeout

if self._shutdown:
_logger.warning("shutdown can only be called once")
return False

result = True
self._metric_readers = metric_readers

for metric_reader in self._metric_readers:
result = result and metric_reader.shutdown()

for metric_exporter in self._metric_exporters:
result = result and metric_exporter.shutdown()
metric_reader._register_meter_provider(self)

self._shutdown = True

if self._atexit_handler is not None:
unregister(self._atexit_handler)
self._atexit_handler = None
self._metric_exporters = metric_exporters

return result
self._resource = resource
self._shutdown = False

def force_flush(self) -> bool:

Expand All @@ -161,56 +146,46 @@ def force_flush(self) -> bool:

return metric_reader_result and metric_exporter_result

def register_metric_reader(self, metric_reader: "MetricReader") -> None:
# FIXME protect this method against race conditions
self._metric_readers.append(metric_reader)

def register_metric_exporter(
self, metric_exporter: "MetricExporter"
) -> None:
# FIXME protect this method against race conditions
self._metric_exporters.append(metric_exporter)

def register_view(self, view: "View") -> None:
# FIXME protect this method against race conditions
self._views.append(view)

def shutdown(self):
# FIXME implement a timeout

class MetricReader(ABC):
def __init__(self):
self._shutdown = False
if self._shutdown:
_logger.warning("shutdown can only be called once")
return False

@abstractmethod
def collect(self):
pass
result = True

def shutdown(self):
# FIXME this will need a Once wrapper
self._shutdown = True
for metric_reader in self._metric_readers:
result = result and metric_reader.shutdown()
ocelotl marked this conversation as resolved.
Show resolved Hide resolved

if not result:
_logger.warning("A MetricReader failed to shutdown")

class MetricExporter(ABC):
def __init__(self):
self._shutdown = False
for metric_exporter in self._metric_exporters:
result = result and metric_exporter.shutdown()

@abstractmethod
def export(self):
pass
if not result:
_logger.warning("A MetricExporter failed to shutdown")

def shutdown(self):
# FIXME this will need a Once wrapper
self._shutdown = True

if self._atexit_handler is not None:
unregister(self._atexit_handler)
self._atexit_handler = None

class View:
pass

return result

class ConsoleMetricExporter(MetricExporter):
def export(self):
pass
def get_meter(
self,
name: str,
version: Optional[str] = None,
schema_url: Optional[str] = None,
) -> Meter:

if self._shutdown:
_logger.warning(
"A shutdown `MeterProvider` can not provide a `Meter`"
)
return _DefaultMeter(name, version=version, schema_url=schema_url)

class SDKMetricReader(MetricReader):
def collect(self):
pass
return Meter(InstrumentationInfo(name, version, schema_url), self)
aabmass marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright The 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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Copyright The 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 MetricExporter:
pass
Loading