Skip to content

Commit 7eb16e6

Browse files
ldmonsterPavel Okhlopkov
and
Pavel Okhlopkov
authored
[shell-operator] Replace Logrus with slog (#671)
Signed-off-by: Pavel Okhlopkov <[email protected]> Co-authored-by: Pavel Okhlopkov <[email protected]>
1 parent 6f640b4 commit 7eb16e6

File tree

88 files changed

+1235
-1035
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+1235
-1035
lines changed

.github/workflows/lint.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ jobs:
3636
3737
- name: Run golangci-lint
3838
run: |
39-
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v1.59.1
39+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v1.60.1
4040
./golangci-lint run --sort-results --build-tags integration,test
4141
4242

.golangci.yaml

+30-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
run:
22
timeout: 15m
3-
skip-dirs:
4-
- test/integration
53
linters:
64
disable-all: true
75
enable:
@@ -24,6 +22,7 @@ linters:
2422
- nolintlint
2523
- prealloc
2624
- revive
25+
- sloglint
2726
- staticcheck
2827
- stylecheck
2928
- unconvert
@@ -39,6 +38,33 @@ linters-settings:
3938
local-prefixes: github.com/flant/
4039
nolintlint:
4140
allow-unused: true
41+
sloglint:
42+
# Enforce not mixing key-value pairs and attributes.
43+
no-mixed-args: true
44+
# Enforce using key-value pairs only (overrides no-mixed-args, incompatible with attr-only).
45+
kv-only: false
46+
# Enforce using attributes only (overrides no-mixed-args, incompatible with kv-only).
47+
attr-only: false
48+
# Enforce not using global loggers.
49+
no-global: ""
50+
# Enforce using methods that accept a context.
51+
context: ""
52+
# Enforce using static values for log messages.
53+
static-msg: false
54+
# Enforce using constants instead of raw keys.
55+
no-raw-keys: false
56+
# Enforce a single key naming convention.
57+
key-naming-case: ""
58+
# Enforce not using specific keys.
59+
forbidden-keys:
60+
- level
61+
- msg
62+
- logger
63+
- source
64+
- stacktrace
65+
- time
66+
# Enforce putting arguments on separate lines.
67+
args-on-sep-lines: false
4268
depguard:
4369
rules:
4470
Main:
@@ -48,6 +74,8 @@ linters-settings:
4874
- pkg: "gopkg.in/satori/go.uuid.v1"
4975
desc: "Use https://github.com/gofrs/uuid instead. Satori/go.uuid is no longer maintained and has critical vulnerabilities."
5076
issues:
77+
exclude-dirs:
78+
- test/integration
5179
exclude:
5280
# Using underscores is a common practice, refactor in the future
5381
- "var-naming: don't use an underscore in package name" # revive

cmd/shell-operator/main.go

+10-11
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ package main
22

33
import (
44
"fmt"
5-
"math/rand"
65
"os"
7-
"time"
86

7+
"github.com/deckhouse/deckhouse/pkg/log"
98
"gopkg.in/alecthomas/kingpin.v2"
109

11-
"github.com/flant/kube-client/klogtologrus"
10+
"github.com/flant/kube-client/klogtolog"
1211
"github.com/flant/shell-operator/pkg/app"
1312
"github.com/flant/shell-operator/pkg/debug"
1413
"github.com/flant/shell-operator/pkg/jq"
@@ -19,17 +18,20 @@ import (
1918
func main() {
2019
kpApp := kingpin.New(app.AppName, fmt.Sprintf("%s %s: %s", app.AppName, app.Version, app.AppDescription))
2120

21+
logger := log.NewLogger(log.Options{})
22+
log.SetDefault(logger)
23+
2224
// override usage template to reveal additional commands with information about start command
2325
kpApp.UsageTemplate(app.OperatorUsageTemplate(app.AppName))
2426

2527
// Initialize klog wrapper when all values are parsed
26-
kpApp.Action(func(c *kingpin.ParseContext) error {
27-
klogtologrus.InitAdapter(app.DebugKubernetesAPI)
28+
kpApp.Action(func(_ *kingpin.ParseContext) error {
29+
klogtolog.InitAdapter(app.DebugKubernetesAPI, logger.Named("klog"))
2830
return nil
2931
})
3032

3133
// print version
32-
kpApp.Command("version", "Show version.").Action(func(c *kingpin.ParseContext) error {
34+
kpApp.Command("version", "Show version.").Action(func(_ *kingpin.ParseContext) error {
3335
fmt.Printf("%s %s\n", app.AppName, app.Version)
3436
fmt.Println(jq.FilterInfo())
3537
return nil
@@ -38,14 +40,11 @@ func main() {
3840
// start main loop
3941
startCmd := kpApp.Command("start", "Start shell-operator.").
4042
Default().
41-
Action(func(c *kingpin.ParseContext) error {
43+
Action(func(_ *kingpin.ParseContext) error {
4244
app.AppStartMessage = fmt.Sprintf("%s %s", app.AppName, app.Version)
4345

44-
// Init rand generator.
45-
rand.Seed(time.Now().UnixNano())
46-
4746
// Init logging and initialize a ShellOperator instance.
48-
operator, err := shell_operator.Init()
47+
operator, err := shell_operator.Init(logger.Named("shell-operator"))
4948
if err != nil {
5049
os.Exit(1)
5150
}

go.mod

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
module github.com/flant/shell-operator
22

3-
go 1.22
3+
go 1.22.8
44

55
require (
6-
github.com/flant/kube-client v1.2.0
6+
github.com/deckhouse/deckhouse/pkg/log v0.0.0-20241102120041-7e44e3e22ab9
7+
github.com/flant/kube-client v1.2.1
78
github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee // branch: master
89
github.com/go-chi/chi/v5 v5.1.0
910
github.com/go-openapi/spec v0.19.8
@@ -17,7 +18,6 @@ require (
1718
github.com/onsi/gomega v1.34.2
1819
github.com/pkg/errors v0.9.1
1920
github.com/prometheus/client_golang v1.20.5
20-
github.com/sirupsen/logrus v1.9.3
2121
github.com/stretchr/testify v1.9.0
2222
golang.org/x/time v0.7.0
2323
gopkg.in/alecthomas/kingpin.v2 v2.2.6
@@ -36,6 +36,7 @@ replace github.com/go-openapi/validate => github.com/flant/go-openapi-validate v
3636
require github.com/gojuno/minimock/v3 v3.4.0
3737

3838
require (
39+
github.com/DataDog/gostackparse v0.7.0 // indirect
3940
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
4041
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
4142
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect

go.sum

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2+
github.com/DataDog/gostackparse v0.7.0 h1:i7dLkXHvYzHV308hnkvVGDL3BR4FWl7IsXNPz/IGQh4=
3+
github.com/DataDog/gostackparse v0.7.0/go.mod h1:lTfqcJKqS9KnXQGnyQMCugq3u1FP6UZMfWR0aitKFMM=
24
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
35
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
46
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
@@ -22,15 +24,17 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
2224
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2325
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2426
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
27+
github.com/deckhouse/deckhouse/pkg/log v0.0.0-20241102120041-7e44e3e22ab9 h1:gCV1iKcaE69x3Knzj8isyVyEtRuG2YI4nmLIzBHBWeQ=
28+
github.com/deckhouse/deckhouse/pkg/log v0.0.0-20241102120041-7e44e3e22ab9/go.mod h1:Mk5HRzkc5pIcDIZ2JJ6DPuuqnwhXVkb3you8M8Mg+4w=
2529
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
2630
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
2731
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
2832
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
2933
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
3034
github.com/flant/go-openapi-validate v0.19.12-flant.0 h1:xk6kvc9fHKMgUdB6J7kbpbLR5vJOUzKAK8p3nrD7mDk=
3135
github.com/flant/go-openapi-validate v0.19.12-flant.0/go.mod h1:Rzou8hA/CBw8donlS6WNEUQupNvUZ0waH08tGe6kAQ4=
32-
github.com/flant/kube-client v1.2.0 h1:cOjnZgwoJVm4scqsMGcgO6qctJ+Z6wRVTFqvyhoAOiQ=
33-
github.com/flant/kube-client v1.2.0/go.mod h1:qjNvqCqnBqS+kc9Hj+wMBbkFzfdyGyiX4r4teE/0Pm8=
36+
github.com/flant/kube-client v1.2.1 h1:8lHF8+wGZrhsXM6TeS3CNAPupXyx7UJLkBvNMpCe/ZI=
37+
github.com/flant/kube-client v1.2.1/go.mod h1:62vCzrIUzWMU4DB0Pn6/02Pu7uwKh5/mHGWy2NmxZAk=
3438
github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee h1:evii83J+/6QGNvyf6tjQ/p27DPY9iftxIBb37ALJRTg=
3539
github.com/flant/libjq-go v1.6.3-0.20201126171326-c46a40ff22ee/go.mod h1:f+REaGl/+pZR97rbTcwHEka/MAipoQQ2Mc0iQUj4ak0=
3640
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@@ -255,8 +259,6 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm
255259
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
256260
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
257261
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
258-
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
259-
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
260262
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
261263
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
262264
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -341,7 +343,6 @@ golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7w
341343
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
342344
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
343345
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
344-
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
345346
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
346347
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
347348
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=

pkg/app/app.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ Use "%s debug-options" for a list of debug options for start command.
148148

149149
// CommandWithDefaultUsageTemplate is used to workaround an absence of per-command usage templates
150150
func CommandWithDefaultUsageTemplate(kpApp *kingpin.Application, name, help string) *kingpin.CmdClause {
151-
return kpApp.Command(name, help).PreAction(func(context *kingpin.ParseContext) error {
151+
return kpApp.Command(name, help).PreAction(func(_ *kingpin.ParseContext) error {
152152
kpApp.UsageTemplate(kingpin.DefaultUsageTemplate)
153153
return nil
154154
})

pkg/app/log.go

+39-52
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package app
22

33
import (
4-
"bytes"
54
"fmt"
65
"strings"
76
"time"
87

9-
log "github.com/sirupsen/logrus"
8+
"github.com/deckhouse/deckhouse/pkg/log"
109
"gopkg.in/alecthomas/kingpin.v2"
1110

1211
"github.com/flant/shell-operator/pkg/config"
@@ -45,68 +44,56 @@ func DefineLoggingFlags(cmd *kingpin.CmdClause) {
4544
}
4645

4746
// SetupLogging sets logger formatter and level.
48-
func SetupLogging(runtimeConfig *config.Config) {
49-
jsonFormatter := log.JSONFormatter{DisableTimestamp: LogNoTime}
50-
textFormatter := log.TextFormatter{DisableTimestamp: LogNoTime, DisableColors: true}
51-
colorFormatter := log.TextFormatter{DisableTimestamp: LogNoTime, ForceColors: true, FullTimestamp: true}
52-
switch strings.ToLower(LogType) {
53-
case "json":
54-
log.SetFormatter(&jsonFormatter)
55-
case "text":
56-
log.SetFormatter(&textFormatter)
57-
case "color":
58-
log.SetFormatter(&colorFormatter)
59-
default:
60-
log.SetFormatter(&jsonFormatter)
61-
}
62-
if LogProxyHookJSON {
63-
formatter := log.StandardLogger().Formatter
64-
log.SetFormatter(&ProxyJsonWrapperFormatter{WrappedFormatter: formatter})
65-
}
47+
func SetupLogging(runtimeConfig *config.Config, logger *log.Logger) {
48+
// TODO: if we need formatters - add to logger
49+
// jsonFormatter := log.JSONFormatter{DisableTimestamp: LogNoTime}
50+
// textFormatter := log.TextFormatter{DisableTimestamp: LogNoTime, DisableColors: true}
51+
// colorFormatter := log.TextFormatter{DisableTimestamp: LogNoTime, ForceColors: true, FullTimestamp: true}
52+
// switch strings.ToLower(LogType) {
53+
// case "json":
54+
// log.SetFormatter(&jsonFormatter)
55+
// case "text":
56+
// log.SetFormatter(&textFormatter)
57+
// case "color":
58+
// log.SetFormatter(&colorFormatter)
59+
// default:
60+
// log.SetFormatter(&jsonFormatter)
61+
// }
62+
// if LogProxyHookJSON {
63+
// formatter := log.StandardLogger().Formatter
64+
// log.SetFormatter(&ProxyJsonWrapperFormatter{WrappedFormatter: formatter})
65+
// }
6666

67-
setLogLevel(LogLevel)
67+
log.SetDefaultLevel(log.LogLevelFromStr(LogLevel))
6868

6969
runtimeConfig.Register("log.level",
7070
fmt.Sprintf("Global log level. Default duration for debug level is %s", ForcedDurationForDebugLevel),
7171
strings.ToLower(LogLevel),
72-
func(oldValue string, newValue string) error {
73-
log.Infof("Set log level to '%s'", newValue)
74-
setLogLevel(newValue)
72+
func(_ string, newValue string) error {
73+
logger.Infof("Set log level to '%s'", newValue)
74+
log.SetDefaultLevel(log.LogLevelFromStr(newValue))
7575
return nil
76-
}, func(oldValue string, newValue string) time.Duration {
76+
}, func(_ string, newValue string) time.Duration {
7777
if strings.ToLower(newValue) == "debug" {
7878
return ForcedDurationForDebugLevel
7979
}
8080
return 0
8181
})
8282
}
8383

84-
func setLogLevel(logLevel string) {
85-
switch strings.ToLower(logLevel) {
86-
case "debug":
87-
log.SetLevel(log.DebugLevel)
88-
case "error":
89-
log.SetLevel(log.ErrorLevel)
90-
case "info":
91-
log.SetLevel(log.InfoLevel)
92-
default:
93-
log.SetLevel(log.InfoLevel)
94-
}
95-
}
96-
97-
type ProxyJsonWrapperFormatter struct {
98-
WrappedFormatter log.Formatter
99-
}
84+
// type ProxyJsonWrapperFormatter struct {
85+
// WrappedFormatter log.Formatter
86+
// }
10087

101-
func (f *ProxyJsonWrapperFormatter) Format(entry *log.Entry) ([]byte, error) {
102-
// if proxying the json message is intended, just return the bytes
103-
// TODO: Find a more elegant way to carry this info
104-
if entry.Data[ProxyJsonLogKey] == true {
105-
b := bytes.NewBufferString(entry.Message)
106-
b.WriteString("\n")
107-
return b.Bytes(), nil
108-
}
88+
// func (f *ProxyJsonWrapperFormatter) Format(entry *log.Entry) ([]byte, error) {
89+
// // if proxying the json message is intended, just return the bytes
90+
// // TODO: Find a more elegant way to carry this info
91+
// if entry.Data[ProxyJsonLogKey] == true {
92+
// b := bytes.NewBufferString(entry.Message)
93+
// b.WriteString("\n")
94+
// return b.Bytes(), nil
95+
// }
10996

110-
// otherwise, use the wrapped formatter
111-
return f.WrappedFormatter.Format(entry)
112-
}
97+
// // otherwise, use the wrapped formatter
98+
// return f.WrappedFormatter.Format(entry)
99+
// }

pkg/config/config.go

+8-7
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ package config
22

33
import (
44
"fmt"
5+
"log/slog"
56
"sort"
67
"strings"
78
"sync"
89
"time"
910

10-
log "github.com/sirupsen/logrus"
11+
"github.com/deckhouse/deckhouse/pkg/log"
1112
)
1213

1314
/**
@@ -42,16 +43,16 @@ type Config struct {
4243
temporalValues map[string]*TemporalValue
4344
expireTicker *time.Ticker
4445

45-
logEntry *log.Entry
46+
logger *log.Logger
4647
}
4748

48-
func NewConfig() *Config {
49+
func NewConfig(logger *log.Logger) *Config {
4950
return &Config{
5051
params: make(map[string]*Parameter),
5152
values: make(map[string]string),
5253
temporalValues: make(map[string]*TemporalValue),
5354
errors: make(map[string]error),
54-
logEntry: log.WithField("component", "runtimeConfig"),
55+
logger: logger.With(slog.String("component", "runtimeConfig")),
5556
}
5657
}
5758

@@ -254,7 +255,7 @@ func (c *Config) expireOverrides() {
254255

255256
for _, expire := range expires {
256257
name, oldValue, newValue := expire[0], expire[1], expire[2]
257-
c.logEntry.Debugf("Parameter '%s' expired", name)
258+
c.logger.Debug("Parameter is expired", slog.String("parameter", name))
258259
c.callOnChange(name, oldValue, newValue)
259260
}
260261
}
@@ -266,8 +267,8 @@ func (c *Config) callOnChange(name string, oldValue string, newValue string) {
266267
}
267268
err := c.params[name].onChange(oldValue, newValue)
268269
if err != nil {
269-
c.logEntry.Errorf("OnChange handler failed for '%s' during value change from '%s' to '%s': %v",
270-
name, oldValue, newValue, err)
270+
c.logger.Error("OnChange handler failed for parameter during value change values",
271+
slog.String("parameter", name), slog.String("old_value", oldValue), slog.String("new_value", newValue), slog.String("error", err.Error()))
271272
}
272273
c.m.Lock()
273274
delete(c.errors, name)

0 commit comments

Comments
 (0)