def __init__( self, exporter: MetricExporter, export_interval_millis: Optional[float] = None, export_timeout_millis: Optional[float] = None, ) -> None: super().__init__(preferred_temporality=exporter.preferred_temporality) self._exporter = exporter if export_interval_millis is None: try: export_interval_millis = float( environ.get("OTEL_METRIC_EXPORT_INTERVAL", 60000)) except ValueError: _logger.warning( "Found invalid value for export interval, using default") export_interval_millis = 60000 if export_timeout_millis is None: try: export_timeout_millis = float( environ.get("OTEL_METRIC_EXPORT_TIMEOUT", 30000)) except ValueError: _logger.warning( "Found invalid value for export timeout, using default") export_timeout_millis = 30000 self._export_interval_millis = export_interval_millis self._export_timeout_millis = export_timeout_millis self._shutdown = False self._shutdown_event = Event() self._shutdown_once = Once() self._daemon_thread = Thread(target=self._ticker, daemon=True) self._daemon_thread.start() if hasattr(os, "register_at_fork"): os.register_at_fork(after_in_child=self._at_fork_reinit) # pylint: disable=protected-access
def test_once_single_thread(self): once_func = MockFunc() once = Once() self.assertEqual(once_func.call_count, 0) # first call should run called = once.do_once(once_func) self.assertTrue(called) self.assertEqual(once_func.call_count, 1) # subsequent calls do nothing called = once.do_once(once_func) self.assertFalse(called) self.assertEqual(once_func.call_count, 1)
def test_once_many_threads(self): once_func = MockFunc() once = Once() def run_concurrently() -> bool: return once.do_once(once_func) results = self.run_with_many_threads(run_concurrently, num_threads=100) self.assertEqual(once_func.call_count, 1) # check that only one of the threads got True self.assertEqual(results.count(True), 1)
class PeriodicExportingMetricReader(MetricReader): """`PeriodicExportingMetricReader` is an implementation of `MetricReader` that collects metrics based on a user-configurable time interval, and passes the metrics to the configured exporter. """ def __init__( self, exporter: MetricExporter, export_interval_millis: Optional[float] = None, export_timeout_millis: Optional[float] = None, ) -> None: super().__init__(preferred_temporality=exporter.preferred_temporality) self._exporter = exporter if export_interval_millis is None: try: export_interval_millis = float( environ.get("OTEL_METRIC_EXPORT_INTERVAL", 60000)) except ValueError: _logger.warning( "Found invalid value for export interval, using default") export_interval_millis = 60000 if export_timeout_millis is None: try: export_timeout_millis = float( environ.get("OTEL_METRIC_EXPORT_TIMEOUT", 30000)) except ValueError: _logger.warning( "Found invalid value for export timeout, using default") export_timeout_millis = 30000 self._export_interval_millis = export_interval_millis self._export_timeout_millis = export_timeout_millis self._shutdown = False self._shutdown_event = Event() self._shutdown_once = Once() self._daemon_thread = Thread(target=self._ticker, daemon=True) self._daemon_thread.start() if hasattr(os, "register_at_fork"): os.register_at_fork(after_in_child=self._at_fork_reinit) # pylint: disable=protected-access def _at_fork_reinit(self): self._daemon_thread = Thread(target=self._ticker, daemon=True) self._daemon_thread.start() def _ticker(self) -> None: interval_secs = self._export_interval_millis / 1e3 while not self._shutdown_event.wait(interval_secs): self.collect() # one last collection below before shutting down completely self.collect() def _receive_metrics(self, metrics: Iterable[Metric]) -> None: if metrics is None: return token = attach(set_value(_SUPPRESS_INSTRUMENTATION_KEY, True)) try: self._exporter.export(metrics) except Exception as e: # pylint: disable=broad-except,invalid-name _logger.exception("Exception while exporting metrics %s", str(e)) detach(token) def shutdown(self) -> bool: def _shutdown(): self._shutdown = True did_set = self._shutdown_once.do_once(_shutdown) if not did_set: _logger.warning("Can't shutdown multiple times") return False self._shutdown_event.set() self._daemon_thread.join() self._exporter.shutdown() return True
def reset_metrics_globals() -> None: """WARNING: only use this for tests.""" metrics_api._METER_PROVIDER_SET_ONCE = Once() # type: ignore[attr-defined] metrics_api._METER_PROVIDER = None # type: ignore[attr-defined] metrics_api._PROXY_METER_PROVIDER = metrics_api._ProxyMeterProvider( ) # type: ignore[attr-defined]
def reset_trace_globals() -> None: """WARNING: only use this for tests.""" trace_api._TRACER_PROVIDER_SET_ONCE = Once() trace_api._TRACER_PROVIDER = None trace_api._PROXY_TRACER_PROVIDER = trace_api.ProxyTracerProvider()
set_status_on_exception: bool = True, end_on_exit: bool = True, ) -> Iterator["Span"]: # pylint: disable=unused-argument,no-self-use yield INVALID_SPAN @deprecated(version="1.9.0", reason="You should use NoOpTracer") # type: ignore class _DefaultTracer(NoOpTracer): """The default Tracer, used when no Tracer implementation is available. All operations are no-op. """ _TRACER_PROVIDER_SET_ONCE = Once() _TRACER_PROVIDER: Optional[TracerProvider] = None _PROXY_TRACER_PROVIDER = ProxyTracerProvider() def get_tracer( instrumenting_module_name: str, instrumenting_library_version: typing.Optional[str] = None, tracer_provider: Optional[TracerProvider] = None, schema_url: typing.Optional[str] = None, ) -> "Tracer": """Returns a `Tracer` for use by the given instrumentation library. This function is a convenience wrapper for opentelemetry.trace.TracerProvider.get_tracer.
def create_observable_up_down_counter( self, name, callback, unit="", description="" ) -> ObservableUpDownCounter: super().create_observable_up_down_counter( name, callback, unit=unit, description=description ) return DefaultObservableUpDownCounter( name, callback, unit=unit, description=description, ) _METER_PROVIDER_SET_ONCE = Once() _METER_PROVIDER: Optional[MeterProvider] = None _PROXY_METER_PROVIDER = _ProxyMeterProvider() def get_meter( name: str, version: str = "", meter_provider: Optional[MeterProvider] = None, ) -> "Meter": """Returns a `Meter` for use by the given instrumentation library. This function is a convenience wrapper for opentelemetry.trace.MeterProvider.get_meter. If meter_provider is omitted the current configured one is used.