Summary
config.SETTINGS.trace.insecure (env INFRAHUB_TRACE_INSECURE, default True) is never
forwarded to the OpenTelemetry OTLP exporter. As a result the gRPC exporter falls back to
the SDK default (insecure=False) and attempts a TLS connection. Against a plaintext
OTLP collector (e.g. Grafana Tempo's OTLP/gRPC receiver on :4317), every span export
fails with:
Failed to export traces to <endpoint>, error code: StatusCode.UNAVAILABLE
No traces are ever delivered, even though INFRAHUB_TRACE_INSECURE=true is set.
Affected version
- Infrahub Enterprise 1.10.2 (also present in the current tracing code path)
- Exporter:
opentelemetry-exporter-otlp-proto-grpc
- Collector under test: Grafana Tempo 2.10.3 (OTLP/gRPC, plaintext,
:4317)
Root cause
backend/infrahub/trace.py builds the exporter without passing insecure:
elif exporter_protocol == "grpc":
exporter = GRPCSpanExporter(endpoint=exporter_endpoint) # insecure not passed
create_tracer_provider() / configure_trace() do not accept an insecure argument, and
the three callers never pass config.SETTINGS.trace.insecure:
backend/infrahub/server.py:58
backend/infrahub/cli/git_agent.py:108
backend/infrahub/workers/infrahub_async.py:103
configure_trace(
service="infrahub-server",
version=__version__,
exporter_type=config.SETTINGS.trace.exporter_type,
exporter_endpoint=config.SETTINGS.trace.exporter_endpoint,
exporter_protocol=config.SETTINGS.trace.exporter_protocol,
# config.SETTINGS.trace.insecure is never passed
)
Meanwhile the setting is defined and defaults to True:
# backend/infrahub/config.py:1012
insecure: bool = Field(
default=True,
description="Use insecure connection (HTTP) if True, otherwise use secure connection (HTTPS)",
)
So the documented INFRAHUB_TRACE_INSECURE knob has no effect on the gRPC path.
Reproduction
With Infrahub configured for OTLP/gRPC to a plaintext collector:
INFRAHUB_TRACE_ENABLE=true
INFRAHUB_TRACE_EXPORTER_TYPE=otlp
INFRAHUB_TRACE_EXPORTER_PROTOCOL=grpc
INFRAHUB_TRACE_EXPORTER_ENDPOINT=<tempo-host>:4317
INFRAHUB_TRACE_INSECURE=true
Server logs stream StatusCode.UNAVAILABLE; the collector receives zero spans.
Minimal confirmation that the flag is the cause (same container, same endpoint):
| Exporter construction |
Result |
GRPCSpanExporter(endpoint=EP) (current behavior, insecure=None → TLS) |
SpanExportResult.FAILURE |
GRPCSpanExporter(endpoint=EP, insecure=True) |
SpanExportResult.SUCCESS |
endpoint="http://"+EP (scheme forces insecure) |
SpanExportResult.SUCCESS |
env OTEL_EXPORTER_OTLP_TRACES_INSECURE=true |
SpanExportResult.SUCCESS |
Suggested fix
Thread insecure through and pass it to the gRPC exporter:
# trace.py
def create_tracer_provider(
service: str,
version: str,
exporter_type: str,
exporter_endpoint: str | None = None,
exporter_protocol: str | None = None,
insecure: bool = True,
) -> TracerProvider:
...
elif exporter_protocol == "grpc":
exporter = GRPCSpanExporter(endpoint=exporter_endpoint, insecure=insecure)
Add the same insecure parameter to configure_trace() and pass
config.SETTINGS.trace.insecure from all three callers.
Note: the OTLP HTTP exporter has no insecure argument — it derives TLS from the
endpoint URL scheme (http:// vs https://), so for http/protobuf the endpoint should
carry an explicit scheme. Worth handling/validating in the same change.
Workaround (no code change)
Set the standard OpenTelemetry env var, which the gRPC exporter honors directly:
OTEL_EXPORTER_OTLP_TRACES_INSECURE=true
(or give the endpoint an http:// scheme).
Summary
config.SETTINGS.trace.insecure(envINFRAHUB_TRACE_INSECURE, defaultTrue) is neverforwarded to the OpenTelemetry OTLP exporter. As a result the gRPC exporter falls back to
the SDK default (
insecure=False) and attempts a TLS connection. Against a plaintextOTLP collector (e.g. Grafana Tempo's OTLP/gRPC receiver on
:4317), every span exportfails with:
No traces are ever delivered, even though
INFRAHUB_TRACE_INSECURE=trueis set.Affected version
opentelemetry-exporter-otlp-proto-grpc:4317)Root cause
backend/infrahub/trace.pybuilds the exporter without passinginsecure:create_tracer_provider()/configure_trace()do not accept aninsecureargument, andthe three callers never pass
config.SETTINGS.trace.insecure:backend/infrahub/server.py:58backend/infrahub/cli/git_agent.py:108backend/infrahub/workers/infrahub_async.py:103Meanwhile the setting is defined and defaults to
True:So the documented
INFRAHUB_TRACE_INSECUREknob has no effect on the gRPC path.Reproduction
With Infrahub configured for OTLP/gRPC to a plaintext collector:
Server logs stream
StatusCode.UNAVAILABLE; the collector receives zero spans.Minimal confirmation that the flag is the cause (same container, same endpoint):
GRPCSpanExporter(endpoint=EP)(current behavior,insecure=None→ TLS)SpanExportResult.FAILUREGRPCSpanExporter(endpoint=EP, insecure=True)SpanExportResult.SUCCESSendpoint="http://"+EP(scheme forces insecure)SpanExportResult.SUCCESSOTEL_EXPORTER_OTLP_TRACES_INSECURE=trueSpanExportResult.SUCCESSSuggested fix
Thread
insecurethrough and pass it to the gRPC exporter:Add the same
insecureparameter toconfigure_trace()and passconfig.SETTINGS.trace.insecurefrom all three callers.Note: the OTLP HTTP exporter has no
insecureargument — it derives TLS from theendpoint URL scheme (
http://vshttps://), so forhttp/protobufthe endpoint shouldcarry an explicit scheme. Worth handling/validating in the same change.
Workaround (no code change)
Set the standard OpenTelemetry env var, which the gRPC exporter honors directly:
(or give the endpoint an
http://scheme).