Search code examples
dockersecuritynetworkingopen-telemetryjaeger

Open Telemetry CORS issue exporting trace data to Jaeger


I'm trying to send trace data from client application by @opentelemetry/exporter-collector to jaeger-collector, but the calls are blocked by CORS. I was trying to setup exporter-collector headers to solve the issue but it didn't help. I'm not familiar with Docker so I don't have any idea how configure it correctly. Jaeger UI is running as expected.

Client:

const collector = new CollectorTraceExporter({
  url: 'http://localhost:14268/api/traces',
  headers: {
    'Content-Type': 'application/json',
    'Access-Control-Allow-Headers': '*',
    'X-CSRF': '1',
  },
});
provider.addSpanProcessor(new SimpleSpanProcessor(collector));

docker-compose.yml

jaeger:
    container_name: jaeger
    image: jaegertracing/all-in-one:1.9
    environment:
      COLLECTOR_OTLP_ENABLED: true
    ports:
      - 16686:16686 # Jaeger UI
      - 14268:14268 # Collector
      - 4317:4317 # OpenTelemetry GRPC
      - 6831:6831 # OpenTelemetry HTTP

Response: Response


Solution

  • Access-Control-Allow-Headers is a response header, so it should be send by the receiving end (in your case Jaeger). Jaeger supports those for zipkin (https://www.jaegertracing.io/docs/latest/cli/ see '--collector.zipkin.allowed-headers'), but not for OTLP.

    There are now 2 things you can do:

    1. Put a reverse proxy (nginx, apache, ...) between your app and jaeger and let the proxy do the CORS handling
    2. Use an OpenTelemetry collector which comes with CORS headers configuration.

    For (1) you could use something like the following in nginx:

    server {
        listen 80 default_server;
        server_name _;
        location / {
            add_header 'Access-Control-Allow-Origin' '*' always;
            add_header 'Access-Control-Allow-Headers' 'Accept,Accept-Language,Content-Language,Content-Type' always;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://jaeger:4318;
        }
    }
    

    A more detailed example for this is described here (although it is a combination of OTel collector and nginx): https://opentelemetry.io/docs/instrumentation/js/exporters/#securely-expose-your-collector

    For (2) you can setup the OTel collecor using a feature available for all http-based receivers:

    receivers:
      otlp:
        protocols:
          http:
            include_metadata: true
            cors:
              allowed_origins:
                - https://foo.bar.com
                - https://*.test.com
              allowed_headers:
                - Example-Header
              max_age: 7200