From eece48d6e7b8a61d2ec89e53299562e5ff262f5f Mon Sep 17 00:00:00 2001 From: czhang771 Date: Thu, 29 Aug 2024 14:20:11 -0700 Subject: [PATCH] add samples for exemplar filter and custom reservoir factory --- .../reader/preferred_exemplarfilter.py | 50 +++++++++++ .../metrics/views/change_reservoir_factory.py | 82 +++++++++++++++++++ 2 files changed, 132 insertions(+) create mode 100644 docs/examples/metrics/reader/preferred_exemplarfilter.py create mode 100644 docs/examples/metrics/views/change_reservoir_factory.py diff --git a/docs/examples/metrics/reader/preferred_exemplarfilter.py b/docs/examples/metrics/reader/preferred_exemplarfilter.py new file mode 100644 index 00000000000..31712d3f39d --- /dev/null +++ b/docs/examples/metrics/reader/preferred_exemplarfilter.py @@ -0,0 +1,50 @@ +# 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. +import time + +from opentelemetry.metrics import get_meter_provider, set_meter_provider +from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics.export import ( + ConsoleMetricExporter, + PeriodicExportingMetricReader, +) +from opentelemetry.sdk.metrics._internal.exemplar import ( + AlwaysOffExemplarFilter, + AlwaysOnExemplarFilter, + TraceBasedExemplarFilter, +) + +# Create an ExemplarFilter instance (e.g., TraceBasedExemplarFilter) +exemplar_filter = TraceBasedExemplarFilter() + +exporter = ConsoleMetricExporter() + +reader = PeriodicExportingMetricReader( + exporter, + export_interval_millis=5_000, +) + +# Set up the MeterProvider with the ExemplarFilter +provider = MeterProvider( + metric_readers=[reader], + exemplar_filter=exemplar_filter, # Pass the ExemplarFilter to the MeterProvider +) +set_meter_provider(provider) + +meter = get_meter_provider().get_meter("exemplar-filter-example", "0.1.2") +counter = meter.create_counter("my-counter") + +for value in range(10): + counter.add(value) + time.sleep(2.0) \ No newline at end of file diff --git a/docs/examples/metrics/views/change_reservoir_factory.py b/docs/examples/metrics/views/change_reservoir_factory.py new file mode 100644 index 00000000000..e6360e41ce1 --- /dev/null +++ b/docs/examples/metrics/views/change_reservoir_factory.py @@ -0,0 +1,82 @@ +# 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. + +import random +import time + +from opentelemetry.metrics import get_meter_provider, set_meter_provider +from opentelemetry.sdk.metrics import Counter, MeterProvider +from opentelemetry.sdk.metrics.export import ( + ConsoleMetricExporter, + PeriodicExportingMetricReader, +) +from opentelemetry.sdk.metrics.view import View +from typing import Callable, Optional, Set, Type, Any, Sequence +from opentelemetry.sdk.metrics._internal.aggregation import ( + Aggregation, + DefaultAggregation, + _Aggregation, + _ExplicitBucketHistogramAggregation, + _ExponentialBucketHistogramAggregation, +) +from opentelemetry.sdk.metrics._internal.exemplar import ( + AlignedHistogramBucketExemplarReservoir, + ExemplarReservoir, + ExemplarReservoirFactory, + SimpleFixedSizeExemplarReservoir +) + +# Returns a factory for creating an exemplar reservoir based on the aggregation type and specified parameters +def generalized_reservoir_factory(size: int = 1, boundaries: Sequence[float] = None) -> Callable[[Type[_Aggregation]], ExemplarReservoirFactory]: + def factory(aggregationType: Type[_Aggregation]) -> ExemplarReservoirFactory: + if issubclass(aggregationType, _ExplicitBucketHistogramAggregation): + return lambda **kwargs: AlignedHistogramBucketExemplarReservoir(boundaries=boundaries or [], **{k: v for k, v in kwargs.items() if k != 'boundaries'}) + else: + return lambda **kwargs: SimpleFixedSizeExemplarReservoir(size=size, **kwargs) + + return factory + +# Create a custom reservoir factory with specified parameters +custom_reservoir_factory = generalized_reservoir_factory(size=10) + +# Create a view with the custom reservoir factory +change_reservoir_factory_view= View( + instrument_name="my.counter", + name="name", + aggregation=DefaultAggregation(), + exemplar_reservoir_factory=custom_reservoir_factory, + ) + +# Use console exporter for the example +exporter = ConsoleMetricExporter() + +# Create a metric reader with stdout exporter +reader = PeriodicExportingMetricReader(exporter, export_interval_millis=1_000) +provider = MeterProvider( + metric_readers=[ + reader, + ], + views=[ + change_reservoir_factory_view, + ], +) +set_meter_provider(provider) + +meter = get_meter_provider().get_meter("reservoir-factory-change", "0.1.2") + +my_counter = meter.create_counter("my.counter") + +while 1: + my_counter.add(random.randint(1, 10)) + time.sleep(random.random())