From f1b5863bb56bcb0bd582a129838fe25dcd385f5d Mon Sep 17 00:00:00 2001 From: GareArc Date: Mon, 9 Feb 2026 01:29:40 -0800 Subject: [PATCH] feat(enterprise-telemetry): wire bearer token auth and configurable insecure flag into OTEL exporter --- api/enterprise/telemetry/exporter.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/api/enterprise/telemetry/exporter.py b/api/enterprise/telemetry/exporter.py index 8b66157c61..247e03691f 100644 --- a/api/enterprise/telemetry/exporter.py +++ b/api/enterprise/telemetry/exporter.py @@ -64,19 +64,20 @@ def _datetime_to_ns(dt: datetime) -> int: class _ExporterFactory: - def __init__(self, protocol: str, endpoint: str, headers: dict[str, str]): + def __init__(self, protocol: str, endpoint: str, headers: dict[str, str], insecure: bool): self._protocol = protocol self._endpoint = endpoint self._headers = headers self._grpc_headers = tuple(headers.items()) if headers else None self._http_headers = headers or None + self._insecure = insecure def create_trace_exporter(self) -> HTTPSpanExporter | GRPCSpanExporter: if self._protocol == "grpc": return GRPCSpanExporter( endpoint=self._endpoint or None, headers=self._grpc_headers, - insecure=True, + insecure=self._insecure, ) trace_endpoint = f"{self._endpoint}/v1/traces" if self._endpoint else "" return HTTPSpanExporter(endpoint=trace_endpoint or None, headers=self._http_headers) @@ -86,7 +87,7 @@ class _ExporterFactory: return GRPCMetricExporter( endpoint=self._endpoint or None, headers=self._grpc_headers, - insecure=True, + insecure=self._insecure, ) metric_endpoint = f"{self._endpoint}/v1/metrics" if self._endpoint else "" return HTTPMetricExporter(endpoint=metric_endpoint or None, headers=self._http_headers) @@ -107,6 +108,9 @@ class EnterpriseExporter: service_name: str = getattr(config, "ENTERPRISE_SERVICE_NAME", "dify") sampling_rate: float = getattr(config, "ENTERPRISE_OTEL_SAMPLING_RATE", 1.0) self.include_content: bool = getattr(config, "ENTERPRISE_INCLUDE_CONTENT", True) + api_key: str = getattr(config, "ENTERPRISE_OTLP_API_KEY", "") + # Auto-detect TLS: when bearer token is configured, use secure channel + insecure: bool = not bool(api_key) resource = Resource( attributes={ @@ -119,7 +123,14 @@ class EnterpriseExporter: self._tracer_provider = TracerProvider(resource=resource, sampler=sampler, id_generator=id_generator) headers = _parse_otlp_headers(headers_raw) - factory = _ExporterFactory(protocol, endpoint, headers) + if api_key: + if "authorization" in headers: + logger.warning( + "ENTERPRISE_OTLP_API_KEY is set but ENTERPRISE_OTLP_HEADERS also contains " + "'authorization'; the API key will take precedence." + ) + headers["authorization"] = f"Bearer {api_key}" + factory = _ExporterFactory(protocol, endpoint, headers, insecure=insecure) trace_exporter = factory.create_trace_exporter() self._tracer_provider.add_span_processor(BatchSpanProcessor(trace_exporter))