Skip to content

Commit 7539592

Browse files
authored
Add MeterProvider and Meter to the SDK (#2227)
* Add MeterProvider and Meter to the SDK Fixes #2200 * Add FIXMEs * Fix docstring * Add FIXME * Fix meter return * Log an error if a force flush fails * Add FIXME * Fix lint * Remove SDK API module * Unregister * Fix API names * Return _DefaultMeter * Remove properties * Pass MeterProvider as a parameter to __init__ * Add FIXMEs * Add FIXMEs * Fix lint
1 parent 0df742d commit 7539592

File tree

2 files changed

+421
-0
lines changed

2 files changed

+421
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# pylint: disable=function-redefined,too-many-ancestors
16+
17+
from abc import ABC, abstractmethod
18+
from atexit import register, unregister
19+
from logging import getLogger
20+
from typing import Optional
21+
22+
from opentelemetry.metrics import Meter as APIMeter
23+
from opentelemetry.metrics import MeterProvider as APIMeterProvider
24+
from opentelemetry.metrics import _DefaultMeter
25+
from opentelemetry.metrics.instrument import (
26+
Counter,
27+
Histogram,
28+
ObservableCounter,
29+
ObservableGauge,
30+
ObservableUpDownCounter,
31+
UpDownCounter,
32+
)
33+
from opentelemetry.sdk.resources import Resource
34+
from opentelemetry.sdk.util.instrumentation import InstrumentationInfo
35+
36+
_logger = getLogger(__name__)
37+
38+
39+
class Meter(APIMeter):
40+
def __init__(
41+
self,
42+
instrumentation_info: InstrumentationInfo,
43+
meter_provider: APIMeterProvider,
44+
):
45+
super().__init__(instrumentation_info)
46+
self._instrumentation_info = instrumentation_info
47+
self._meter_provider = meter_provider
48+
49+
def create_counter(self, name, unit=None, description=None) -> Counter:
50+
# FIXME implement this method
51+
pass
52+
53+
def create_up_down_counter(
54+
self, name, unit=None, description=None
55+
) -> UpDownCounter:
56+
# FIXME implement this method
57+
pass
58+
59+
def create_observable_counter(
60+
self, name, callback, unit=None, description=None
61+
) -> ObservableCounter:
62+
# FIXME implement this method
63+
pass
64+
65+
def create_histogram(self, name, unit=None, description=None) -> Histogram:
66+
# FIXME implement this method
67+
pass
68+
69+
def create_observable_gauge(
70+
self, name, callback, unit=None, description=None
71+
) -> ObservableGauge:
72+
# FIXME implement this method
73+
pass
74+
75+
def create_observable_up_down_counter(
76+
self, name, callback, unit=None, description=None
77+
) -> ObservableUpDownCounter:
78+
# FIXME implement this method
79+
pass
80+
81+
82+
class MeterProvider(APIMeterProvider):
83+
"""See `opentelemetry.metrics.MeterProvider`."""
84+
85+
def __init__(
86+
self,
87+
resource: Resource = Resource.create({}),
88+
shutdown_on_exit: bool = True,
89+
):
90+
self._resource = resource
91+
self._atexit_handler = None
92+
93+
if shutdown_on_exit:
94+
self._atexit_handler = register(self.shutdown)
95+
96+
self._metric_readers = []
97+
self._metric_exporters = []
98+
self._views = []
99+
self._shutdown = False
100+
101+
def get_meter(
102+
self,
103+
name: str,
104+
version: Optional[str] = None,
105+
schema_url: Optional[str] = None,
106+
) -> Meter:
107+
108+
if self._shutdown:
109+
_logger.warning(
110+
"A shutdown `MeterProvider` can not provide a `Meter`"
111+
)
112+
return _DefaultMeter(name, version=version, schema_url=schema_url)
113+
114+
return Meter(InstrumentationInfo(name, version, schema_url), self)
115+
116+
def shutdown(self):
117+
# FIXME implement a timeout
118+
119+
if self._shutdown:
120+
_logger.warning("shutdown can only be called once")
121+
return False
122+
123+
result = True
124+
125+
for metric_reader in self._metric_readers:
126+
result = result and metric_reader.shutdown()
127+
128+
for metric_exporter in self._metric_exporters:
129+
result = result and metric_exporter.shutdown()
130+
131+
self._shutdown = True
132+
133+
if self._atexit_handler is not None:
134+
unregister(self._atexit_handler)
135+
self._atexit_handler = None
136+
137+
return result
138+
139+
def force_flush(self) -> bool:
140+
141+
# FIXME implement a timeout
142+
143+
metric_reader_result = True
144+
metric_exporter_result = True
145+
146+
for metric_reader in self._metric_readers:
147+
metric_reader_result = (
148+
metric_reader_result and metric_reader.force_flush()
149+
)
150+
151+
if not metric_reader_result:
152+
_logger.warning("Unable to force flush all metric readers")
153+
154+
for metric_exporter in self._metric_exporters:
155+
metric_exporter_result = (
156+
metric_exporter_result and metric_exporter.force_flush()
157+
)
158+
159+
if not metric_exporter_result:
160+
_logger.warning("Unable to force flush all metric exporters")
161+
162+
return metric_reader_result and metric_exporter_result
163+
164+
def register_metric_reader(self, metric_reader: "MetricReader") -> None:
165+
# FIXME protect this method against race conditions
166+
self._metric_readers.append(metric_reader)
167+
168+
def register_metric_exporter(
169+
self, metric_exporter: "MetricExporter"
170+
) -> None:
171+
# FIXME protect this method against race conditions
172+
self._metric_exporters.append(metric_exporter)
173+
174+
def register_view(self, view: "View") -> None:
175+
# FIXME protect this method against race conditions
176+
self._views.append(view)
177+
178+
179+
class MetricReader(ABC):
180+
def __init__(self):
181+
self._shutdown = False
182+
183+
@abstractmethod
184+
def collect(self):
185+
pass
186+
187+
def shutdown(self):
188+
# FIXME this will need a Once wrapper
189+
self._shutdown = True
190+
191+
192+
class MetricExporter(ABC):
193+
def __init__(self):
194+
self._shutdown = False
195+
196+
@abstractmethod
197+
def export(self):
198+
pass
199+
200+
def shutdown(self):
201+
# FIXME this will need a Once wrapper
202+
self._shutdown = True
203+
204+
205+
class View:
206+
pass
207+
208+
209+
class ConsoleMetricExporter(MetricExporter):
210+
def export(self):
211+
pass
212+
213+
214+
class SDKMetricReader(MetricReader):
215+
def collect(self):
216+
pass

0 commit comments

Comments
 (0)