Skip to content

bug: INFRAHUB_TRACE_INSECURE is ignored for the gRPC OTLP exporter (tracing fails with StatusCode.UNAVAILABLE) #9869

Description

@FragmentedPacket

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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions