Skip to content

Commit 25d40b5

Browse files
chore: replace zerolog with zap (#120)
1 parent 2855b16 commit 25d40b5

File tree

16 files changed

+259
-384
lines changed

16 files changed

+259
-384
lines changed

cmd/root.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package cmd
33
import (
44
"os"
55

6-
"github.com/rs/zerolog"
76
"github.com/spf13/cobra"
87
"github.com/spf13/viper"
8+
"go.uber.org/zap"
99

1010
"github.com/smartcontractkit/timelock-worker/pkg/logger"
1111
)
@@ -15,9 +15,9 @@ var (
1515
Use: "timelock-worker",
1616
Short: "Pull and execute scheduled transactions from Timelock contract",
1717
}
18-
19-
logs *zerolog.Logger
20-
logLevel, output string
18+
logs *zap.Logger
19+
logLevel string
20+
output string
2121
)
2222

2323
func Execute() {
@@ -53,7 +53,11 @@ func configureRootCmd() error {
5353
}
5454

5555
func initConfig() {
56-
// Output hardcoded to JSON
57-
logs = logger.Logger(viper.GetString("log-level"), viper.GetString("output"))
58-
logs.Debug().Msgf("initialized Logger")
56+
var err error
57+
logs, err = logger.NewLogger(viper.GetString("log-level"), viper.GetString("output"))
58+
if err != nil {
59+
panic("unable to create logger")
60+
}
61+
62+
logs.Debug("initialized Logger")
5963
}

cmd/start.go

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func startCommand() *cobra.Command {
2727
// Precedence: flags > env variables > timelock.env file.
2828
timelockConf, err := cli.NewTimelockCLI()
2929
if err != nil {
30-
logs.Fatal().Msgf("error initializing configuration: %s", err.Error())
30+
logs.Sugar().Fatalf("error initializing configuration: %s", err.Error())
3131
}
3232
// Set liveStatus to OK on startup.
3333
// Set readyStatus to Error on startup.
@@ -54,63 +54,65 @@ func startHandler(cmd *cobra.Command, _ []string) {
5454
}
5555

5656
func startTimelock(cmd *cobra.Command) {
57+
slog := logs.Sugar()
58+
5759
nodeURL, err := cmd.Flags().GetString("node-url")
5860
if err != nil {
59-
logs.Fatal().Msgf("value of node-url not set: %s", err.Error())
61+
slog.Fatalf("value of node-url not set: %s", err.Error())
6062
}
6163

6264
timelockAddress, err := cmd.Flags().GetString("timelock-address")
6365
if err != nil {
64-
logs.Fatal().Msgf("value of timelock-address not set: %s", err.Error())
66+
slog.Fatalf("value of timelock-address not set: %s", err.Error())
6567
}
6668

6769
callProxyAddress, err := cmd.Flags().GetString("call-proxy-address")
6870
if err != nil {
69-
logs.Fatal().Msgf("value of call-proxy-address not set: %s", err.Error())
71+
slog.Fatalf("value of call-proxy-address not set: %s", err.Error())
7072
}
7173

7274
privateKey, err := cmd.Flags().GetString("private-key")
7375
if err != nil {
74-
logs.Fatal().Msgf("value of private-key not set: %s", err.Error())
76+
slog.Fatalf("value of private-key not set: %s", err.Error())
7577
}
7678

7779
fromBlock, err := cmd.Flags().GetInt64("from-block")
7880
if err != nil {
79-
logs.Fatal().Msgf("value of from-block not set: %s", err.Error())
81+
slog.Fatalf("value of from-block not set: %s", err.Error())
8082
}
8183

8284
pollPeriod, err := cmd.Flags().GetInt64("poll-period")
8385
if err != nil {
84-
logs.Fatal().Msgf("value of poll-period not set: %s", err.Error())
86+
slog.Fatalf("value of poll-period not set: %s", err.Error())
8587
}
8688

8789
eventListenerPollPeriod, err := cmd.Flags().GetInt64("event-listener-poll-period")
8890
if err != nil {
89-
logs.Fatal().Msgf("value of poll-period not set: %s", err.Error())
91+
slog.Fatalf("value of poll-period not set: %s", err.Error())
9092
}
9193

9294
dryRun, err := cmd.Flags().GetBool("dry-run")
9395
if err != nil {
94-
logs.Fatal().Msgf("value of dry-run not set: %s", err.Error())
96+
slog.Fatalf("value of dry-run not set: %s", err.Error())
9597
}
9698

9799
tWorker, err := timelock.NewTimelockWorker(nodeURL, timelockAddress, callProxyAddress, privateKey,
98-
big.NewInt(fromBlock), pollPeriod, eventListenerPollPeriod, dryRun, logs)
100+
big.NewInt(fromBlock), pollPeriod, eventListenerPollPeriod, dryRun, slog)
99101
if err != nil {
100-
logs.Fatal().Msgf("error creating the timelock-worker: %s", err.Error())
102+
slog.Fatalf("error creating the timelock-worker: %s", err.Error())
101103
}
102104

103105
if err := tWorker.Listen(context.Background()); err != nil {
104-
logs.Fatal().Msgf("error while starting timelock-worker: %s", err.Error())
106+
slog.Fatalf("error while starting timelock-worker: %s", err.Error())
105107
}
106108

107-
logs.Info().Msg("shutting down timelock-worker")
109+
slog.Infof("shutting down timelock-worker")
108110
}
109111

110112
func startHTTPHealthServer() {
111-
timelock.StartHTTPHealthServer(logs)
113+
timelock.StartHTTPHealthServer(logs.Sugar())
112114
}
113115

114116
func startMetricsServer() {
115-
timelock.StartMetricsServer(logs)
117+
timelock.StartMetricsServer(logs.Sugar())
116118
}

cmd/version.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ func versionCommand() *cobra.Command {
2222
}
2323

2424
func versionHandler(_ *cobra.Command, _ []string) {
25-
logs.Info().Msgf("%s Version: %s Commit: %s", os.Args[0], Version, Commit)
25+
logs.Sugar().Infof("%s Version: %s Commit: %s", os.Args[0], Version, Commit)
2626
}

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ require (
77
github.com/ethereum/go-ethereum v1.13.15
88
github.com/google/go-cmp v0.6.0
99
github.com/prometheus/client_golang v1.19.1
10-
github.com/rs/zerolog v1.33.0
1110
github.com/samber/lo v1.47.0
1211
github.com/smartcontractkit/ccip-owner-contracts v0.0.0-20240917103524-56f1a8d2cd4b
1312
github.com/smartcontractkit/chain-selectors v1.0.17
1413
github.com/spf13/cobra v1.8.1
1514
github.com/spf13/viper v1.19.0
1615
github.com/stretchr/testify v1.9.0
1716
github.com/testcontainers/testcontainers-go v0.34.0
17+
go.uber.org/zap v1.27.0
1818
)
1919

2020
require (
@@ -129,8 +129,7 @@ require (
129129
go.opentelemetry.io/otel v1.24.0 // indirect
130130
go.opentelemetry.io/otel/metric v1.24.0 // indirect
131131
go.opentelemetry.io/otel/trace v1.24.0 // indirect
132-
go.uber.org/atomic v1.11.0 // indirect
133-
go.uber.org/multierr v1.9.0 // indirect
132+
go.uber.org/multierr v1.11.0 // indirect
134133
golang.org/x/crypto v0.26.0 // indirect
135134
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
136135
golang.org/x/net v0.28.0 // indirect

go.sum

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7np
7575
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
7676
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
7777
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
78-
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
7978
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
8079
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
8180
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
@@ -157,7 +156,6 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78
157156
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
158157
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
159158
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
160-
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
161159
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
162160
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
163161
github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
@@ -273,7 +271,6 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd
273271
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
274272
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
275273
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
276-
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
277274
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
278275
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
279276
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -365,9 +362,6 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
365362
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
366363
github.com/rs/cors v1.8.3 h1:O+qNyWn7Z+F9M0ILBHgMVPuB1xTOucVd5gtaYyXBpRo=
367364
github.com/rs/cors v1.8.3/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
368-
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
369-
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
370-
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
371365
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
372366
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
373367
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -487,10 +481,12 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
487481
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
488482
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
489483
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
490-
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
491-
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
492-
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
493-
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
484+
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
485+
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
486+
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
487+
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
488+
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
489+
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
494490
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
495491
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
496492
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -568,7 +564,6 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
568564
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
569565
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
570566
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
571-
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
572567
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
573568
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
574569
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

pkg/logger/logger.go

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,33 @@
11
package logger
22

33
import (
4-
"os"
5-
"sync"
6-
"time"
4+
"fmt"
75

8-
"github.com/rs/zerolog"
6+
"go.uber.org/zap"
97
)
108

11-
var (
12-
once sync.Once //nolint:gochecknoglobals
13-
logger *zerolog.Logger //nolint:gochecknoglobals
14-
)
15-
16-
// humanConsoleWriter configures the human-readable output.
17-
var humanConsoleWriter = zerolog.ConsoleWriter{ //nolint:gochecknoglobals
18-
Out: os.Stdout,
19-
TimeFormat: time.RFC3339,
20-
}
9+
// NewLogger initializes the Logger with the given arguments.
10+
func NewLogger(logLevel string, output string) (*zap.Logger, error) {
11+
var err error
12+
var loggerConfig zap.Config
2113

22-
// Logger returns an instance of Logger.
23-
func Logger(logLevel string, output string) *zerolog.Logger {
24-
if logger == nil {
25-
once.Do(
26-
func() {
27-
logger = newLogger(logLevel, output)
28-
})
14+
switch output {
15+
case "json":
16+
loggerConfig = zap.NewProductionConfig()
17+
case "human":
18+
loggerConfig = zap.NewDevelopmentConfig()
19+
default:
20+
return nil, fmt.Errorf("invalid logger output: %q", output)
2921
}
3022

31-
return logger
32-
}
33-
34-
// newLogger initializes the Logger with the given arguments.
35-
func newLogger(logLevel string, output string) *zerolog.Logger {
36-
level, err := zerolog.ParseLevel(logLevel)
23+
loggerConfig.Level, err = zap.ParseAtomicLevel(logLevel)
3724
if err != nil {
38-
// Do not crash on wrong user input, default to InfoLevel.
39-
level = zerolog.InfoLevel
25+
return nil, err
4026
}
4127

42-
var l zerolog.Logger
43-
switch output {
44-
case "human":
45-
l = zerolog.New(humanConsoleWriter).Level(level).With().Timestamp().Logger()
46-
case "json":
47-
l = zerolog.New(os.Stdout).Level(level).With().Timestamp().Logger()
48-
default:
49-
l = zerolog.New(humanConsoleWriter).Level(level).With().Timestamp().Logger()
50-
}
28+
// use stdout, not stderr to maintain compatibility with zerolog
29+
loggerConfig.OutputPaths = []string{"stdout"}
30+
loggerConfig.ErrorOutputPaths = []string{"stdout"}
5131

52-
return &l
32+
return loggerConfig.Build()
5333
}

pkg/logger/logger_test.go

Lines changed: 48 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,59 @@
11
package logger_test
22

33
import (
4-
"reflect"
54
"testing"
65

7-
"github.com/rs/zerolog"
6+
"github.com/stretchr/testify/require"
7+
"go.uber.org/zap"
8+
89
"github.com/smartcontractkit/timelock-worker/pkg/logger"
9-
"github.com/stretchr/testify/assert"
1010
)
1111

12-
func TestLogger(t *testing.T) {
13-
testLogger := logger.Logger("info", "human")
14-
assert.NotNil(t, testLogger)
15-
16-
testType := reflect.TypeOf(testLogger)
17-
loggerType := reflect.TypeOf((*zerolog.Logger)(nil))
18-
19-
if !(loggerType == testType) {
20-
t.Errorf("testType does not implement loggerType")
12+
func Test_NewLogger(t *testing.T) {
13+
t.Parallel()
14+
15+
tests := []struct {
16+
name string
17+
level string
18+
output string
19+
wantErr string
20+
}{
21+
{
22+
name: "success: info human",
23+
level: "info",
24+
output: "human",
25+
},
26+
{
27+
name: "success: debug json",
28+
level: "info",
29+
output: "json",
30+
},
31+
{
32+
name: "invalid log level",
33+
level: "invalid",
34+
output: "human",
35+
wantErr: "unrecognized level: \"invalid\"",
36+
},
37+
{
38+
name: "invalid output",
39+
level: "info",
40+
output: "invalid",
41+
wantErr: "invalid logger output: \"invalid\"",
42+
},
2143
}
22-
}
23-
24-
func TestLoggerJSON(t *testing.T) {
25-
testLogger := logger.Logger("debug", "json")
26-
assert.NotNil(t, testLogger)
27-
28-
testType := reflect.TypeOf(testLogger)
29-
loggerType := reflect.TypeOf((*zerolog.Logger)(nil))
30-
31-
if !(loggerType == testType) {
32-
t.Errorf("testType does not implement loggerType")
33-
}
34-
}
35-
36-
func TestLoggerWrongLogLevel(t *testing.T) {
37-
testLogger := logger.Logger("wrongLogLevel", "human")
38-
assert.NotNil(t, testLogger)
39-
40-
testType := reflect.TypeOf(testLogger)
41-
loggerType := reflect.TypeOf((*zerolog.Logger)(nil))
42-
43-
if !(loggerType == testType) {
44-
t.Errorf("testType does not implement loggerType")
45-
}
46-
}
47-
48-
func TestLoggerWrongAll(t *testing.T) {
49-
testLogger := logger.Logger("wrongLogLevel", "wrongOutput")
50-
assert.NotNil(t, testLogger)
51-
52-
testType := reflect.TypeOf(testLogger)
53-
loggerType := reflect.TypeOf((*zerolog.Logger)(nil))
54-
55-
if !(loggerType == testType) {
56-
t.Errorf("testType does not implement loggerType")
44+
for _, tt := range tests {
45+
tt := tt
46+
t.Run(tt.name, func(t *testing.T) {
47+
t.Parallel()
48+
49+
logger, err := logger.NewLogger(tt.level, tt.output)
50+
51+
if tt.wantErr == "" {
52+
require.NoError(t, err)
53+
require.IsType(t, logger, new(zap.Logger))
54+
} else {
55+
require.ErrorContains(t, err, tt.wantErr)
56+
}
57+
})
5758
}
5859
}

0 commit comments

Comments
 (0)