diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 779493efd9d..ebf5aad8b42 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,15 +45,7 @@ during their normal contribution hours. ## Development -To quickly get up and running, you can use the `scripts/eachdist.py` tool that -ships with this project. First create a virtualenv and activate it. -Then run `python scripts/eachdist.py develop` to install all required packages -as well as the project's packages themselves (in `--editable` mode). - -You can then run `scripts/eachdist.py test` to test everything or -`scripts/eachdist.py lint` to lint everything (fixing anything that is auto-fixable). - -Additionally, this project uses [tox](https://tox.readthedocs.io) to automate +This project uses [tox](https://tox.readthedocs.io) to automate some aspects of development, including testing against multiple Python versions. To install `tox`, run: @@ -104,8 +96,6 @@ The continuation integration overrides that environment variable with as per the ### Benchmarks -Performance progression of benchmarks for packages distributed by OpenTelemetry Python can be viewed as a [graph of throughput vs commit history](https://opentelemetry-python.readthedocs.io/en/latest/performance/benchmarks.html). From the linked page, you can download a JSON file with the performance results. - Running the `tox` tests also runs the performance tests if any are available. Benchmarking tests are done with `pytest-benchmark` and they output a table with results to the console. To write benchmarks, simply use the [pytest benchmark fixture](https://pytest-benchmark.readthedocs.io/en/latest/usage.html#usage) like the following: diff --git a/docs/examples/views/README.rst b/docs/examples/views/README.rst new file mode 100644 index 00000000000..3bf6010660d --- /dev/null +++ b/docs/examples/views/README.rst @@ -0,0 +1,35 @@ +View common scenarios +===================== + +These examples show how to customize the metrics that are output by the SDK using Views. There are multiple examples: + +* change_aggregation: Shows how to configure to change the default aggregation for an instrument. +* change_name: Shows how to change the name of a metric. +* limit_num_of_attrs: Shows how to limit the number of attributes that are output for a metric. + +The source files of these examples are available :scm_web:`here `. + + +Installation +------------ + +.. code-block:: sh + + pip install -r requirements.txt + +Run the Example +--------------- + +.. code-block:: sh + + python .py + +The output will be shown in the console. + +Useful links +------------ + +- OpenTelemetry_ +- :doc:`../../api/metrics` + +.. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ diff --git a/docs/examples/views/change_aggregation.py b/docs/examples/views/change_aggregation.py new file mode 100644 index 00000000000..5dad07e64bf --- /dev/null +++ b/docs/examples/views/change_aggregation.py @@ -0,0 +1,53 @@ +# 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 MeterProvider +from opentelemetry.sdk.metrics.export import ( + ConsoleMetricExporter, + PeriodicExportingMetricReader, +) +from opentelemetry.sdk.metrics.view import SumAggregation, View + +# Create a view matching the histogram instrument name `http.client.request.latency` +# and configure the `SumAggregation` for the result metrics stream +hist_to_sum_view = View( + instrument_name="http.client.request.latency", aggregation=SumAggregation() +) + +# 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=[ + hist_to_sum_view, + ], +) +set_meter_provider(provider) + +meter = get_meter_provider().get_meter("view-change-aggregation", "0.1.2") + +histogram = meter.create_histogram("http.client.request.latency") + +while 1: + histogram.record(99.9) + time.sleep(random.random()) diff --git a/docs/examples/views/change_name.py b/docs/examples/views/change_name.py new file mode 100644 index 00000000000..c70f7852a24 --- /dev/null +++ b/docs/examples/views/change_name.py @@ -0,0 +1,55 @@ +# 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 + +# Create a view matching the counter instrument `my.counter` +# and configure the new name `my.counter.total` for the result metrics stream +change_metric_name_view = View( + instrument_type=Counter, + instrument_name="my.counter", + name="my.counter.total", +) + +# 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_metric_name_view, + ], +) +set_meter_provider(provider) + +meter = get_meter_provider().get_meter("view-name-change", "0.1.2") + +my_counter = meter.create_counter("my.counter") + +while 1: + my_counter.add(random.randint(1, 10)) + time.sleep(random.random()) diff --git a/docs/examples/views/limit_num_of_attrs.py b/docs/examples/views/limit_num_of_attrs.py new file mode 100644 index 00000000000..d9f0e9484c4 --- /dev/null +++ b/docs/examples/views/limit_num_of_attrs.py @@ -0,0 +1,71 @@ +# 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 typing import Iterable + +from opentelemetry.metrics import ( + CallbackOptions, + Observation, + get_meter_provider, + set_meter_provider, +) +from opentelemetry.sdk.metrics import MeterProvider, ObservableGauge +from opentelemetry.sdk.metrics.export import ( + ConsoleMetricExporter, + PeriodicExportingMetricReader, +) +from opentelemetry.sdk.metrics.view import View + +# Create a view matching the observable gauge instrument `observable_gauge` +# and configure the attributes in the result metric stream +# to contain only the attributes with keys with `k_3` and `k_5` +view_with_attributes_limit = View( + instrument_type=ObservableGauge, + instrument_name="observable_gauge", + attribute_keys={"k_3", "k_5"}, +) + +exporter = ConsoleMetricExporter() + +reader = PeriodicExportingMetricReader(exporter, export_interval_millis=1_000) +provider = MeterProvider( + metric_readers=[ + reader, + ], + views=[ + view_with_attributes_limit, + ], +) +set_meter_provider(provider) + +meter = get_meter_provider().get_meter("reduce-cardinality-with-view", "0.1.2") + + +def observable_gauge_func(options: CallbackOptions) -> Iterable[Observation]: + attrs = {} + for i in range(random.randint(1, 100)): + attrs[f"k_{i}"] = f"v_{i}" + yield Observation(1, attrs) + + +# Async gauge +observable_gauge = meter.create_observable_gauge( + "observable_gauge", + [observable_gauge_func], +) + +while 1: + time.sleep(1) diff --git a/docs/examples/views/requirements.txt b/docs/examples/views/requirements.txt new file mode 100644 index 00000000000..f690f9d1ca1 --- /dev/null +++ b/docs/examples/views/requirements.txt @@ -0,0 +1,6 @@ +Deprecated==1.2.13 +opentelemetry-api==1.12.0rc2 +opentelemetry-sdk==1.12.0rc2 +opentelemetry-semantic-conventions==0.32b0 +typing_extensions==4.3.0 +wrapt==1.14.1 \ No newline at end of file diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py index 996a7f28002..3088dbc5bbf 100644 --- a/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py +++ b/opentelemetry-sdk/src/opentelemetry/sdk/resources/__init__.py @@ -71,8 +71,9 @@ OTEL_SERVICE_NAME, ) from opentelemetry.semconv.resource import ResourceAttributes +from opentelemetry.util.types import AttributeValue -LabelValue = typing.Union[str, bool, int, float] +LabelValue = AttributeValue Attributes = typing.Dict[str, LabelValue] logger = logging.getLogger(__name__)