opentelemetry-collector: [processor/attributes] unable to add span custom attribute from custom header

Describe the bug By enabling include_metadata and using attributes processor I don’t see http headers from the POST request on the otlp http endpoint added as span attributes.

Steps to reproduce I have set include_metadata to true in my http otlp receiver I try to upsert a span custom attribute using attributes processor just like in this readme:

https://github.com/open-telemetry/opentelemetry-collector/blob/main/config/confighttp/README.md

In my case the header is CloudFront-Viewer-Longitude but I don’t think that’s relevant :

          - key: http.client_latitude
            from_context: CloudFront-Viewer-Latitude
            action: upsert
          - key: http.client_longitude
            from_context: CloudFront-Viewer-Longitude
            action: upsert

Anyway below you’ll find my full configuration.

What did you expect to see? CloudFront-Viewer-Longitude added as http.client_longitude span attribute.

What did you see instead? http.client_longitude is not added among span attributes.

What version did you use? otel/opentelemetry-collector-contrib:0.54.0

What config did you use?

receivers:
    otlp:
        protocols:
            http:
                include_metadata: true
                cors:
                    allowed_origins: [
                        ${RECEIVERS_OTLP_PROTOCOLS_HTTP_CORS_ALLOWED_ORIGINS}
                    ]
                    
    # Dummy receiver that's never used, because a pipeline is required to have one.
    otlp/spanmetrics:
        protocols:
            grpc:
                endpoint: "localhost:12345"

    prometheus/spanmetrics:
      config:
        scrape_configs:
          - job_name: 'ratelimiter'
            scrape_interval: 6m
            static_configs:
              - targets: ['localhost:8889']

processors:
    attributes/traces:
        actions:
          - key: http.client_latitude_2
            from_context: metadata.CloudFront-Viewer-Latitude
            action: upsert
          - key: http.client_longitude_2
            from_context: metadata.CloudFront-Viewer-Longitude
            action: upsert
          - key: http.client_latitude
            from_context: CloudFront-Viewer-Latitude
            action: upsert
          - key: http.client_longitude
            from_context: CloudFront-Viewer-Longitude
            action: upsert
          - key: test
            value: 123
            action: upsert
          - key: origin2
            from_context: metadata.origin
            action: upsert
          - key: client_latitude
            from_context: CloudFront-Viewer-Latitude
            action: upsert
          - key: client_longitude
            from_context: CloudFront-Viewer-Longitude
            action: upsert
          - key: client_latitude2
            from_context: cloudfront-viewer-latitude
            action: upsert
          - key: client_longitude2
            from_context: cloudfront-viewer-longitude
            action: upsert
          - key: client_latitude3
            from_context: metadata.cloudfront-viewer-latitude
            action: upsert
          - key: client_longitude3
            from_context: metadata.cloudfront-viewer-longitude
            action: upsert
          - key: client_latitude4
            from_context: metadata.CloudFront-Viewer-Latitude
            action: upsert
          - key: client_longitude4
            from_context: metadata.CloudFront-Viewer-Longitude
            action: upsert
    memory_limiter:
        check_interval: 5s
        limit_mib: 448
        spike_limit_mib: 64
    batch:
        send_batch_size: 48
        send_batch_max_size: 48
        timeout: 15s
    transform:
        logs:
            queries:
                - set(attributes["severity_text"], severity_text)
    filter:
        logs:
            exclude:
                match_type: regexp
                record_attributes:
                    - key: severity_text
                      value: "(TRACE|DEBUG)"
    spanmetrics:
        metrics_exporter: prometheus/spanmetrics
        dimensions:
            - name: enduser.id
            - name: http.status_code
            - name: http.client_ip
            - name: http.client_latitude
            - name: http.client_longitude
            - name: http.method
        aggregation_temporality: "AGGREGATION_TEMPORALITY_DELTA"

