From bf241e2a5d9f582f6aad32a8f8a55f7b7356c00a Mon Sep 17 00:00:00 2001 From: HugoW5 Date: Thu, 23 Oct 2025 14:19:52 +0200 Subject: [PATCH 1/2] Add terminal logging support to httpLogFilter --- pkg/gofr/logging/logger.go | 4 ++ .../remotelogger/dynamic_level_logger.go | 37 +++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/pkg/gofr/logging/logger.go b/pkg/gofr/logging/logger.go index 76ed18595..8ccbae6cc 100644 --- a/pkg/gofr/logging/logger.go +++ b/pkg/gofr/logging/logger.go @@ -245,6 +245,10 @@ func checkIfTerminal(w io.Writer) bool { } } +func (l *logger) IsTerminal() bool { + return l.isTerminal +} + // ChangeLevel changes the log level of the logger. // This allows dynamic adjustment of the logging verbosity. func (l *logger) ChangeLevel(level Level) { diff --git a/pkg/gofr/logging/remotelogger/dynamic_level_logger.go b/pkg/gofr/logging/remotelogger/dynamic_level_logger.go index eaef2d3c2..43aa19d14 100644 --- a/pkg/gofr/logging/remotelogger/dynamic_level_logger.go +++ b/pkg/gofr/logging/remotelogger/dynamic_level_logger.go @@ -29,6 +29,18 @@ type httpLogFilter struct { initLogged bool } +func (f *httpLogFilter) isTerminalLogger() bool { + type terminalChecker interface { + IsTerminal() bool + } + + if l, ok := f.Logger.(terminalChecker); ok { + return l.IsTerminal() + } + + return false +} + // Log implements a simplified filtering strategy with consistent formatting. func (f *httpLogFilter) Log(args ...any) { if len(args) == 0 || args[0] == nil { @@ -78,14 +90,23 @@ func (f *httpLogFilter) handleHTTPLog(httpLog *service.Log, args []any) { // Subsequent successful hits - log at DEBUG level with consistent format case isSuccessful: if debugLogger, ok := f.Logger.(interface{ Debugf(string, ...any) }); ok { - colorCode := colorForResponseCode(httpLog.ResponseCode) - debugLogger.Debugf("\u001B[38;5;8m%s \u001B[38;5;%dm%-6d\u001B[0m %8d\u001B[38;5;8mµs\u001B[0m %s %s", - httpLog.CorrelationID, - colorCode, - httpLog.ResponseCode, - httpLog.ResponseTime, - httpLog.HTTPMethod, - httpLog.URI) + if f.isTerminalLogger() { + colorCode := colorForResponseCode(httpLog.ResponseCode) + debugLogger.Debugf("\u001B[38;5;8m%s \u001B[38;5;%dm%-6d\u001B[0m %8dμs\u001B[0m %s %s", + httpLog.CorrelationID, + colorCode, + httpLog.ResponseCode, + httpLog.ResponseTime, + httpLog.HTTPMethod, + httpLog.URI) + } else { + debugLogger.Debugf("%s %d %dμs %s %s", + httpLog.CorrelationID, + httpLog.ResponseCode, + httpLog.ResponseTime, + httpLog.HTTPMethod, + httpLog.URI) + } } // Error responses - pass through to original logger From 502212219b3ce108e87d4183c46b47007cc2643a Mon Sep 17 00:00:00 2001 From: HugoW5 Date: Thu, 23 Oct 2025 14:21:55 +0200 Subject: [PATCH 2/2] Added descriptive comments for the new functions --- pkg/gofr/logging/logger.go | 2 ++ pkg/gofr/logging/remotelogger/dynamic_level_logger.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pkg/gofr/logging/logger.go b/pkg/gofr/logging/logger.go index 8ccbae6cc..291508617 100644 --- a/pkg/gofr/logging/logger.go +++ b/pkg/gofr/logging/logger.go @@ -245,6 +245,8 @@ func checkIfTerminal(w io.Writer) bool { } } +// IsTerminal returns true if the logger's output is a terminal (TTY). +// This helps decide whether to include ANSI color codes for pretty printing. func (l *logger) IsTerminal() bool { return l.isTerminal } diff --git a/pkg/gofr/logging/remotelogger/dynamic_level_logger.go b/pkg/gofr/logging/remotelogger/dynamic_level_logger.go index 43aa19d14..dd3c7a712 100644 --- a/pkg/gofr/logging/remotelogger/dynamic_level_logger.go +++ b/pkg/gofr/logging/remotelogger/dynamic_level_logger.go @@ -29,6 +29,8 @@ type httpLogFilter struct { initLogged bool } +// isTerminalLogger checks if the underlying logger supports terminal output (TTY). +// Returns true if colors and pretty-printing can be applied safely. func (f *httpLogFilter) isTerminalLogger() bool { type terminalChecker interface { IsTerminal() bool