envoy: Decorator and tracing doesn't work when filter add/replace a header

When we want to use match with headers and some filter add/replace a header, the decorator or tracing doesn’t work correctly.

Test

We use the x-pool header to match the route and we inject this header in a filter.

In this example, we do a lower() of the header, and if the header is not modified, the decorator is correctly added and the request is sampled, but if we send the header with a capital letter, and it is modified, the request is routed correctly, but the decorator is not added and the request is not sampled.

OK:

curl -v localhost:8000/ -H "x-pool:pool"
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.77.0
> Accept: */*
> x-pool:pool
> 
< HTTP/1.1 200 OK
< x-sampled: True
< content-type: text/html; charset=utf-8
< content-length: 111
< server: envoy
< date: Fri, 19 Nov 2021 19:51:23 GMT
< x-envoy-upstream-service-time: 23
< x-envoy-decorator-operation: test

No add decorator and tracing:

curl -v localhost:8000/ -H "x-pool:POOL"
> GET / HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.77.0
> Accept: */*
> x-pool:POOL
> 
< HTTP/1.1 200 OK
< x-sampled: False
< content-type: text/html; charset=utf-8
< content-length: 111
< server: envoy
< date: Fri, 19 Nov 2021 19:53:21 GMT
< x-envoy-upstream-service-time: 26

Config

static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 8000
    traffic_direction: INBOUND
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          http_filters:
            - name: envoy.filters.http.lua
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.http.lua.v3.Lua
                inline_code: |
                  function envoy_on_request(request_handle)
                    local originalHeader = request_handle:headers():get("x-pool")
                    if originalHeader then
                      request_handle:headers():remove("x-pool")
                      request_handle:headers():add("x-pool", originalHeader:lower())
                    end
                  end
            - name: envoy.filters.http.router
              typed_config: {}
          request_id_extension:
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.request_id.uuid.v3.UuidRequestIdConfig
              pack_trace_reason: false
          generate_request_id: true
          tracing:
            verbose: true
            client_sampling:
              value: 0.0
            random_sampling:
              value: 0.0
            overall_sampling:
              value: 100.0
            provider:
              name: envoy.tracers.zipkin
              typed_config:
                "@type": type.googleapis.com/envoy.config.trace.v3.ZipkinConfig
                collector_cluster: otel 
                collector_endpoint: "/api/v2/spans"
                shared_span_context: true
                collector_endpoint_version: HTTP_JSON
          codec_type: AUTO
          stat_prefix: ingress_http
          route_config:
            name: reverse_proxy
            virtual_hosts:
            - name: pool
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                  headers:
                  - name: x-pool
                    exact_match: pool
                route:
                  cluster: cluster.test
                decorator:
                  operation: test
                tracing:
                  client_sampling:
                    numerator: 100
                  random_sampling:
                    numerator: 100
                  overall_sampling:
                    numerator: 100
  clusters:
  - name: cluster.test
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: cluster.test
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: service
                port_value: 8080
  - name: otel
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: otel
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: otel
                port_value: 9411
admin:
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 8001

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 39 (23 by maintainers)

Most upvoted comments

I read the previous discussions. I am not sure I get all the important info. So, if I miss anything, please call it out.

IMO, this is because the refreshCachedRoute do not handle the tracing config and decorator.

The request doesn’t match any route entry at first. So the Envoy does nothing about tracing or decorator. After the filters (lua or any other filter) update the header, the refreshCachedRoute will be called and a valid route entry is matched. But the refreshCachedRoute would not handle the tracing config and decorator in this route entry. For now, the Envoy handles the tracing config and decorator only before the filter chain is called.

And IMO, because the matched route entry may updated frequently, it’s hard for Envoy to update the tracing decision and decorator at each time the route entry changed.

@wbpcode Thanks for response. as per slack seems your tz is 3 hrs ahead to mine. pls suggest if we can find some common time to discuss… today we have some dev env issues , may be on coming Monday we can connect.

@matiasrege Sorry for late response… still debugging and stuck on some part… i would like discuss my finding with code owner to proceed further… in early next week may be. let’s catchup on slack …

@matiasrege I am back today and checking this bug… shall connect you Soon

/assign

@matiasrege i would like to work on this. I might need help for more understanding of this bug.