From 049aeff8a86726ddf5c7f390300c55cec88cd704 Mon Sep 17 00:00:00 2001 From: Renuka Fernando Date: Thu, 20 Aug 2026 14:46:29 +0530 Subject: [PATCH] feat(platform-api): include user-agent in access logs Replace gin.Default() with gin.New() plus explicit logger and recovery middleware so the access log can be customized. Add a custom formatter that mirrors gin's default format and appends the request User-Agent for client identification. Signed-off-by: Renuka Fernando --- platform-api/src/internal/server/server.go | 27 ++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/platform-api/src/internal/server/server.go b/platform-api/src/internal/server/server.go index 700d6e96c6..60df4f5d88 100644 --- a/platform-api/src/internal/server/server.go +++ b/platform-api/src/internal/server/server.go @@ -328,8 +328,11 @@ func StartPlatformAPIServer(cfg *config.Server, slogger *slog.Logger) (*Server, gin.SetMode(gin.ReleaseMode) } - // Setup router - router := gin.Default() + // Setup router. Use gin.New() with explicit middleware (instead of gin.Default()) + // so the access log can include the request User-Agent. + router := gin.New() + router.Use(gin.LoggerWithFormatter(accessLogFormatter)) + router.Use(gin.Recovery()) // Configure and apply CORS middleware first (before auth middleware) corsConfig := cors.DefaultConfig() @@ -445,6 +448,26 @@ func StartPlatformAPIServer(cfg *config.Server, slogger *slog.Logger) (*Server, }, nil } +// accessLogFormatter mirrors gin's default access-log format (without color) +// and appends the request's User-Agent so the client is identified in the logs. +func accessLogFormatter(param gin.LogFormatterParams) string { + latency := param.Latency + if latency > time.Minute { + latency = latency.Truncate(time.Second) + } + + return fmt.Sprintf("[GIN] %v | %3d | %13v | %15s | %-7s %#v | %q\n%s", + param.TimeStamp.Format("2006/01/02 - 15:04:05"), + param.StatusCode, + latency, + param.ClientIP, + param.Method, + param.Path, + param.Request.UserAgent(), + param.ErrorMessage, + ) +} + // demoMode reports whether APIP_DEMO_MODE is enabled. // Defaults to true when the variable is unset. func demoMode() bool {