Skip to content

Instrumentation Request for gin-gonic/gin #479

@waqar2403

Description

@waqar2403

Is there an existing issue for this?

  • I have searched the existing issues

Package

github.com/gin-gonic/gin

Version

v1.10.0 (current stable; needs >= v1.4.0 for FullPath())

Environment

Go HTTP servers, mostly containerized. Gin is pretty widely used this would cover a lot of ground.

Use-case

REST APIs built with gin. The net/http hook right now gives spans like "GET" with url.path=/users/42 but there's no way to get the actual route template. With gin, c.FullPath() returns /users/:id which is what you do want as http.route for grouping requests properly in dashboards. Without it every unique URL becomes its own series.
The hard part is that c.FullPath() is only populated after gin's router matches the request so a gin-specific hook is needed on top of net/http.

Telemetry

Server spans following HTTP semconv v1.37.0, same attributes as the existing nethttp server hook http.request.method, http.response.status_code, url.path, server.address, etc. The key addition would be http.route from c.FullPath().

Span name would go from just "GET" to "GET /users/:id" after the route is resolved. 5xx responses would set span status to Error. Metrics deferred to a follow-up.

Anything else?

While looking into this I checked how loongsuite and dd-trace-go handle gin:

  • loongsuite (alibaba/loongsuite-go-agent/pkg/rules/gin/) hooks (*Context) Next and uses GLS to find the span. Since otelc uses context.Context instead of GLS, that approach doesn't directly apply here.
  • dd-trace-go (DataDog/dd-trace-go/contrib/gin-gonic/gin/) adds a runtime middleware but that requires the user to change their code.

What I'm thinking is two hooks in one YAML file (similar to how redis/v9/v9.yaml has multiple rules):

  1. (*Engine).ServeHTTP start the span, wrap ResponseWriter, pass context through r.WithContext(ctx)
  2. (*Context).Next at this point routing is done, so read c.FullPath() and update the span name

I've been experimenting locally and have something that seems to work with basic unit tests. Happy to share it once we agree on the approach
Also not sure if this needs an ADR since it's the first case of two hooks coordinating through request context.

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions