The OpenTelemetry Collector's configuration is deploy/otel-collector/config.yaml, mounted read-only into the otel-collector service (Observability). Values such as ${env:STACKR_ENVIRONMENT} are read from the service's environment, which compose.yaml sets from .env.
${env:STACKR_TRACES_EXPORTERS}: set by make up from the profiles
metrics
otlp
memory_limiter, resource/environment, batch
otlp_http/prometheus
logs
otlp
memory_limiter, resource/environment, batch
otlp_http/loki
The traces pipeline's exporters come from STACKR_TRACES_EXPORTERS, which make up sets from the profiles: [otlp_grpc/tempo, otlp_http/langfuse] when the langfuse profile runs, and [otlp_grpc/tempo] when it doesn't. Compose's default, for plain docker compose, is both.
LANGFUSE_OTLP_AUTH is base64 of the Langfuse project's public and secret keys, which make env derives. Prometheus scrapes the Collector's own metrics on port 8888 for the Collector health dashboard; neither 8888 nor the health check's 13133 is published.
# The OpenTelemetry Collector: every application, and the LiteLLM proxy, sends# OTLP here, and the Collector fans it out:# traces -> Tempo, and Langfuse when the langfuse profile runs# metrics -> Prometheus, through its OTLP receiver# logs -> Loki, through its OTLP endpoint# See docs/architecture.md and ADR-0007.extensions:health_check:endpoint:0.0.0.0:13133receivers:otlp:protocols:grpc:endpoint:0.0.0.0:4317http:endpoint:0.0.0.0:4318cors:# Browser applications served from this machine can send OTLP too.allowed_origins:["http://localhost:*","http://127.0.0.1:*"]processors:memory_limiter:check_interval:1slimit_percentage:80spike_limit_percentage:25# Telemetry that doesn't say which environment it comes from is labelled# with STACKR_ENVIRONMENT (`local` by default).resource/environment:attributes:-key:deployment.environment.namevalue:${env:STACKR_ENVIRONMENT}action:insertbatch:{}exporters:otlp_grpc/tempo:endpoint:tempo:4317tls:insecure:trueotlp_http/prometheus:endpoint:http://prometheus:9090/api/v1/otlptls:insecure:trueotlp_http/loki:endpoint:http://loki:3100/otlptls:insecure:true# Langfuse takes traces only, over OTLP HTTP. The ingestion version header# makes them visible as soon as they are written.otlp_http/langfuse:endpoint:http://langfuse-web:3000/api/public/otelheaders:Authorization:Basic ${env:LANGFUSE_OTLP_AUTH}x-langfuse-ingestion-version:"4"service:extensions:[health_check]pipelines:traces:receivers:[otlp]processors:[memory_limiter,resource/environment,batch]# [otlp_grpc/tempo, otlp_http/langfuse], or Tempo alone when the# langfuse profile isn't running; set in compose.yaml and the Makefile.exporters:${env:STACKR_TRACES_EXPORTERS}metrics:receivers:[otlp]processors:[memory_limiter,resource/environment,batch]exporters:[otlp_http/prometheus]logs:receivers:[otlp]processors:[memory_limiter,resource/environment,batch]exporters:[otlp_http/loki]telemetry:# The Collector's own metrics, scraped by Prometheus for the Collector# dashboard.metrics:level:detailedreaders:-pull:exporter:prometheus:host:0.0.0.0port:8888logs:level:info