def __init__(
     self,
     source: "MeterProvider",
     instrumentation_info: "InstrumentationInfo",
 ):
     self.instrumentation_info = instrumentation_info
     self.processor = Processor(source.stateful, source.resource)
     self.instruments = {}
     self.instruments_lock = threading.Lock()
     self.view_manager = ViewManager()
 def test_finished_collection_stateless(self):
     meter_provider = metrics.MeterProvider()
     meter = meter_provider.get_meter(__name__)
     processor = Processor(False, meter_provider.resource)
     aggregator = SumAggregator()
     metric = metrics.Counter("available memory", "available memory",
                              "bytes", int, meter)
     aggregator.update(1.0)
     labels = ()
     _batch_map = {}
     _batch_map[(metric, SumAggregator, tuple(), labels)] = aggregator
     processor._batch_map = _batch_map
     processor.finished_collection()
     self.assertEqual(len(processor._batch_map), 0)
 def test_checkpoint_set(self):
     meter_provider = metrics.MeterProvider()
     meter = meter_provider.get_meter(__name__)
     processor = Processor(True, meter_provider.resource)
     aggregator = SumAggregator()
     metric = metrics.Counter("available memory", "available memory",
                              "bytes", int, meter)
     aggregator.update(1.0)
     labels = ()
     _batch_map = {}
     _batch_map[(metric, SumAggregator, tuple(), labels)] = aggregator
     processor._batch_map = _batch_map
     records = processor.checkpoint_set()
     self.assertEqual(len(records), 1)
     self.assertEqual(records[0].instrument, metric)
     self.assertEqual(records[0].labels, labels)
     self.assertEqual(records[0].aggregator, aggregator)
 def test_processor_process_not_exists(self):
     meter_provider = metrics.MeterProvider()
     meter = meter_provider.get_meter(__name__)
     processor = Processor(True, meter_provider.resource)
     aggregator = SumAggregator()
     metric = metrics.Counter("available memory", "available memory",
                              "bytes", int, meter)
     labels = ()
     _batch_map = {}
     batch_key = (metric, SumAggregator, tuple(), labels)
     aggregator.update(1.0)
     processor._batch_map = _batch_map
     record = metrics.Record(metric, labels, aggregator)
     processor.process(record)
     self.assertEqual(len(processor._batch_map), 1)
     self.assertIsNotNone(processor._batch_map.get(batch_key))
     self.assertEqual(processor._batch_map.get(batch_key).current, 0)
     self.assertEqual(processor._batch_map.get(batch_key).checkpoint, 1.0)
class Accumulator(metrics_api.Meter):
    """See `opentelemetry.metrics.Meter`.

    Args:
        source: The `MeterProvider` that created this meter.
        instrumentation_info: The `InstrumentationInfo` for this meter.
    """
    def __init__(
        self,
        source: "MeterProvider",
        instrumentation_info: "InstrumentationInfo",
    ):
        self.instrumentation_info = instrumentation_info
        self.processor = Processor(source.stateful, source.resource)
        self.metrics = set()
        self.observers = set()
        self.metrics_lock = threading.Lock()
        self.observers_lock = threading.Lock()
        self.view_manager = ViewManager()

    def collect(self) -> None:
        """Collects all the metrics created with this `Meter` for export.

        Utilizes the processor to create checkpoints of the current values in
        each aggregator belonging to the metrics that were created with this
        meter instance.
        """

        self._collect_metrics()
        self._collect_observers()

    def _collect_metrics(self) -> None:
        for metric in self.metrics:
            if not metric.enabled:
                continue
            to_remove = []
            with metric.bound_instruments_lock:
                for (
                        labels,
                        bound_instrument,
                ) in metric.bound_instruments.items():
                    for view_data in bound_instrument.view_datas:
                        accumulation = Accumulation(metric, view_data.labels,
                                                    view_data.aggregator)
                        self.processor.process(accumulation)

                    if bound_instrument.ref_count() == 0:
                        to_remove.append(labels)

            # Remove handles that were released
            for labels in to_remove:
                del metric.bound_instruments[labels]

    def _collect_observers(self) -> None:
        with self.observers_lock:
            for observer in self.observers:
                if not observer.enabled:
                    continue

                if not observer.run():
                    continue

                for labels, aggregator in observer.aggregators.items():
                    accumulation = Accumulation(observer, labels, aggregator)
                    self.processor.process(accumulation)

    def record_batch(
        self,
        labels: Dict[str, str],
        record_tuples: Sequence[Tuple[metrics_api.Metric, metrics_api.ValueT]],
    ) -> None:
        """See `opentelemetry.metrics.Meter.record_batch`."""
        # TODO: Avoid enconding the labels for each instrument, encode once
        # and reuse.
        for metric, value in record_tuples:
            metric.UPDATE_FUNCTION(value, labels)

    def create_counter(
        self,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        enabled: bool = True,
    ) -> metrics_api.Counter:
        """See `opentelemetry.metrics.Meter.create_counter`."""
        counter = Counter(name,
                          description,
                          unit,
                          value_type,
                          self,
                          enabled=enabled)
        with self.metrics_lock:
            self.metrics.add(counter)
        return counter

    def create_updowncounter(
        self,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        enabled: bool = True,
    ) -> metrics_api.UpDownCounter:
        """See `opentelemetry.metrics.Meter.create_updowncounter`."""
        counter = UpDownCounter(name,
                                description,
                                unit,
                                value_type,
                                self,
                                enabled=enabled)
        with self.metrics_lock:
            self.metrics.add(counter)
        return counter

    def create_valuerecorder(
        self,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        enabled: bool = True,
    ) -> metrics_api.ValueRecorder:
        """See `opentelemetry.metrics.Meter.create_valuerecorder`."""
        recorder = ValueRecorder(name,
                                 description,
                                 unit,
                                 value_type,
                                 self,
                                 enabled=enabled)
        with self.metrics_lock:
            self.metrics.add(recorder)
        return recorder

    def register_sumobserver(
        self,
        callback: metrics_api.ObserverCallbackT,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        label_keys: Sequence[str] = (),
        enabled: bool = True,
    ) -> metrics_api.SumObserver:
        ob = SumObserver(callback, name, description, unit, value_type,
                         label_keys, enabled)
        with self.observers_lock:
            self.observers.add(ob)
        return ob

    def register_updownsumobserver(
        self,
        callback: metrics_api.ObserverCallbackT,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        label_keys: Sequence[str] = (),
        enabled: bool = True,
    ) -> metrics_api.UpDownSumObserver:
        ob = UpDownSumObserver(callback, name, description, unit, value_type,
                               label_keys, enabled)
        with self.observers_lock:
            self.observers.add(ob)
        return ob

    def register_valueobserver(
        self,
        callback: metrics_api.ObserverCallbackT,
        name: str,
        description: str,
        unit: str,
        value_type: Type[metrics_api.ValueT],
        label_keys: Sequence[str] = (),
        enabled: bool = True,
    ) -> metrics_api.ValueObserver:
        ob = ValueObserver(callback, name, description, unit, value_type,
                           label_keys, enabled)
        with self.observers_lock:
            self.observers.add(ob)
        return ob

    def unregister_observer(self, observer: metrics_api.Observer) -> None:
        with self.observers_lock:
            self.observers.remove(observer)

    def register_view(self, view):
        self.view_manager.register_view(view)

    def unregister_view(self, view):
        self.view_manager.unregister_view(view)
 def test_checkpoint_set_empty(self):
     processor = Processor(True, Resource.create_empty())
     records = processor.checkpoint_set()
     self.assertEqual(len(records), 0)