exporters:
    logging:
        loglevel: ${EXPORTERS_LOGGING_LOGLEVEL}
    otlp:
        endpoint: tempo-eu-west-0.grafana.net:443
        headers:
            authorization: ##########
            
    prometheusremotewrite:
        endpoint: https://prometheus-prod-01-eu-west-0.grafana.net/api/prom/push
        headers:
            authorization: ##########
            
    loki:
        endpoint: https://logs-prod-eu-west-0.grafana.net/loki/api/v1/push
        headers:
            authorization: ##########
        format: json
        labels:
            attributes:
                container_name: ""
                source: ""
            resource:
                host.name: "hostname"
                
    prometheus/spanmetrics:
        endpoint: "localhost:8889"

extensions:
    health_check:
service:
    telemetry:
        logs:
            level: ${SERVICE_TELEMETRY_LOGS_LEVEL}
    extensions: [health_check]
    pipelines:
        traces:
            receivers: [otlp]
            processors: [attributes/traces, spanmetrics, memory_limiter, batch]
            exporters: [otlp, logging]
        metrics/spanmetrics:
            # This receiver is just a dummy and never used.
            # Added to pass validation requiring at least one receiver in a pipeline.
            receivers: [otlp/spanmetrics]
            # The metrics_exporter must be present in this list.
            exporters: [prometheus/spanmetrics]
        metrics:
            receivers: [otlp, prometheus/spanmetrics]
            processors: [memory_limiter, batch]
            exporters: [prometheusremotewrite]
        logs:
            receivers: [otlp]
            processors: [transform, filter, memory_limiter, batch]
            exporters: [loki]

Environment AWS Beanstalk with Docker Linux V2

Additional context

I need this to inject AWS Cloudfront geolocation headers into my spans : https://aws.amazon.com/it/about-aws/whats-new/2020/07/cloudfront-geolocation-headers/

I have put my otel collector behind a non caching Cloudfront, and it is properly receiving POST http requests on v1/traces with those headers containing latitude and logitude.

I am sure everything is received properly because I am running tcpdump on 4318 port on otel collector and I DO see those headers.

Now I need to propagate those values from the http request, containing the spans in its body, to the span themself.

This is what include_metadata is supposed to enable, right ? Did I understand correctly ?

I also tried different combinations, trying to read from metadata context (inspired by https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/processor/attributesprocessor/testdata/config.yaml) but none worked.

The only attribute I see properly set is “test” to value 123, but that’s the only key not using “from_context”.

Please help.

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 23 (8 by maintainers)

Commits related to this issue

Most upvoted comments

I just submitted a new PR that would fix this:

processors:
  attributes:
    actions:
      - key: http.client_latitude
        from_context: metadata.X-CloudFront-Viewer-Latitude
        action: upsert
      - key: http.client_latitude2
        from_context: metadata.X-Cloudfront-Viewer-Latitude
        action: upsert
