diff --git a/logger/logger.go b/logger/logger.go index 133fe29..abe67cb 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -12,6 +12,7 @@ import ( type Zaplog struct { *zap.Logger + *redactor } var ( @@ -20,6 +21,25 @@ var ( appEnv AppEnv ) +// initLogger initialise Logger instance only once +func initLogger() { + once.Do(func() { + r := NewRedactor() + switch appEnv { + case Local: + cfg := zap.NewDevelopmentConfig() + cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder + cfg.EncoderConfig.TimeKey = "" + cfg.EncoderConfig.EncodeCaller = zapcore.ShortCallerEncoder + log, _ := cfg.Build() + instance = &Zaplog{log, r} + default: + log, _ := zap.NewProduction() + instance = &Zaplog{log, r} + } + }) +} + // SetLoggerMode set Logger level from given string func SetLoggerMode(envStr string) { appEnv = EnvFromStr(envStr) @@ -32,7 +52,7 @@ func Log() *Zaplog { } //LogWithContext is invoking Zap Logger function with context -func LogWithContext(ctx context.Context) *zap.Logger { +func LogWithContext(ctx context.Context) *Zaplog { initLogger() publicKey := helper.GetPublicKey(ctx) @@ -46,20 +66,61 @@ func LogWithContext(ctx context.Context) *zap.Logger { ) } -// initLogger initialise Logger instance only once -func initLogger() { - once.Do(func() { - switch appEnv { - case Local: - cfg := zap.NewDevelopmentConfig() - cfg.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder - cfg.EncoderConfig.TimeKey = "" - cfg.EncoderConfig.EncodeCaller = zapcore.ShortCallerEncoder - log, _ := cfg.Build() - instance = &Zaplog{log} - default: - log, _ := zap.NewProduction() - instance = &Zaplog{log} - } - }) +func (z *Zaplog) With(fields ...zapcore.Field) *Zaplog { + return &Zaplog{z.Logger.With(fields...), z.redactor} +} + +func (z *Zaplog) InfoRedact(s string) *Zaplog { + z.Info(z.Redact(s)) + return z +} + +func (z *Zaplog) DebugRedact(s string) *Zaplog { + z.Debug(z.Redact(s)) + return z +} + +func (z *Zaplog) WarnRedact(s string) *Zaplog { + z.Warn(z.Redact(s)) + return z +} + +func (z *Zaplog) ErrorRedact(s string) *Zaplog { + z.Error(z.Redact(s)) + return z +} + +func (z *Zaplog) PanicRedact(s string) *Zaplog { + z.Panic(z.Redact(s)) + return z +} + +func (z *Zaplog) FatalRedact(s string) *Zaplog { + z.Fatal(z.Redact(s)) + return z +} + +func (z *Zaplog) InfoErr(e error) *Zaplog { + z.Logger.Info(e.Error()) + return z +} + +func (z *Zaplog) DebugErr(e error) *Zaplog { + z.Logger.Debug(e.Error()) + return z +} + +func (z *Zaplog) WarnErr(e error) *Zaplog { + z.Logger.Warn(e.Error()) + return z +} + +func (z *Zaplog) ErrorErr(e error) *Zaplog { + z.Logger.Error(e.Error()) + return z +} + +func (z *Zaplog) PanicErr(e error) *Zaplog { + z.Logger.Panic(e.Error()) + return z } diff --git a/logger/redact.go b/logger/redact.go new file mode 100644 index 0000000..e80e9db --- /dev/null +++ b/logger/redact.go @@ -0,0 +1,22 @@ +package logger + +import "regexp" + +const ipAddrRegex = `\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b` + +type redactor struct { + ipAddrRegex *regexp.Regexp +} + +func NewRedactor() *redactor { + return &redactor{regexp.MustCompile(ipAddrRegex)} +} + +func (r *redactor) Redact(message string) string { + + if r.ipAddrRegex.MatchString(message) { + return r.ipAddrRegex.ReplaceAllString(message, "xxx.xxx.xxx.xxx") + } + + return message +} diff --git a/logger/redactor_test.go b/logger/redactor_test.go new file mode 100644 index 0000000..a80c582 --- /dev/null +++ b/logger/redactor_test.go @@ -0,0 +1,22 @@ +package logger + +import ( + "testing" +) + +func Test_Redactor_RemovesIPAddresses(t *testing.T) { + r := NewRedactor() + + m := map[string]string{ + "this contains a valid ip: 172.217.22.14": "this contains a valid ip: xxx.xxx.xxx.xxx", + "192.168.1.1 this started with a valid ip": "xxx.xxx.xxx.xxx this started with a valid ip", + "this contains a non-ip 1234.12.15.2": "this contains a non-ip 1234.12.15.2", + "this has ip with port, 192.168.1.1:80": "this has ip with port, xxx.xxx.xxx.xxx:80", + } + + for msg, res := range m { + if r.Redact(msg) != res { + t.Errorf("Expected %s, got %s", res, r.Redact(msg)) + } + } +}