Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add use_local_time_encoder and show_caller config #59

Draft
wants to merge 20 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 55 additions & 10 deletions config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package logger

import (
"fmt"
"os"
"strings"
"time"
Expand Down Expand Up @@ -95,15 +96,31 @@

// File logger options
FileLogger *FileLoggerConfig `mapstructure:"file_logger_options"`

// UseLocalTime is used to set the encoder to use local time instead of UTC.
UseLocalTime bool `mapstructure:"use_local_time"`

// ShowCaller is used to set the encoder to show the caller.
ShowCaller bool `mapstructure:"show_caller"`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When developing custom plugins, it was difficult to find the corresponding location in the log, so caller was added
In the production environment, the log time format is not readable enough, so the local time display function is added

I'm not sure if I understand this. The caller is the line where your log is. How is that difficult to find where you send this log?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When developing custom plugins, although logs show what happened, pinpointing the exact source of a log entry in complex plugin code can be challenging without caller information. By enabling show_caller, we can immediately see which file and line generated the log, significantly improving debugging efficiency.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How can it be complex? It is just ctrl+f (or / for vim) -> enter log message -> here you are.

rustatian marked this conversation as resolved.
Show resolved Hide resolved
}

// BuildLogger converts config into Zap configuration.
func (cfg *Config) BuildLogger() (*zap.Logger, error) {
var zCfg zap.Config
var callerKey = zapcore.OmitKey
var encodeCaller zapcore.CallerEncoder = nil

Check failure on line 111 in config.go

View workflow job for this annotation

GitHub Actions / Golang-CI (lint)

var-declaration: should drop = nil from declaration of var encodeCaller; it is the zero value (revive)
if cfg.ShowCaller {
callerKey = "caller"
encodeCaller = ColoredShortCallerEncoder
}
switch Mode(strings.ToLower(string(cfg.Mode))) {
case off, none:
return zap.NewNop(), nil
case production:
encodeTime := utcEpochTimeEncoder
if cfg.UseLocalTime {
encodeTime = localTimeEncoder
}
zCfg = zap.Config{
Level: zap.NewAtomicLevelAt(zap.InfoLevel),
Development: false,
Expand All @@ -112,20 +129,24 @@
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: zapcore.OmitKey,
CallerKey: callerKey,
FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: zapcore.OmitKey,
LineEnding: cfg.LineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: utcEpochTimeEncoder,
EncodeTime: encodeTime,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeCaller: encodeCaller,
},
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}
case development:
encodeTime := utcISO8601TimeEncoder
if cfg.UseLocalTime {
encodeTime = localTimeEncoder
}
zCfg = zap.Config{
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
Development: true,
Expand All @@ -134,16 +155,16 @@
TimeKey: "ts",
LevelKey: "level",
NameKey: "logger",
CallerKey: zapcore.OmitKey,
CallerKey: callerKey,
FunctionKey: zapcore.OmitKey,
MessageKey: "msg",
StacktraceKey: zapcore.OmitKey,
LineEnding: cfg.LineEnding,
EncodeLevel: ColoredLevelEncoder,
EncodeName: ColoredNameEncoder,
EncodeTime: utcISO8601TimeEncoder,
EncodeTime: encodeTime,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeCaller: encodeCaller,
},
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
Expand All @@ -160,23 +181,27 @@
ErrorOutputPaths: []string{"stderr"},
}
default:
encodeTime := utcISO8601TimeEncoder
if cfg.UseLocalTime {
encodeTime = localTimeEncoder
}
zCfg = zap.Config{
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
Encoding: "console",
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "T",
LevelKey: "L",
NameKey: "N",
CallerKey: zapcore.OmitKey,
CallerKey: callerKey,
FunctionKey: zapcore.OmitKey,
MessageKey: "M",
StacktraceKey: zapcore.OmitKey,
LineEnding: cfg.LineEnding,
EncodeLevel: ColoredLevelEncoder,
EncodeName: ColoredNameEncoder,
EncodeTime: utcISO8601TimeEncoder,
EncodeTime: encodeTime,
EncodeDuration: zapcore.StringDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
EncodeCaller: encodeCaller,
},
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
Expand Down Expand Up @@ -206,6 +231,11 @@
// init it
// otherwise - return standard config
if cfg.FileLogger != nil {
fileEncoderConfig := zCfg.EncoderConfig
if cfg.ShowCaller {
fileEncoderConfig.EncodeCaller = ShortCallerEncoderWithPadding
}

// init absent options
cfg.FileLogger.InitDefaults()

Expand All @@ -220,10 +250,13 @@
)

core := zapcore.NewCore(
zapcore.NewJSONEncoder(zCfg.EncoderConfig),
zapcore.NewJSONEncoder(fileEncoderConfig),
w,
zCfg.Level,
)
if cfg.ShowCaller {
return zap.New(core, zap.AddCaller()), nil
}
return zap.New(core), nil
}

Expand Down Expand Up @@ -251,3 +284,15 @@
func utcEpochTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendInt64(t.UTC().UnixNano())
}

func localTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(t.Local().Format("2006-01-02 15:04:05.000 "))
}

func ColoredShortCallerEncoder(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(fmt.Sprintf("\x1b[35m%-30s\x1b[0m", caller.TrimmedPath()))
}

