Esempio n. 1
0
 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)
Esempio n. 4
0
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()
Esempio n. 7
0
        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.
Esempio n. 8
0
    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.