diff --git a/config.yaml b/config.yaml index 3449098..25bfb91 100644 --- a/config.yaml +++ b/config.yaml @@ -144,13 +144,13 @@ sdk: # Environment variable: OTEL_TRACES_EXPORTER exporter: console # Add a batch span processor configured with zipkin exporter. For full description of options see sdk.tracer_provider.span_processors[0]. - batch/zipkin: - args: - exporter: zipkin - # Add a batch span processor configured with jaeger exporter. For full description of options see sdk.tracer_provider.span_processors[0]. - batch/jaeger: - args: - exporter: jaeger + # batch/zipkin: + # args: + # exporter: zipkin + # # Add a batch span processor configured with jaeger exporter. For full description of options see sdk.tracer_provider.span_processors[0]. + # batch/jaeger: + # args: + # exporter: jaeger # Configure the span limits. See also sdk.attribute_limits. span_limits: # Set the max span attribute value size. Overrides sdk.attribute_limits.attribute_value_length_limit. diff --git a/prototypes/python/otel.py b/prototypes/python/otel.py index 6f7e7ad..7def73e 100644 --- a/prototypes/python/otel.py +++ b/prototypes/python/otel.py @@ -1,4 +1,5 @@ +import importlib import logging import yaml @@ -8,6 +9,7 @@ from opentelemetry.trace import set_tracer_provider + class Config: def __init__(self, config=None) -> None: self._config = config @@ -17,14 +19,60 @@ def _resource(self): # attributes from opentelemetry.sdk.resources import Resource return Resource.create(self._config.get("sdk").get("resource").get("attributes")) + + # _get_exporter returns a configured span + def _get_exporter(self, signal, name): + if name not in self._config.get("sdk").get(signal).get("exporters"): + raise Exception(f"exporter {name} not specified for {signal} signal") + # TODO: replace to use entrypoints + _KNOWN_TRACE_EXPORTER_MAP = { + "traces": { + "console": { + "pkg": "opentelemetry.sdk.trace.export", + "class": "ConsoleSpanExporter", + }, + "jaeger": { + "pkg": "opentelemetry.exporter.jaeger.thrift", + "class": "JaegerExporter", + }, + "zipkin": { + "pkg": "opentelemetry.exporter.zipkin.json", + "class": "ZipkinExporter", + }, + }, + "metrics": { + "console": { + "pkg": "opentelemetry.sdk.metrics.export", + "class": "ConsoleExporter", + }, + }, + "logs": { + "console": { + "pkg": "opentelemetry.sdk.logs.export", + "class": "ConsoleExporter", + }, + } + } + # look for known exporters + if name in _KNOWN_TRACE_EXPORTER_MAP.get(signal): + mod = importlib.__import__(_KNOWN_TRACE_EXPORTER_MAP.get(signal).get(name).get("pkg"), fromlist=[_KNOWN_TRACE_EXPORTER_MAP.get(signal).get(name).get("class")]) + _cls = getattr(mod, _KNOWN_TRACE_EXPORTER_MAP.get(signal).get(name).get("class")) + return _cls() + # handle case where a custom exporter is used + def set_tracer_provider(self): from opentelemetry.sdk.trace import TracerProvider provider = TracerProvider(resource=self._resource()) - from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter + from opentelemetry.sdk.trace.export import BatchSpanProcessor - processor = BatchSpanProcessor(ConsoleSpanExporter()) - provider.add_span_processor(processor) + for processor in self._config.get("sdk").get("traces").get("span_processors"): + logging.debug("adding span processor %s", processor) + try: + processor = BatchSpanProcessor(self._get_exporter("traces", self._config.get("sdk").get("traces").get("span_processors").get(processor).get("args").get("exporter"))) + provider.add_span_processor(processor) + except ModuleNotFoundError as exc: + logging.error("module not found", exc) set_tracer_provider(provider) def set_meter_provider(self): @@ -34,7 +82,6 @@ def apply(self): logging.debug("applying configuration %s", self._config) if self._config is None or self._config.get("sdk").get("disabled"): logging.debug("sdk disabled, nothing to apply") - # do nothing return self.set_tracer_provider() self.set_meter_provider() @@ -42,6 +89,8 @@ def apply(self): NoOpConfig = Config() +def configure(configuration: Config) -> None: + configuration.apply() def parse_and_validate_from_config_file(filename: str, schema: str="../schema/schema.json") -> Config: logging.debug(f"Loading config file: {filename}") diff --git a/prototypes/python/prototype.py b/prototypes/python/prototype.py index 8098a8c..097bfa0 100644 --- a/prototypes/python/prototype.py +++ b/prototypes/python/prototype.py @@ -5,14 +5,13 @@ from opentelemetry.trace import get_tracer -from otel import parse_and_validate_from_config_file +import otel def main(): logging.basicConfig(level=logging.DEBUG) - config = parse_and_validate_from_config_file(sys.argv[1], sys.argv[2]) - config.apply() + otel.configure(otel.parse_and_validate_from_config_file(sys.argv[1], sys.argv[2])) tracer = get_tracer("config-prototype")