Attributes:
     -> http.method: STRING(POST)
     -> http.url: STRING(https://services.optoplus.cloud/optoplus-services-web/api/lens/compute)
     -> http.response_content_length: INT(0)
     -> http.status_code: INT(200)
     -> http.status_text: STRING()
     -> http.host: STRING(services.optoplus.cloud)
     -> http.scheme: STRING(https)
     -> http.user_agent: STRING(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44)
     -> http.client_latitude: STRING(44.44444)
     -> http.client_latitude2: STRING(44.44444)

New test :

          - key: http.client_latitude
            from_context: CloudFront-Viewer-Latitude
            action: upsert
          - key: http.client_longitude
            from_context: CloudFront-Viewer-Longitude
            action: upsert
          - key: http.client_latitude2
            from_context: metadata.CloudFront-Viewer-Latitude
            action: upsert
          - key: http.client_longitude2
            from_context: metadata.CloudFront-Viewer-Longitude
            action: upsert
          - key: http.client_latitude3
            value: 123
            action: upsert
          - key: http.client_longitude3
            value: 123
            action: upsert
          - key: http.client_latitude4
            from_context: metadata.CloudFront-Viewer-Latitude
            action: insert
          - key: http.client_longitude4
            from_context: metadata.CloudFront-Viewer-Longitude
            action: insert
          - key: http.client_latitude5
            from_context: CloudFront-Viewer-Latitude
            action: insert
          - key: http.client_longitude5
            from_context: CloudFront-Viewer-Longitude
            action: insert
          - key: test1
            from_context: metadata.X-Forwarded-For
            action: upsert
          - key: test2
            from_context: X-Forwarded-For
            action: upsert
          - key: test3
            from_context: metadata.X-Forwarded-For
            action: insert
          - key: test4
            from_context: X-Forwarded-For
            action: insert
          - key: test5
            from_context: metadata.X-Amzn-Trace-Id
            action: upsert
          - key: test6
            from_context: X-Amzn-Trace-Id
            action: upsert
          - key: test7
            from_context: metadata.X-Amzn-Trace-Id
            action: insert
          - key: test8
            from_context: X-Amzn-Trace-Id
            action: insert
          - key: test11
            from_context: metadata.Via
            action: upsert
          - key: test12
            from_context: Via
            action: upsert
          - key: test13
            from_context: metadata.Via
            action: insert
          - key: test14
            from_context: Via
            action: insert

Then this is logged :

Span #5
    Trace ID       : 0275913834ce9a99b5cc0047ded211c9
    Parent ID      : 
    ID             : 28827a6522de56bb
    Name           : click
    Kind           : SPAN_KIND_INTERNAL
    Start time     : 2022-07-07 09:14:05.8470003 +0000 UTC
    End time       : 2022-07-07 09:14:05.8471002 +0000 UTC
    Status code    : STATUS_CODE_UNSET
    Status message : 
Attributes:
     -> component: STRING(user-interaction)
     -> event_type: STRING(click)
     -> target_element: STRING(SPAN)
     -> target_xpath: STRING(//html/body/div[3]/div[2]/div/div/div/mat-option[10]/span)
     -> http.url: STRING(https://calc.optoplus.cloud/#/factory/compute)
     -> http.user_agent: STRING(Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.66 Safari/537.36 Edg/103.0.1264.44)
     -> http.client_latitude3: INT(123)
     -> http.client_longitude3: INT(123)
     -> test1: STRING(2.118.34.194, 130.176.221.40)
     -> test2: STRING(2.118.34.194, 130.176.221.40)
     -> test3: STRING(2.118.34.194, 130.176.221.40)
     -> test4: STRING(2.118.34.194, 130.176.221.40)
     -> test5: STRING(Root=1-62c6a3e0-7a2f843d26dac2c1205716cd)
     -> test6: STRING(Root=1-62c6a3e0-7a2f843d26dac2c1205716cd)
     -> test7: STRING(Root=1-62c6a3e0-7a2f843d26dac2c1205716cd)
     -> test8: STRING(Root=1-62c6a3e0-7a2f843d26dac2c1205716cd)
     -> test11: STRING(2.0 ec2e016357b2a4b61d6fc1a2e7c0826a.cloudfront.net (CloudFront))
     -> test12: STRING(2.0 ec2e016357b2a4b61d6fc1a2e7c0826a.cloudfront.net (CloudFront))
     -> test13: STRING(2.0 ec2e016357b2a4b61d6fc1a2e7c0826a.cloudfront.net (CloudFront))
     -> test14: STRING(2.0 ec2e016357b2a4b61d6fc1a2e7c0826a.cloudfront.net (CloudFront))
Resource SchemaURL: 
Resource labels:
     -> service.name: STRING(optoplus-calc-prod)
     -> telemetry.sdk.language: STRING(webjs)
     -> telemetry.sdk.name: STRING(opentelemetry)
     -> telemetry.sdk.version: STRING(1.2.0)

So the problem is related ONLY to the specific CloudFront-Viewer-Latitude and CloudFront-Viewer-Longitude headers … How can this be even possible 😢 ?

image image

THANK YOU very much @jpkrohling , going to test it right now …

EDIT : Yea, this is working properly !

Anyway this should be fixed, the match with the header should be ignore case !!!

X-Cloudfront-Viewer-Latitude and x-cloudfront-viewer-latitude are the same http header, doing otherwise could lead to issues with libraries and sdk IMHO.