From 857d0f820b05261491a09057e6fef0549abd3f3e Mon Sep 17 00:00:00 2001 From: Helene Durand Date: Tue, 10 Oct 2023 16:02:11 +0200 Subject: [PATCH] MINOR: add transactionID in all logs For debugging, this will help to match any failed transaction (saved in a file with the transactionID as suffix) with all logs related to it. --- pkg/controller/controller.go | 3 ++ pkg/haproxy/api/api.go | 2 ++ pkg/k8s/main.go | 3 +- pkg/utils/logging.go | 53 +++++++++++++++++++++++++++++++++--- 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 65baa9b4..ea7cefa1 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -106,6 +106,9 @@ func (c *HAProxyController) updateHAProxy() { defer func() { c.haproxy.APIDisposeTransaction() }() + // First log here that will contain the "transactionID" field (added in APIStartTransaction) + // All subsequent log line will contain the "transactionID" field. + logger.Trace("HAProxy config sync transaction started") reload, restart := c.handleGlobalConfig() c.reload = c.reload || reload diff --git a/pkg/haproxy/api/api.go b/pkg/haproxy/api/api.go index 35ac90dc..5c4f90e5 100644 --- a/pkg/haproxy/api/api.go +++ b/pkg/haproxy/api/api.go @@ -134,6 +134,7 @@ func (c *clientNative) APIStartTransaction() error { if err != nil { return err } + utils.GetLogger().WithField(utils.LogFieldTransactionID, transaction.ID) c.activeTransaction = transaction.ID c.activeTransactionHasChanges = false return nil @@ -155,6 +156,7 @@ func (c *clientNative) APICommitTransaction() error { } func (c *clientNative) APIDisposeTransaction() { + utils.GetLogger().ResetFields() c.activeTransaction = "" c.activeTransactionHasChanges = false } diff --git a/pkg/k8s/main.go b/pkg/k8s/main.go index aea05404..bb912e66 100644 --- a/pkg/k8s/main.go +++ b/pkg/k8s/main.go @@ -40,7 +40,7 @@ import ( gatewaynetworking "sigs.k8s.io/gateway-api/pkg/client/informers/externalversions" ) -var logger = utils.GetLogger() +var logger = utils.GetK8sLogger() // TRACE_API outputs all k8s events received from k8s API const ( @@ -85,6 +85,7 @@ type k8s struct { } func New(osArgs utils.OSArgs, whitelist map[string]struct{}, publishSvc *utils.NamespaceValue) K8s { //nolint:ireturn + logger.SetLevel(osArgs.LogLevel.LogLevel) restconfig, err := getRestConfig(osArgs) logger.Panic(err) builtInClient := k8sclientset.NewForConfigOrDie(restconfig) diff --git a/pkg/utils/logging.go b/pkg/utils/logging.go index 51c2ea06..04957659 100644 --- a/pkg/utils/logging.go +++ b/pkg/utils/logging.go @@ -38,6 +38,10 @@ const ( Trace LogLevel = 6 ) +const ( + LogFieldTransactionID = "transactionID" +) + // Logger provides functions to writing log messages // level can be defined only as `trace`, `debug`, `info`, `warning`, `error` // error and panic are always printed, panic also exits application. @@ -76,11 +80,14 @@ type Logger interface { //nolint:interfacebloat SetLevel(level LogLevel) ShowFilename(show bool) + WithField(key string, value interface{}) + ResetFields() } type logger struct { Level LogLevel FileName bool + fields map[string]interface{} } var ( @@ -88,18 +95,37 @@ var ( doOnce sync.Once ) +var ( + k8slogSingelton *logger + k8sdoOnce sync.Once +) + //nolint:golint // 'exported func GetLogger returns unexported type , which can be annoying to use' - this is deliberate here func GetLogger() *logger { doOnce.Do(func() { logSingelton = &logger{ Level: Warning, FileName: true, + fields: make(map[string]interface{}), } log.SetFlags(LogTypeShort) }) return logSingelton } +//nolint:golint // 'exported func GetK8sLogger returns unexported type , which can be annoying to use' - this is deliberate here +func GetK8sLogger() *logger { + k8sdoOnce.Do(func() { + k8slogSingelton = &logger{ + Level: Warning, + FileName: true, + fields: make(map[string]interface{}), + } + log.SetFlags(LogTypeShort) + }) + return k8slogSingelton +} + func (l *logger) SetLevel(level LogLevel) { l.Level = level } @@ -108,6 +134,25 @@ func (l *logger) ShowFilename(show bool) { l.FileName = show } +func (l *logger) WithField(key string, value interface{}) { + l.fields[key] = value +} + +func (l *logger) ResetFields() { + clear(l.fields) +} + +func (l *logger) fieldsAsString() string { + var fields strings.Builder + fields.WriteString("[") + for k, v := range l.fields { + fields.WriteString(fmt.Sprintf("%s=%v", k, v)) + } + fields.WriteString("]") + + return fields.String() +} + func (l *logger) log(logType string, data ...interface{}) { if !l.FileName { for _, d := range data { @@ -134,9 +179,9 @@ func (l *logger) log(logType string, data ...interface{}) { } if logType == "" { - log.Printf("%s:%d %s\n", file1, no, d) + log.Printf("%s:%d %s %s\n", file1, no, l.fieldsAsString(), d) } else { - log.Printf("%s%s:%d %s\n", logType, file1, no, d) + log.Printf("%s%s:%d %s %s\n", logType, file1, no, l.fieldsAsString(), d) } } } @@ -159,9 +204,9 @@ func (l *logger) logf(logType string, format string, data ...interface{}) { } // file1 := strings.Replace(file, "/src/", "", 1) if logType == "" { - log.Printf("%s:%d %s\n", file1, no, line) + log.Printf("%s:%d %s %s\n", file1, no, l.fieldsAsString(), line) } else { - log.Printf("%s%s:%d %s\n", logType, file1, no, line) + log.Printf("%s%s:%d %s %s\n", logType, file1, no, l.fieldsAsString(), line) } } }