diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d9a92b2e44..835601d58ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v1.5.0-0.24b0...HEAD) - +- Automatically load OTEL environment variables as options for `opentelemetry-instrument` + ([#1969](https://github.com/open-telemetry/opentelemetry-python/pull/1969)) - `opentelemetry-semantic-conventions` Update to semantic conventions v1.6.1 ([#2077](https://github.com/open-telemetry/opentelemetry-python/pull/2077)) - Do not count invalid attributes for dropped diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7084a8fbca1..ac76ccc70d0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -214,6 +214,16 @@ rather than conform to specific API names or argument patterns in the spec. For a deeper discussion, see: https://github.com/open-telemetry/opentelemetry-specification/issues/165 +### Environment Variables + +If you are adding a component that introduces new OpenTelemetry environment variables, put them all in a module, +as it is done in `opentelemetry.environment_variables` or in `opentelemetry.sdk.environment_variables`. + +Keep in mind that any new environment variable must be declared in all caps and must start with `OTEL_PYTHON_`. + +Register this module with the `opentelemetry_environment_variables` entry point to make your environment variables +automatically load as options for the `opentelemetry-instrument` command. + ## Style Guide * docstrings should adhere to the [Google Python Style diff --git a/opentelemetry-api/setup.cfg b/opentelemetry-api/setup.cfg index 99d52838fb1..91a38ac9278 100644 --- a/opentelemetry-api/setup.cfg +++ b/opentelemetry-api/setup.cfg @@ -56,6 +56,8 @@ opentelemetry_tracer_provider = opentelemetry_propagator = tracecontext = opentelemetry.trace.propagation.tracecontext:TraceContextTextMapPropagator baggage = opentelemetry.baggage.propagation:W3CBaggagePropagator +opentelemetry_environment_variables = + api = opentelemetry.environment_variables [options.extras_require] test = diff --git a/opentelemetry-api/src/opentelemetry/environment_variables/__init__.py b/opentelemetry-api/src/opentelemetry/environment_variables.py similarity index 88% rename from opentelemetry-api/src/opentelemetry/environment_variables/__init__.py rename to opentelemetry-api/src/opentelemetry/environment_variables.py index 6077115b013..83ec67149dd 100644 --- a/opentelemetry-api/src/opentelemetry/environment_variables/__init__.py +++ b/opentelemetry-api/src/opentelemetry/environment_variables.py @@ -22,11 +22,6 @@ .. envvar:: OTEL_PYTHON_CONTEXT """ -OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "OTEL_PYTHON_DISABLED_INSTRUMENTATIONS" -""" -.. envvar:: OTEL_PYTHON_DISABLED_INSTRUMENTATIONS -""" - OTEL_PYTHON_ID_GENERATOR = "OTEL_PYTHON_ID_GENERATOR" """ .. envvar:: OTEL_PYTHON_ID_GENERATOR diff --git a/opentelemetry-distro/src/opentelemetry/distro/__init__.py b/opentelemetry-distro/src/opentelemetry/distro/__init__.py index e70cb67335d..97e3e2fcc94 100644 --- a/opentelemetry-distro/src/opentelemetry/distro/__init__.py +++ b/opentelemetry-distro/src/opentelemetry/distro/__init__.py @@ -11,7 +11,7 @@ # 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 os from opentelemetry.environment_variables import OTEL_TRACES_EXPORTER diff --git a/opentelemetry-instrumentation/setup.cfg b/opentelemetry-instrumentation/setup.cfg index 6ecd9d75e69..042f0edb198 100644 --- a/opentelemetry-instrumentation/setup.cfg +++ b/opentelemetry-instrumentation/setup.cfg @@ -51,6 +51,8 @@ where = src console_scripts = opentelemetry-instrument = opentelemetry.instrumentation.auto_instrumentation:run opentelemetry-bootstrap = opentelemetry.instrumentation.bootstrap:run +opentelemetry_environment_variables = + instrumentation = opentelemetry.instrumentation.environment_variables [options.extras_require] test = diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py index 9f076b340e5..29b09a0c347 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/__init__.py @@ -14,72 +14,74 @@ # See the License for the specific language governing permissions and # limitations under the License. -import argparse +from argparse import REMAINDER, ArgumentParser from logging import getLogger from os import environ, execl, getcwd from os.path import abspath, dirname, pathsep +from re import sub from shutil import which -from opentelemetry.environment_variables import ( - OTEL_PYTHON_ID_GENERATOR, - OTEL_TRACES_EXPORTER, -) +from pkg_resources import iter_entry_points -logger = getLogger(__file__) +_logger = getLogger(__file__) -def parse_args(): - parser = argparse.ArgumentParser( +def run() -> None: + + parser = ArgumentParser( description=""" opentelemetry-instrument automatically instruments a Python program and its dependencies and then runs the program. - """ + """, + epilog=""" + Optional arguments (except for --help) for opentelemetry-instrument + directly correspond with OpenTelemetry environment variables. The + corresponding optional argument is formed by removing the OTEL_ or + OTEL_PYTHON_ prefix from the environment variable and lower casing the + rest. For example, the optional argument --attribute_value_length_limit + corresponds with the environment variable + OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT. + + These optional arguments will override the current value of the + corresponding environment variable during the execution of the command. + """, ) - parser.add_argument( - "--trace-exporter", - required=False, - help=""" - Uses the specified exporter to export spans. - Accepts multiple exporters as comma separated values. + argument_otel_environment_variable = {} - Examples: + for entry_point in iter_entry_points( + "opentelemetry_environment_variables" + ): + environment_variable_module = entry_point.load() - --trace-exporter=jaeger - """, - ) + for attribute in dir(environment_variable_module): - parser.add_argument( - "--id-generator", - required=False, - help=""" - The IDs Generator to be used with the Tracer Provider. + if attribute.startswith("OTEL_"): - Examples: + argument = sub(r"OTEL_(PYTHON_)?", "", attribute).lower() - --id-generator=random - """, - ) + parser.add_argument( + f"--{argument}", + required=False, + ) + argument_otel_environment_variable[argument] = attribute parser.add_argument("command", help="Your Python application.") parser.add_argument( "command_args", help="Arguments for your application.", - nargs=argparse.REMAINDER, + nargs=REMAINDER, ) - return parser.parse_args() - -def load_config_from_cli_args(args): - if args.trace_exporter: - environ[OTEL_TRACES_EXPORTER] = args.trace_exporter - if args.id_generator: - environ[OTEL_PYTHON_ID_GENERATOR] = args.id_generator + args = parser.parse_args() + for argument, otel_environment_variable in ( + argument_otel_environment_variable + ).items(): + value = getattr(args, argument) + if value is not None: -def run() -> None: - args = parse_args() - load_config_from_cli_args(args) + environ[otel_environment_variable] = value python_path = environ.get("PYTHONPATH") diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py index a4a5dc8d5a0..f7a6412ff6e 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/auto_instrumentation/sitecustomize.py @@ -20,13 +20,13 @@ from pkg_resources import iter_entry_points -from opentelemetry.environment_variables import ( - OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, -) from opentelemetry.instrumentation.dependencies import ( get_dist_dependency_conflicts, ) from opentelemetry.instrumentation.distro import BaseDistro, DefaultDistro +from opentelemetry.instrumentation.environment_variables import ( + OTEL_PYTHON_DISABLED_INSTRUMENTATIONS, +) logger = getLogger(__file__) diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/environment_variables.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/environment_variables.py new file mode 100644 index 00000000000..ad28f068590 --- /dev/null +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/environment_variables.py @@ -0,0 +1,18 @@ +# 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. + +OTEL_PYTHON_DISABLED_INSTRUMENTATIONS = "OTEL_PYTHON_DISABLED_INSTRUMENTATIONS" +""" +.. envvar:: OTEL_PYTHON_DISABLED_INSTRUMENTATIONS +""" diff --git a/opentelemetry-instrumentation/tests/test_run.py b/opentelemetry-instrumentation/tests/test_run.py index 01bd86ed32f..9fd3a21711e 100644 --- a/opentelemetry-instrumentation/tests/test_run.py +++ b/opentelemetry-instrumentation/tests/test_run.py @@ -111,7 +111,8 @@ def test_exporter(self, _): # pylint: disable=no-self-use self.assertIsNone(environ.get(OTEL_TRACES_EXPORTER)) with patch( - "sys.argv", ["instrument", "--trace-exporter", "jaeger", "1", "2"] + "sys.argv", + ["instrument", "--traces_exporter", "jaeger", "1", "2"], ): auto_instrumentation.run() self.assertEqual(environ.get(OTEL_TRACES_EXPORTER), "jaeger") diff --git a/opentelemetry-sdk/setup.cfg b/opentelemetry-sdk/setup.cfg index 0c699262c64..56390868ed1 100644 --- a/opentelemetry-sdk/setup.cfg +++ b/opentelemetry-sdk/setup.cfg @@ -56,6 +56,8 @@ opentelemetry_traces_exporter = console = opentelemetry.sdk.trace.export:ConsoleSpanExporter opentelemetry_id_generator = random = opentelemetry.sdk.trace.id_generator:RandomIdGenerator +opentelemetry_environment_variables = + sdk = opentelemetry.sdk.environment_variables [options.extras_require] test = diff --git a/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py b/opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py similarity index 100% rename from opentelemetry-sdk/src/opentelemetry/sdk/environment_variables/__init__.py rename to opentelemetry-sdk/src/opentelemetry/sdk/environment_variables.py