func ShortCallerEncoderWithPadding(caller zapcore.EntryCaller, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(fmt.Sprintf("%-30s", caller.TrimmedPath()))
}
16 changes: 16 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,8 @@ github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQs
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
Expand All @@ -169,6 +171,7 @@ github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1 h1:I2qBYMChEhIjOgazfJmV3/mZM256btk6wkCDRmW7JYs=
Expand All @@ -184,6 +187,7 @@ github.com/sagikazarmark/crypt v0.19.0 h1:WMyLTjHBo64UvNcWqpzY3pbZTYgnemZU8FBZig
github.com/sagikazarmark/crypt v0.19.0/go.mod h1:c6vimRziqqERhtSe0MhIvzE1w54FrCHtrXb5NH/ja78=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
Expand Down Expand Up @@ -216,6 +220,8 @@ go.temporal.io/api v1.30.1 h1:73UCTi+8l+Qy3GdDypW2FB5rj995A3Pi0mXkSu/qedw=
go.temporal.io/api v1.30.1/go.mod h1:xI9UdP3s07881dgWzG8idIBAnZq3/aop+O682EIDoT0=
go.temporal.io/api v1.35.0 h1:+1o2zyBncLjnpjJt4FedKZMtuUav/LUgTB+mhQxx0zs=
go.temporal.io/api v1.35.0/go.mod h1:OYkuupuCw6s/5TkcKHMb9EcIrOI+vTsbf/CGaprbzb0=
go.temporal.io/api v1.36.0 h1:WdntOw9m38lFvMdMXuOO+3BQ0R8HpVLgtk9+f+FwiDk=
go.temporal.io/api v1.36.0/go.mod h1:0nWIrFRVPlcrkopXqxir/UWOtz/NZCo+EE9IX4UwVxw=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
Expand All @@ -232,6 +238,8 @@ golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk=
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0=
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
Expand All @@ -241,6 +249,8 @@ golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8=
golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww=
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
golang.org/x/time v0.1.0 h1:xYY+Bajn2a7VBmTM5GikTmnK8ZuX8YgnQCqZpbBNtmA=
golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
Expand Down Expand Up @@ -270,6 +280,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac=
google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d h1:Aqf0fiIdUQEj0Gn9mKFFXoQfTTEaNopWpfVyYADxiSg=
google.golang.org/genproto/googleapis/api v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Od4k8V1LQSizPRUK4OzZ7TBE/20k+jPczUDAEyvn69Y=
google.golang.org/genproto/googleapis/api v0.0.0-20240722135656-d784300faade h1:WxZOF2yayUHpHSbUE6NMzumUzBxYc3YGwo0YHnbzsJY=
google.golang.org/genproto/googleapis/api v0.0.0-20240722135656-d784300faade/go.mod h1:mw8MG/Qz5wfgYr6VqVCiZcHe/GJEfI+oGGDCohaVgB0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0=
Expand All @@ -278,6 +290,8 @@ google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d h1:k3zyW3BYYR30e8v3x0bTDdE9vpYFjZHK+HcyqkrppWk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o=
google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I=
Expand All @@ -286,6 +300,8 @@ google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ=
gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
Expand Down
2 changes: 2 additions & 0 deletions tests/configs/.rr-file-logger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ http:
logs:
mode: development
level: debug
use_local_time: true
show_caller: true
Comment on lines +24 to +25
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Documentation needed for new logging configuration options

The new configuration options use_local_time and show_caller are present in the test configuration but are not documented in the schema. These options should be added to the schema definition under the FileLoggerOptions section to maintain consistency and provide proper documentation for users.

  • Add documentation for use_local_time in the schema
  • Add documentation for show_caller in the schema
🔗 Analysis chain

LGTM! Well-structured configuration.

The new logging options are correctly placed under the logs section and follow the existing configuration structure. The boolean values are appropriate for these feature flags.

Let's verify the configuration schema documentation:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check if these new options are documented in the schema or docs
# Expected: Find references to these new config options in documentation

# Look for schema definitions or documentation
rg -g '*.{md,json,yaml}' -i "use.*local.*time|show.*caller" 

Length of output: 174


Script:

#!/bin/bash
# Let's check for any documentation or schema files that might define logger configuration
fd -e md -e yaml -e json . | grep -i "schema\|config\|logger" | xargs cat 2>/dev/null | grep -i "logger\|log"

Length of output: 2239

file_logger_options:
log_output: "test.log"
11 changes: 11 additions & 0 deletions tests/logger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"os"
"os/signal"
"regexp"
"strings"
"sync"
"syscall"
Expand Down Expand Up @@ -337,6 +338,16 @@ func TestFileLogger(t *testing.T) {
strings.Contains(string(f), "worker constructed")
strings.Contains(string(f), "201 GET")

// when use_local_time=true, check local time format
matched, err := regexp.MatchString(`\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3}`, string(f))
assert.NoError(t, err)
assert.True(t, matched)

// when show_caller=true, check caller info
callerMatched, err := regexp.MatchString(`\w+\.go:\d+`, string(f))
assert.NoError(t, err)
assert.True(t, callerMatched)

_ = os.Remove("test.log")

stopCh <- struct{}{}
Expand Down
Loading