2 Commits

Author SHA1 Message Date
340cf67515 update changelog 2025-08-27 10:33:39 -04:00
f5cb3456b1 fix otel http instrumentation span naming (#2)
Reviewed-on: #2
Co-authored-by: Ryan D McGuire <ryand_mcguire@sweetwater.com>
Co-committed-by: Ryan D McGuire <ryand_mcguire@sweetwater.com>
2025-08-27 14:32:16 +00:00
2 changed files with 29 additions and 18 deletions

View File

@@ -1,3 +1,7 @@
# v0.12.1
* feat: Implement custom OpenTelemetry span name formatting for HTTP requests.
* refactor: Streamline OpenTelemetry handler integration by removing custom wrapper.
# v0.12.0 # v0.12.0
* feat: Add support for excluding HTTP request paths from logging using configurable regular expressions. * feat: Add support for excluding HTTP request paths from logging using configurable regular expressions.

View File

@@ -10,6 +10,7 @@ import (
"net" "net"
"net/http" "net/http"
"os" "os"
"regexp"
"strings" "strings"
"time" "time"
@@ -25,11 +26,12 @@ import (
) )
var ( var (
httpMeter metric.Meter httpMeter metric.Meter
httpTracer trace.Tracer httpTracer trace.Tracer
defReadTimeout = 10 * time.Second httpPatternWithMethodRegexp = regexp.MustCompile(`(\w+) .*`)
defWriteTimeout = 10 * time.Second defReadTimeout = 10 * time.Second
defIdleTimeout = 15 * time.Second defWriteTimeout = 10 * time.Second
defIdleTimeout = 15 * time.Second
) )
func prepHTTPServer(opts *opts.AppHTTP) *http.Server { func prepHTTPServer(opts *opts.AppHTTP) *http.Server {
@@ -39,19 +41,12 @@ func prepHTTPServer(opts *opts.AppHTTP) *http.Server {
mux = &http.ServeMux{} mux = &http.ServeMux{}
) )
// NOTE: Wraps handle func with otelhttp handler and
// inserts route tag
otelHandleFunc := func(pattern string, handlerFunc func(http.ResponseWriter, *http.Request)) {
handler := otelhttp.WithRouteTag(pattern, http.HandlerFunc(handlerFunc))
mux.Handle(pattern, handler) // Associate pattern with handler
}
healthChecks := handleHealthCheckFunc(opts.Ctx, opts.HealthChecks...) healthChecks := handleHealthCheckFunc(opts.Ctx, opts.HealthChecks...)
otelHandleFunc("/health", healthChecks) mux.HandleFunc("/health", healthChecks)
otelHandleFunc("/", healthChecks) mux.HandleFunc("/", healthChecks)
for _, f := range opts.Funcs { for _, f := range opts.Funcs {
otelHandleFunc(f.Path, f.HandlerFunc) mux.HandleFunc(f.Path, f.HandlerFunc)
} }
// Prometheus metrics endpoint // Prometheus metrics endpoint
@@ -74,12 +69,12 @@ func prepHTTPServer(opts *opts.AppHTTP) *http.Server {
if h.StripPrefix { if h.StripPrefix {
h.Handler = http.StripPrefix(h.Prefix[:len(h.Prefix)-1], h.Handler) h.Handler = http.StripPrefix(h.Prefix[:len(h.Prefix)-1], h.Handler)
} }
mux.Handle(h.Prefix, h.Handler) mux.Handle(h.Prefix, otelhttp.WithRouteTag(h.Prefix, h.Handler))
} }
// Add OTEL, skip health-check spans // Add OTEL instrumentation, filter noise, set span names
// NOTE: Add any other span exclusions here
handler := otelhttp.NewHandler(mux, "/", handler := otelhttp.NewHandler(mux, "/",
// TODO: Make configurable similar to config.http.LogExcludePathRegexps
otelhttp.WithFilter(func(r *http.Request) bool { otelhttp.WithFilter(func(r *http.Request) bool {
switch r.URL.Path { switch r.URL.Path {
case "/health": case "/health":
@@ -89,6 +84,18 @@ func prepHTTPServer(opts *opts.AppHTTP) *http.Server {
default: default:
return true return true
} }
}),
otelhttp.WithSpanNameFormatter(func(operation string, r *http.Request) string {
endpoint := r.URL.Path
if _, pattern := mux.Handler(r); pattern != "" {
endpoint = pattern
}
if httpPatternWithMethodRegexp.MatchString(endpoint) {
return endpoint
}
return fmt.Sprintf("%s %s", r.Method, endpoint)
})) }))
// Set timeouts from defaults, override // Set timeouts from defaults, override