#!/usr/bin/env python3 # 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 ast import logging import os import subprocess import sys import astor from otel_packaging import ( get_instrumentation_packages, root_path, scripts_path, ) logging.basicConfig(level=logging.INFO) logger = logging.getLogger("instrumentation_list_generator") _template = """ {header} # DO NOT EDIT. THIS FILE WAS AUTOGENERATED FROM INSTRUMENTATION PACKAGES. # RUN `python scripts/generate_instrumentation_bootstrap.py` TO REGENERATE. {source} """ _source_tmpl = """ libraries = {} default_instrumentations = [] """ gen_path = os.path.join( root_path, "opentelemetry-instrumentation", "src", "opentelemetry", "instrumentation", "bootstrap_gen.py", ) packages_to_exclude = [ # AWS Lambda instrumentation is excluded from the default list because it often # requires specific configurations and dependencies that may not be set up # in all environments. Instead, users who need AWS Lambda support can opt-in # by manually adding it to their environment. # See https://github.com/open-telemetry/opentelemetry-python-contrib/issues/2787 "opentelemetry-instrumentation-aws-lambda", # Google GenAI instrumentation is currently excluded because it is still in early # development. This filter will get removed once it is further along in its # development lifecycle and ready to be included by default. "opentelemetry-instrumentation-google-genai", # Langchain instrumentation is currently excluded because it is still in early # development. This filter will get removed once it is further along in its # development lifecycle and ready to be included by default. "opentelemetry-instrumentation-langchain", ] # Static version specifiers for instrumentations that are released independently independent_packages = { "opentelemetry-instrumentation-openai-v2": "", "opentelemetry-instrumentation-vertexai": ">=2.0b0", "opentelemetry-instrumentation-google-genai": "", } def main(): # pylint: disable=no-member default_instrumentations = ast.List(elts=[]) libraries = ast.List(elts=[]) for pkg in get_instrumentation_packages( independent_packages=independent_packages ): pkg_name = pkg.get("name") if pkg_name in packages_to_exclude: continue if not pkg["instruments"] and not pkg["instruments-any"]: default_instrumentations.elts.append(ast.Str(pkg["requirement"])) for target_pkg in pkg["instruments"]: libraries.elts.append( ast.Dict( keys=[ast.Str("library"), ast.Str("instrumentation")], values=[ast.Str(target_pkg), ast.Str(pkg["requirement"])], ) ) # instruments-any is an optional field that can be used instead of or in addition to _instruments. While _instruments is a list of dependencies, all of which are expected by the instrumentation, instruments-any is a list any of which but not all are expected. for target_pkg in pkg["instruments-any"]: libraries.elts.append( ast.Dict( keys=[ast.Str("library"), ast.Str("instrumentation")], values=[ast.Str(target_pkg), ast.Str(pkg["requirement"])], ) ) tree = ast.parse(_source_tmpl) tree.body[0].value = libraries tree.body[1].value = default_instrumentations source = astor.to_source(tree) with open( os.path.join(scripts_path, "license_header.txt"), encoding="utf-8" ) as header_file: header = header_file.read() source = _template.format(header=header, source=source) with open(gen_path, "w", encoding="utf-8") as gen_file: gen_file.write(source) subprocess.run( [ sys.executable, "scripts/eachdist.py", "format", "--path", "opentelemetry-instrumentation/src", ], check=True, ) logger.info("generated %s", gen_path) if __name__ == "__main__": main()