diff --git a/cmd/webhook/init/configuration/configuration.go b/cmd/webhook/init/configuration/configuration.go index fd5a17d..a94fd3a 100644 --- a/cmd/webhook/init/configuration/configuration.go +++ b/cmd/webhook/init/configuration/configuration.go @@ -4,7 +4,9 @@ import ( "time" "github.com/caarlos0/env/v11" - log "github.com/sirupsen/logrus" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" + + "go.uber.org/zap" ) // Config struct for configuration environmental variables @@ -23,7 +25,7 @@ type Config struct { func Init() Config { cfg := Config{} if err := env.Parse(&cfg); err != nil { - log.Fatalf("error reading configuration from environment: %v", err) + log.Error("error reading configuration from environment", zap.Error(err)) } return cfg } diff --git a/cmd/webhook/init/dnsprovider/dnsprovider.go b/cmd/webhook/init/dnsprovider/dnsprovider.go index e8d5700..a05de29 100644 --- a/cmd/webhook/init/dnsprovider/dnsprovider.go +++ b/cmd/webhook/init/dnsprovider/dnsprovider.go @@ -7,11 +7,10 @@ import ( "github.com/caarlos0/env/v11" "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/configuration" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" "github.com/kashalls/external-dns-provider-unifi/internal/unifi" "sigs.k8s.io/external-dns/endpoint" "sigs.k8s.io/external-dns/provider" - - log "github.com/sirupsen/logrus" ) type UnifiProviderFactory func(baseProvider *provider.BaseProvider, unifiConfig *unifi.Config) provider.Provider diff --git a/cmd/webhook/init/log/log.go b/cmd/webhook/init/log/log.go new file mode 100644 index 0000000..394cc00 --- /dev/null +++ b/cmd/webhook/init/log/log.go @@ -0,0 +1,66 @@ +package log + +import ( + "os" + + "go.uber.org/zap" +) + +var logger *zap.Logger + +func Init() { + config := zap.NewProductionConfig() + + // Set the log format + format := os.Getenv("LOG_FORMAT") + if format == "test" { + config.Encoding = "console" + } else { + config.Encoding = "json" + } + + // Set the log level + level := os.Getenv("LOG_LEVEL") + switch level { + case "debug": + config.Level = zap.NewAtomicLevelAt(zap.DebugLevel) + case "info": + config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) + case "warn": + config.Level = zap.NewAtomicLevelAt(zap.WarnLevel) + case "error": + config.Level = zap.NewAtomicLevelAt(zap.ErrorLevel) + default: + config.Level = zap.NewAtomicLevelAt(zap.InfoLevel) + } + + // Build the logger + var err error + logger, err = config.Build() + if err != nil { + panic(err) + } + + // Ensure we flush any buffered log entries + defer logger.Sync() +} + +func Info(message string, fields ...zap.Field) { + logger.Info(message, fields...) +} + +func Debug(message string, fields ...zap.Field) { + logger.Debug(message, fields...) +} + +func Error(message string, fields ...zap.Field) { + logger.Error(message, fields...) +} + +func Fatal(message string, fields ...zap.Field) { + logger.Fatal(message, fields...) +} + +func With(fields ...zap.Field) *zap.Logger { + return logger.With(fields...) +} diff --git a/cmd/webhook/init/logging/log.go b/cmd/webhook/init/logging/log.go deleted file mode 100644 index 9b72e1b..0000000 --- a/cmd/webhook/init/logging/log.go +++ /dev/null @@ -1,37 +0,0 @@ -package logging - -import ( - "os" - - log "github.com/sirupsen/logrus" -) - -func Init() { - setLogLevel() - setLogFormat() -} - -func setLogFormat() { - format := os.Getenv("LOG_FORMAT") - if format == "test" { - log.SetFormatter(&log.TextFormatter{}) - } else { - log.SetFormatter(&log.JSONFormatter{}) - } -} - -func setLogLevel() { - level := os.Getenv("LOG_LEVEL") - switch level { - case "debug": - log.SetLevel(log.DebugLevel) - case "info": - log.SetLevel(log.InfoLevel) - case "warn": - log.SetLevel(log.WarnLevel) - case "error": - log.SetLevel(log.ErrorLevel) - default: - log.SetLevel(log.InfoLevel) - } -} diff --git a/cmd/webhook/init/server/server.go b/cmd/webhook/init/server/server.go index ab356da..eabb986 100644 --- a/cmd/webhook/init/server/server.go +++ b/cmd/webhook/init/server/server.go @@ -12,10 +12,11 @@ import ( "github.com/go-chi/chi/v5" "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/configuration" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" "github.com/kashalls/external-dns-provider-unifi/pkg/webhook" "github.com/prometheus/client_golang/prometheus/promhttp" - log "github.com/sirupsen/logrus" + "go.uber.org/zap" ) // HealthCheckHandler returns the status of the service @@ -40,9 +41,9 @@ func Init(config configuration.Config, p *webhook.Webhook) (*http.Server, *http. mainServer := createHTTPServer(fmt.Sprintf("%s:%d", config.ServerHost, config.ServerPort), mainRouter, config.ServerReadTimeout, config.ServerWriteTimeout) go func() { - log.Infof("starting server on addr: '%s' ", mainServer.Addr) + log.Info("starting webhook server", zap.String("address", mainServer.Addr)) if err := mainServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Errorf("can't serve on addr: '%s', error: %v", mainServer.Addr, err) + log.Error("unable to start webhook server", zap.String("address", mainServer.Addr), zap.Error(err)) } }() @@ -53,9 +54,9 @@ func Init(config configuration.Config, p *webhook.Webhook) (*http.Server, *http. healthServer := createHTTPServer("0.0.0.0:8080", healthRouter, config.ServerReadTimeout, config.ServerWriteTimeout) go func() { - log.Infof("starting health server on addr: '%s' ", healthServer.Addr) + log.Info("starting health server", zap.String("address", healthServer.Addr)) if err := healthServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { - log.Errorf("can't serve health on addr: '%s', error: %v", healthServer.Addr, err) + log.Error("unable to start health server", zap.String("address", healthServer.Addr), zap.Error(err)) } }() @@ -77,15 +78,15 @@ func ShutdownGracefully(mainServer *http.Server, healthServer *http.Server) { signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) sig := <-sigCh - log.Infof("shutting down servers due to received signal: %v", sig) + log.Info("shutting down servers due to received signal", zap.Any("signal", sig)) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() if err := mainServer.Shutdown(ctx); err != nil { - log.Errorf("error shutting down main server: %v", err) + log.Error("error shutting down main server", zap.Error(err)) } if err := healthServer.Shutdown(ctx); err != nil { - log.Errorf("error shutting down health server: %v", err) + log.Error("error shutting down health server", zap.Error(err)) } } diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index f8a55ca..19a0184 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -5,10 +5,11 @@ import ( "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/configuration" "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/dnsprovider" - "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/logging" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/server" "github.com/kashalls/external-dns-provider-unifi/pkg/webhook" - log "github.com/sirupsen/logrus" + + "go.uber.org/zap" ) const banner = ` @@ -25,12 +26,12 @@ var ( func main() { fmt.Printf(banner, Version, Gitsha) - logging.Init() + log.Init() config := configuration.Init() provider, err := dnsprovider.Init(config) if err != nil { - log.Fatalf("failed to initialize provider: %v", err) + log.Error("failed to initialize provider", zap.Error(err)) } main, health := server.Init(config, webhook.New(provider)) diff --git a/go.mod b/go.mod index 845fca1..316f4ac 100644 --- a/go.mod +++ b/go.mod @@ -8,33 +8,35 @@ require ( github.com/caarlos0/env/v11 v11.0.1 github.com/go-chi/chi/v5 v5.0.12 github.com/prometheus/client_golang v1.19.1 - github.com/sirupsen/logrus v1.9.3 + go.uber.org/zap v1.27.0 golang.org/x/net v0.26.0 sigs.k8s.io/external-dns v0.14.2 ) require ( - github.com/aws/aws-sdk-go v1.53.9 // indirect + github.com/aws/aws-sdk-go v1.54.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/text v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.53.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/prometheus/common v0.54.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + go.uber.org/multierr v1.11.0 // indirect golang.org/x/sys v0.21.0 // indirect golang.org/x/text v0.16.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - k8s.io/apimachinery v0.30.1 // indirect + k8s.io/apimachinery v0.30.2 // indirect k8s.io/klog/v2 v2.120.1 // indirect k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index 001b595..8fb1b4f 100644 --- a/go.sum +++ b/go.sum @@ -1,12 +1,11 @@ -github.com/aws/aws-sdk-go v1.53.9 h1:6oipls9+L+l2Me5rklqlX3xGWNWGcMinY3F69q9Q+Cg= -github.com/aws/aws-sdk-go v1.53.9/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= +github.com/aws/aws-sdk-go v1.54.0 h1:tGCQ6YS2TepzKtbl+ddXnLIoV8XvWdxMKtuMxdrsa4U= +github.com/aws/aws-sdk-go v1.54.0/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/caarlos0/env/v11 v11.0.1 h1:A8dDt9Ub9ybqRSUF3fQc/TA/gTam2bKT4Pit+cwrsPs= github.com/caarlos0/env/v11 v11.0.1/go.mod h1:2RC3HQu8BQqtEK3V4iHPxj0jOdWdbPpWJ6pOueeU1xM= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= @@ -47,12 +46,12 @@ github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQ github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= -github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/prometheus/common v0.54.0 h1:ZlZy0BgJhTwVZUn7dLOkwCZHUkrAqd3WYtcFCWnM1D8= +github.com/prometheus/common v0.54.0/go.mod h1:/TQgMJP5CuVYveyT7n/0Ix8yLNNXy9yRSkhnLTHPDIQ= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -66,6 +65,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -98,8 +103,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= @@ -111,8 +116,8 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/apimachinery v0.30.1 h1:ZQStsEfo4n65yAdlGTfP/uSHMQSoYzU/oeEbkmF7P2U= -k8s.io/apimachinery v0.30.1/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= +k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/utils v0.0.0-20240502163921-fe8a2dddb1d0 h1:jgGTlFYnhF1PM1Ax/lAlxUPE+KfCIXHaathvJg1C3ak= diff --git a/internal/unifi/client.go b/internal/unifi/client.go index e452431..6f1f934 100644 --- a/internal/unifi/client.go +++ b/internal/unifi/client.go @@ -10,9 +10,11 @@ import ( "net/http/cookiejar" "net/url" - log "github.com/sirupsen/logrus" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" "golang.org/x/net/publicsuffix" "sigs.k8s.io/external-dns/endpoint" + + "go.uber.org/zap" ) // httpClient is the DNS provider client. @@ -78,7 +80,7 @@ func (c *httpClient) login() error { // Check if the login was successful if resp.StatusCode != http.StatusOK { respBody, _ := io.ReadAll(resp.Body) - log.Errorf("login failed: %s, response: %s", resp.Status, string(respBody)) + log.Error("login failed", zap.String("status", resp.Status), zap.String("response", string(respBody))) return fmt.Errorf("login failed: %s", resp.Status) } @@ -92,7 +94,7 @@ func (c *httpClient) login() error { // doRequest makes an HTTP request to the UniFi controller. func (c *httpClient) doRequest(method, path string, body io.Reader) (*http.Response, error) { - log.Debugf("making %s request to %s", method, path) + log.Debug(fmt.Sprintf("making %s request to %s", method, path)) req, err := http.NewRequest(method, path, body) if err != nil { @@ -110,11 +112,11 @@ func (c *httpClient) doRequest(method, path string, body io.Reader) (*http.Respo c.csrf = csrf } - log.Debugf("response code from %s request to %s: %d", method, path, resp.StatusCode) + log.Debug(fmt.Sprintf("response code from %s request to %s: %d", method, path, resp.StatusCode)) // If the status code is 401, re-login and retry the request if resp.StatusCode == http.StatusUnauthorized { - log.Debugf("Received 401 Unauthorized, re-login required") + log.Debug("Received 401 Unauthorized, re-login required") if err := c.login(); err != nil { return nil, err } @@ -150,7 +152,8 @@ func (c *httpClient) GetEndpoints() ([]DNSRecord, error) { if err = json.NewDecoder(resp.Body).Decode(&records); err != nil { return nil, err } - log.Debugf("retrieved records: %+v", records) + + log.Debug(fmt.Sprintf("retrieved records: %+v", records)) return records, nil } @@ -181,7 +184,8 @@ func (c *httpClient) CreateEndpoint(endpoint *endpoint.Endpoint) (*DNSRecord, er if err = json.NewDecoder(resp.Body).Decode(&record); err != nil { return nil, err } - log.Debugf("created record: %+v", record) + + log.Debug(fmt.Sprintf("created record: %+v", record)) return &record, nil } @@ -230,8 +234,8 @@ func (c *httpClient) setHeaders(req *http.Request) { // Log the request URL and cookies if c.Client.Jar != nil { parsedURL, _ := url.Parse(req.URL.String()) - log.Debugf("Requesting %s cookies: %d", req.URL, len(c.Client.Jar.Cookies(parsedURL))) + log.Debug(fmt.Sprintf("Requesting %s cookies: %d", req.URL, len(c.Client.Jar.Cookies(parsedURL)))) } else { - log.Debugf("Requesting %s", req.URL) + log.Debug(fmt.Sprintf("Requesting %s", req.URL)) } } diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index b16a5a9..735ad4d 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -5,21 +5,20 @@ import ( "fmt" "net/http" - log "github.com/sirupsen/logrus" + "github.com/kashalls/external-dns-provider-unifi/cmd/webhook/init/log" "sigs.k8s.io/external-dns/endpoint" "sigs.k8s.io/external-dns/plan" "sigs.k8s.io/external-dns/provider" + + "go.uber.org/zap" ) const ( - contentTypeHeader = "Content-Type" - contentTypePlaintext = "text/plain" - acceptHeader = "Accept" - varyHeader = "Vary" - logFieldRequestPath = "requestPath" - logFieldRequestMethod = "requestMethod" - logFieldError = "error" + contentTypeHeader = "Content-Type" + contentTypePlaintext = "text/plain" + acceptHeader = "Accept" + varyHeader = "Vary" ) // Webhook for external dns provider @@ -63,7 +62,7 @@ func (p *Webhook) headerCheck(isContentType bool, w http.ResponseWriter, r *http _, writeErr := fmt.Fprint(w, err.Error()) if writeErr != nil { - requestLog(r).WithField(logFieldError, writeErr).Fatalf("error writing error message to response writer") + requestLog(r).With(zap.Error(writeErr)).Fatal("error writing error message to response writer") } return err } @@ -83,7 +82,7 @@ func (p *Webhook) headerCheck(isContentType bool, w http.ResponseWriter, r *http err := fmt.Errorf(msg+": %s", err.Error()) _, writeErr := fmt.Fprint(w, err.Error()) if writeErr != nil { - requestLog(r).WithField(logFieldError, writeErr).Fatalf("error writing error message to response writer") + requestLog(r).With(zap.Error(writeErr)).Fatal("error writing error message to response writer") } return err } @@ -94,7 +93,7 @@ func (p *Webhook) headerCheck(isContentType bool, w http.ResponseWriter, r *http // Records handles the get request for records func (p *Webhook) Records(w http.ResponseWriter, r *http.Request) { if err := p.acceptHeaderCheck(w, r); err != nil { - requestLog(r).WithField(logFieldError, err).Error("accept header check failed") + requestLog(r).With(zap.Error(err)).Error("accept header check failed") return } @@ -102,17 +101,17 @@ func (p *Webhook) Records(w http.ResponseWriter, r *http.Request) { ctx := r.Context() records, err := p.provider.Records(ctx) if err != nil { - requestLog(r).WithField(logFieldError, err).Error("error getting records") + requestLog(r).With(zap.Error(err)).Error("error getting records") w.WriteHeader(http.StatusInternalServerError) return } - requestLog(r).Debugf("returning records count: %d", len(records)) + requestLog(r).With(zap.Int("count", len(records))).Debug("returning records") w.Header().Set(contentTypeHeader, string(mediaTypeVersion1)) w.Header().Set(varyHeader, contentTypeHeader) err = json.NewEncoder(w).Encode(records) if err != nil { - requestLog(r).WithField(logFieldError, err).Error("error encoding records") + requestLog(r).With(zap.Error(err)).Error("error encoding records") w.WriteHeader(http.StatusInternalServerError) return } @@ -121,7 +120,7 @@ func (p *Webhook) Records(w http.ResponseWriter, r *http.Request) { // ApplyChanges handles the post request for record changes func (p *Webhook) ApplyChanges(w http.ResponseWriter, r *http.Request) { if err := p.contentTypeHeaderCheck(w, r); err != nil { - requestLog(r).WithField(logFieldError, err).Error("content type header check failed") + requestLog(r).With(zap.Error(err)).Error("content type header check failed") return } @@ -133,14 +132,18 @@ func (p *Webhook) ApplyChanges(w http.ResponseWriter, r *http.Request) { errMsg := fmt.Sprintf("error decoding changes: %s", err.Error()) if _, writeError := fmt.Fprint(w, errMsg); writeError != nil { - requestLog(r).WithField(logFieldError, writeError).Fatalf("error writing error message to response writer") + requestLog(r).With(zap.Error(writeError)).Fatal("error writing error message to response writer") } - requestLog(r).WithField(logFieldError, err).Info(errMsg) + requestLog(r).With(zap.Error(err)).Info(errMsg) return } - requestLog(r).Debugf("requesting apply changes, create: %d , updateOld: %d, updateNew: %d, delete: %d", - len(changes.Create), len(changes.UpdateOld), len(changes.UpdateNew), len(changes.Delete)) + requestLog(r).With( + zap.Int("create", len(changes.Create)), + zap.Int("update_old", len(changes.UpdateOld)), + zap.Int("update_new", len(changes.UpdateNew)), + zap.Int("delete", len(changes.Delete)), + ).Debug("requesting apply changes") if err := p.provider.ApplyChanges(ctx, &changes); err != nil { w.Header().Set(contentTypeHeader, contentTypePlaintext) w.WriteHeader(http.StatusInternalServerError) @@ -152,11 +155,11 @@ func (p *Webhook) ApplyChanges(w http.ResponseWriter, r *http.Request) { // AdjustEndpoints handles the post request for adjusting endpoints func (p *Webhook) AdjustEndpoints(w http.ResponseWriter, r *http.Request) { if err := p.contentTypeHeaderCheck(w, r); err != nil { - log.Errorf("content type header check failed, request method: %s, request path: %s", r.Method, r.URL.Path) + log.Error("content-type header check failed", zap.String("req_method", r.Method), zap.String("req_path", r.URL.Path)) return } if err := p.acceptHeaderCheck(w, r); err != nil { - log.Errorf("accept header check failed, request method: %s, request path: %s", r.Method, r.URL.Path) + log.Error("accept header check failed", zap.String("req_method", r.Method), zap.String("req_path", r.URL.Path)) return } @@ -166,14 +169,14 @@ func (p *Webhook) AdjustEndpoints(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusBadRequest) errMessage := fmt.Sprintf("failed to decode request body: %v", err) - log.Infof(errMessage+" , request method: %s, request path: %s", r.Method, r.URL.Path) + requestLog(r).With(zap.Error(err)).Info("failed to decode request body") if _, writeError := fmt.Fprint(w, errMessage); writeError != nil { - requestLog(r).WithField(logFieldError, writeError).Fatalf("error writing error message to response writer") + requestLog(r).With(zap.Error(writeError)).Fatal("error writing error message to response writer") } return } - log.Debugf("requesting adjust endpoints count: %d", len(pve)) + log.Debug("requesting adjust endpoints count", zap.Int("endpoints", len(pve))) pve, err := p.provider.AdjustEndpoints(pve) if err != nil { w.Header().Set(contentTypeHeader, contentTypePlaintext) @@ -182,35 +185,36 @@ func (p *Webhook) AdjustEndpoints(w http.ResponseWriter, r *http.Request) { } out, _ := json.Marshal(&pve) - log.Debugf("return adjust endpoints response, resultEndpointCount: %d", len(pve)) + log.Debug("return adjust endpoints response", zap.Int("endpoints", len(pve))) + w.Header().Set(contentTypeHeader, string(mediaTypeVersion1)) w.Header().Set(varyHeader, contentTypeHeader) if _, writeError := fmt.Fprint(w, string(out)); writeError != nil { - requestLog(r).WithField(logFieldError, writeError).Fatalf("error writing response") + requestLog(r).With(zap.Error(writeError)).Fatal("error writing response") } } func (p *Webhook) Negotiate(w http.ResponseWriter, r *http.Request) { if err := p.acceptHeaderCheck(w, r); err != nil { - requestLog(r).WithField(logFieldError, err).Error("accept header check failed") + requestLog(r).With(zap.Error(err)).Error("accept header check failed") return } b, err := p.provider.GetDomainFilter().MarshalJSON() if err != nil { - log.Errorf("failed to marshal domain filter, request method: %s, request path: %s", r.Method, r.URL.Path) + requestLog(r).Error("failed to marshal domain filter") w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set(contentTypeHeader, string(mediaTypeVersion1)) if _, writeError := w.Write(b); writeError != nil { - requestLog(r).WithField(logFieldError, writeError).Error("error writing response") + requestLog(r).With(zap.Error(writeError)).Error("error writing response") w.WriteHeader(http.StatusInternalServerError) return } } -func requestLog(r *http.Request) *log.Entry { - return log.WithFields(log.Fields{logFieldRequestMethod: r.Method, logFieldRequestPath: r.URL.Path}) +func requestLog(r *http.Request) *zap.Logger { + return log.With(zap.String("req_method", r.Method), zap.String("req_path", r.URL.Path)) }