caddyserver / caddy

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
https://caddyserver.com
Apache License 2.0
58.09k stars 4.03k forks source link

Use matched path as span name #6469

Open victoraugustolls opened 3 months ago

victoraugustolls commented 3 months ago

I'm trying to setup Caddy as the reverse proxy for our project and everything is great so far. We have a mix o reverse_proxies that uses path and some that use path_regexp.

The problem here is that, following OTel guidelines, the span name should be of low cardinality and for this I'm trying to use {http.method} {http.route}, where the http.route if the original path matching rule like so:

path:

Reverse proxy:

@service-panda-signin-matcher {
    method GET
    path /api/v1/users/login
}
reverse_proxy @service-panda-signin-matcher {
    to localhost
    rewrite /api/v1/identity/login
}

Expected span name: GET /api/v1/users/login

path_regexp:

Reverse proxy:

@admin-user-attack-detection-delete-matcher {
    method POST
    path_regexp ^/admin/v1/users/(.*)/accounts$
}
reverse_proxy @admin-user-attack-detection-delete-matcher {
    to localhost
    rewrite /admin/v1/identity/users/{re.1}/accounts
}

Expected span name: POST ^/admin/v1/users/(.*)/accounts$

Is this possible somehow? Thanks in advance.

francislavoie commented 3 months ago

I guess the tracing directive span name should support placeholder replacement support.

@andriikushch could you look into that, since you contributed tracing?

victoraugustolls commented 3 months ago

It does support placeholder replacement @francislavoie ! But I'm not seeing the necessary placeholders in the http.request.* for me to get the values described above. The closest to it is the http.request.uri.path but it gives me the final path, and not the matched one when its a path_regexp.

francislavoie commented 3 months ago

Hmm, I was reading the code and I don't see where it gets placeholder-replaced.

If you're using path_regexp, then you can just use {re.1} to grab the 1st match in the regexp. This is explained in the matcher docs https://caddyserver.com/docs/caddyfile/matchers#path-regexp

victoraugustolls commented 3 months ago

@francislavoie yes but if I'm setting up tracer on a listener, I have reverse_proxies that use path and path_regexp, so I must use the same value for the span name! What It would be needed here is to get the path "rule" for the span name.

francislavoie commented 3 months ago

I don't understand the problem. You haven't shown your full config so I don't have any context here.

victoraugustolls commented 3 months ago

@francislavoie here you have a sample config. In the original config the reverse_proxies are imported from individual proxies files.

Sample config:

{
    debug

    servers {
        metrics
    }
}

localhost {
    log {
    format console
    }

    tracing {
        span "{http.request.method} {http.request.uri.path}"
    }

    @admin-user-create-account-matcher {
        method POST
        path_regexp ^/admin/v1/users/(.*)/accounts$
    }
    reverse_proxy @admin-user-create-account-matcher {
        to localhost
        rewrite /admin/v1/identity/users/{re.1}/accounts
    }

    @admin-user-login-matcher {
        method POST
        path /admin/v1/users/login
    }
    reverse_proxy @admin-user-login-matcher {
        to localhost
        rewrite /admin/v1/identity/login
    }
}

localhost:80 {
    log {
    format console
    }

    tracing {
    span {http.request.uri.path.*}
    }

    handle_path /admin/* {
        respond "Hello!"
    }
}

Expected span names to keep low cardinality as recommended by Otel:

  1. POST /admin/v1/users/login
  2. POST ^/admin/v1/users/(.*)/accounts$

Possibly what I need is something like http.request.matcher.path, but I don't think this is available. Is there another way?