diff --git a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/config.py b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/config.py index ce451328..61b3aa7b 100644 --- a/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/config.py +++ b/libraries/microsoft-agents-a365-observability-core/microsoft_agents_a365/observability/core/config.py @@ -8,20 +8,17 @@ from typing import Any, Optional from opentelemetry import trace -from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( - OTLPSpanExporter as GrpcOTLPSpanExporter, -) -from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter +from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter from opentelemetry.sdk.resources import SERVICE_NAME, SERVICE_NAMESPACE, Resource from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import ConsoleSpanExporter +from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter from .exporters.agent365_exporter import _Agent365Exporter from .exporters.agent365_exporter_options import Agent365ExporterOptions from .exporters.enriching_span_processor import ( _EnrichingBatchSpanProcessor, ) -from .exporters.spectra_exporter_options import SpectraExporterOptions from .exporters.utils import is_agent365_exporter_enabled from .trace_processor.span_processor import SpanProcessor @@ -62,7 +59,7 @@ def configure( logger_name: str = DEFAULT_LOGGER_NAME, token_resolver: Callable[[str, str], str | None] | None = None, cluster_category: str = "prod", - exporter_options: Agent365ExporterOptions | SpectraExporterOptions | None = None, + exporter_options: Optional[Agent365ExporterOptions] = None, suppress_invoke_agent_input: bool = False, **kwargs: Any, ) -> bool: @@ -76,10 +73,9 @@ def configure( Use exporter_options instead. :param cluster_category: (Deprecated) Environment / cluster category (e.g. "prod"). Use exporter_options instead. - :param exporter_options: Exporter configuration. Pass Agent365ExporterOptions for A365 API - export, SpectraExporterOptions for Spectra Collector sidecar export, or None (default) - to construct Agent365ExporterOptions from legacy parameters. - :param suppress_invoke_agent_input: If True, suppress input messages for InvokeAgent spans. + :param exporter_options: Agent365ExporterOptions instance for configuring the exporter. + If provided, exporter_options takes precedence. If exporter_options is None, the token_resolver and cluster_category parameters are used as fallback/legacy support to construct a default Agent365ExporterOptions instance. + :param suppress_invoke_agent_input: If True, suppress input messages for spans that are children of InvokeAgent spans. :return: True if configuration succeeded, False otherwise. """ try: @@ -105,7 +101,7 @@ def _configure_internal( logger_name: str, token_resolver: Callable[[str, str], str | None] | None = None, cluster_category: str = "prod", - exporter_options: Agent365ExporterOptions | SpectraExporterOptions | None = None, + exporter_options: Optional[Agent365ExporterOptions] = None, suppress_invoke_agent_input: bool = False, **kwargs: Any, ) -> bool: @@ -161,43 +157,33 @@ def _configure_internal( "max_export_batch_size": exporter_options.max_export_batch_size, } - # Type-based exporter dispatch - if isinstance(exporter_options, SpectraExporterOptions): - # Spectra path — OTLP exporter to sidecar - # ENABLE_A365_OBSERVABILITY_EXPORTER is intentionally ignored. - if exporter_options.protocol == "grpc": - exporter = GrpcOTLPSpanExporter( - endpoint=exporter_options.endpoint, - insecure=exporter_options.insecure, - ) - else: - exporter = OTLPSpanExporter( - endpoint=exporter_options.endpoint, - ) - - elif is_agent365_exporter_enabled() and exporter_options.token_resolver is not None: + exporter = None + if is_agent365_exporter_enabled() and exporter_options.token_resolver is not None: exporter = _Agent365Exporter( token_resolver=exporter_options.token_resolver, cluster_category=exporter_options.cluster_category, use_s2s_endpoint=exporter_options.use_s2s_endpoint, + suppress_invoke_agent_input=suppress_invoke_agent_input, ) - + else: - exporter = ConsoleSpanExporter() - self._logger.warning( - "is_agent365_exporter_enabled() not enabled or token_resolver not set." - " Falling back to console exporter." - ) + + if os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"): + exporter = OTLPSpanExporter() + self._logger.warning( + "is_agent365_exporter_enabled() not enabled or token_resolver not set. Falling back to OTLP exporter." + ) + else: + exporter = ConsoleSpanExporter() + self._logger.warning( + "is_agent365_exporter_enabled() not enabled or token_resolver not set.Falling back to console exporter." + ) # Add span processors # Create _EnrichingBatchSpanProcessor with optimized settings # This allows extensions to enrich spans before export - batch_processor = _EnrichingBatchSpanProcessor( - exporter, - suppress_invoke_agent_input=suppress_invoke_agent_input, - **batch_processor_kwargs, - ) + batch_processor = _EnrichingBatchSpanProcessor(exporter, **batch_processor_kwargs) agent_processor = SpanProcessor() tracer_provider.add_span_processor(batch_processor) @@ -213,6 +199,7 @@ def _configure_internal( tracer_provider.add_span_processor( _EnrichingBatchSpanProcessor(otlp_exporter, **batch_processor_kwargs) ) + self._logger.info("OTLP exporter enabled.") # Configure logging if logger_name is provided if logger_name: @@ -271,8 +258,7 @@ def configure( logger_name: str = DEFAULT_LOGGER_NAME, token_resolver: Callable[[str, str], str | None] | None = None, cluster_category: str = "prod", - exporter_options: Agent365ExporterOptions | SpectraExporterOptions | None = None, - suppress_invoke_agent_input: bool = False, + exporter_options: Optional[Agent365ExporterOptions] = None, **kwargs: Any, ) -> bool: """ @@ -285,10 +271,8 @@ def configure( Use exporter_options instead. :param cluster_category: (Deprecated) Environment / cluster category (e.g. "prod"). Use exporter_options instead. - :param exporter_options: Exporter configuration. Pass Agent365ExporterOptions for A365 API - export, SpectraExporterOptions for Spectra Collector sidecar export, or None (default) - to construct Agent365ExporterOptions from legacy parameters. - :param suppress_invoke_agent_input: If True, suppress input messages for InvokeAgent spans. + :param exporter_options: Agent365ExporterOptions instance for configuring the exporter. + If provided, exporter_options takes precedence. If exporter_options is None, the token_resolver and cluster_category parameters are used as fallback/legacy support to construct a default Agent365ExporterOptions instance. :return: True if configuration succeeded, False otherwise. """ return _telemetry_manager.configure( @@ -298,7 +282,6 @@ def configure( token_resolver, cluster_category, exporter_options, - suppress_invoke_agent_input, **kwargs, )