From fcfa1882957a1d111c616c1ef646b98a0fb6a70f Mon Sep 17 00:00:00 2001 From: xiangtianyu Date: Thu, 11 Aug 2022 17:35:49 +0800 Subject: [PATCH] feat: add log rotate (#1200) --- CHANGELOG.md | 2 ++ cmd/ingress/ingress.go | 27 ++++++++++++++++++---- cmd/ingress/ingress_test.go | 46 +++++++++++++++++++++++++++++++++++++ conf/config-default.yaml | 5 ++++ go.mod | 1 + go.sum | 2 ++ pkg/config/config.go | 8 +++++++ pkg/config/config_test.go | 8 +++++++ 8 files changed, 95 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00d3b8f279..9e9fd5e983 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -363,6 +363,7 @@ https://github.com/apache/apisix-ingress-controller/issues. * chen zhuo ### Changes +
24 commits

@@ -390,6 +391,7 @@ https://github.com/apache/apisix-ingress-controller/issues. * [`4a2ebaf`](https://github.com/apache/apisix-ingress-controller/commit/4a2ebaf43ee4cf42212659b412e7ed8a8ab8ee21) chore: fix typo in ApidixRoute CRD (#830) * [`46fcf3f`](https://github.com/apache/apisix-ingress-controller/commit/46fcf3f153a00cef868454b06452065172500dd1) fix: consumer name contain "-" (#828) * [`b7dd90a`](https://github.com/apache/apisix-ingress-controller/commit/b7dd90ad9d6a5102fe67c91c29ab76fc4bad4b1a) chore: v1.4 release +

diff --git a/cmd/ingress/ingress.go b/cmd/ingress/ingress.go index cf732566ae..6450449de5 100644 --- a/cmd/ingress/ingress.go +++ b/cmd/ingress/ingress.go @@ -25,6 +25,8 @@ import ( "time" "github.com/spf13/cobra" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" "github.com/apache/apisix-ingress-controller/pkg/config" "github.com/apache/apisix-ingress-controller/pkg/log" @@ -102,10 +104,23 @@ the apisix cluster and others are created`, dief("bad configuration: %s", err) } - logger, err := log.NewLogger( - log.WithLogLevel(cfg.LogLevel), - log.WithOutputFile(cfg.LogOutput), - ) + var ws zapcore.WriteSyncer + + options := []log.Option{log.WithLogLevel(cfg.LogLevel), log.WithOutputFile(cfg.LogOutput)} + + if cfg.LogRotateOutputPath != "" { + ws = zapcore.AddSync(&lumberjack.Logger{ + Filename: cfg.LogRotateOutputPath, + MaxSize: cfg.LogRotationMaxSize, + MaxBackups: cfg.LogRotationMaxBackups, + MaxAge: cfg.LogRotationMaxAge, + }) + + options = append(options, log.WithWriteSyncer(ws)) + } + + logger, err := log.NewLogger(options...) + if err != nil { dief("failed to initialize logging: %s", err) } @@ -143,6 +158,10 @@ the apisix cluster and others are created`, cmd.PersistentFlags().StringVar(&configPath, "config-path", "", "configuration file path for apisix-ingress-controller") cmd.PersistentFlags().StringVar(&cfg.LogLevel, "log-level", "info", "error log level") cmd.PersistentFlags().StringVar(&cfg.LogOutput, "log-output", "stderr", "error log output file") + cmd.PersistentFlags().StringVar(&cfg.LogRotateOutputPath, "log-rotate-output-path", "", "rotate log output path") + cmd.PersistentFlags().IntVar(&cfg.LogRotationMaxSize, "log-rotate-max-size", 100, "rotate log max size") + cmd.PersistentFlags().IntVar(&cfg.LogRotationMaxAge, "log-rotate-max-age", 0, "old rotate log max age to retain") + cmd.PersistentFlags().IntVar(&cfg.LogRotationMaxBackups, "log-rotate-max-backups", 0, "old rotate log max numbers to retain") cmd.PersistentFlags().StringVar(&cfg.HTTPListen, "http-listen", ":8080", "the HTTP Server listen address") cmd.PersistentFlags().StringVar(&cfg.HTTPSListen, "https-listen", ":8443", "the HTTPS Server listen address") cmd.PersistentFlags().StringVar(&cfg.IngressPublishService, "ingress-publish-service", "", diff --git a/cmd/ingress/ingress_test.go b/cmd/ingress/ingress_test.go index 35168ef8a7..a32a00b7b6 100644 --- a/cmd/ingress/ingress_test.go +++ b/cmd/ingress/ingress_test.go @@ -19,6 +19,7 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "math/rand" "os" "strings" @@ -162,3 +163,48 @@ func parseLog(t *testing.T, r *bufio.Reader) *fields { assert.Nil(t, err) return &f } + +func TestRotateLog(t *testing.T) { + listen := getRandomListen() + cmd := NewIngressCommand() + cmd.SetArgs([]string{ + "--log-rotate-output-path", "./testlog/test.log", + "--log-rotate-max-size", "1", + "--http-listen", listen, + "--enable-profiling", + "--kubeconfig", "/foo/bar/baz", + "--resync-interval", "24h", + "--default-apisix-cluster-base-url", "http://apisixgw.default.cluster.local/apisix", + "--default-apisix-cluster-admin-key", "0x123", + }) + defer os.RemoveAll("./testlog/") + + stopCh := make(chan struct{}) + go func() { + assert.Nil(t, cmd.Execute()) + close(stopCh) + }() + + // fill logs with data until the size > 1m + line := "" + for i := 0; i < 256; i++ { + line += "0" + } + + for i := 0; i < 4096; i++ { + log.Info(line) + } + + time.Sleep(5 * time.Second) + assert.Nil(t, syscall.Kill(os.Getpid(), syscall.SIGINT)) + <-stopCh + + files, err := ioutil.ReadDir("./testlog") + + if err != nil { + t.Fatalf("Unable to read log dir: %v", err) + } + + assert.Equal(t, true, len(files) >= 2) + +} diff --git a/conf/config-default.yaml b/conf/config-default.yaml index a91aa3e891..3fe9cf1c33 100644 --- a/conf/config-default.yaml +++ b/conf/config-default.yaml @@ -27,6 +27,11 @@ log_output: "stderr" # the output file path of error log, default is stderr, whe # are marshalled in JSON format, which can be parsed by # programs easily. +log_rotate_output_path: "" # rotate output path, the logs will be written in this file +log_rotation_max_size: 100 # rotate max size, max size in megabytes of log file before it get rotated. It defaults to 100 +log_rotation_max_age: 0 # rotate max age, max age of old log files to retain +log_rotation_max_backups: 0 # rotate max backups, max numbers of old log files to retain + cert_file: "/etc/webhook/certs/cert.pem" # the TLS certificate file path. key_file: "/etc/webhook/certs/key.pem" # the TLS key file path. diff --git a/go.mod b/go.mod index 1a486d1a69..83720cb4fd 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( go.uber.org/multierr v1.8.0 go.uber.org/zap v1.21.0 golang.org/x/net v0.0.0-20220725212005-46097bf591d3 + gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/yaml.v2 v2.4.0 k8s.io/api v0.24.3 k8s.io/apimachinery v0.24.3 diff --git a/go.sum b/go.sum index 5d6e37093d..a29610c4f2 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,7 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935 github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -999,6 +1000,7 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/pkg/config/config.go b/pkg/config/config.go index 4e061b6c48..a3997e0fcb 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -79,6 +79,10 @@ type Config struct { KeyFilePath string `json:"key_file" yaml:"key_file"` LogLevel string `json:"log_level" yaml:"log_level"` LogOutput string `json:"log_output" yaml:"log_output"` + LogRotateOutputPath string `json:"log_rotate_output_path" yaml:"log_rotate_output_path"` + LogRotationMaxSize int `json:"log_rotation_max_size" yaml:"log_rotation_max_size"` + LogRotationMaxAge int `json:"log_rotation_max_age" yaml:"log_rotation_max_age"` + LogRotationMaxBackups int `json:"log_rotation_max_backups" yaml:"log_rotation_max_backups"` HTTPListen string `json:"http_listen" yaml:"http_listen"` HTTPSListen string `json:"https_listen" yaml:"https_listen"` IngressPublishService string `json:"ingress_publish_service" yaml:"ingress_publish_service"` @@ -120,6 +124,10 @@ func NewDefaultConfig() *Config { return &Config{ LogLevel: "warn", LogOutput: "stderr", + LogRotateOutputPath: "", + LogRotationMaxSize: 100, + LogRotationMaxAge: 0, + LogRotationMaxBackups: 0, HTTPListen: ":8080", HTTPSListen: ":8443", IngressPublishService: "", diff --git a/pkg/config/config_test.go b/pkg/config/config_test.go index c448d440e0..5586114992 100644 --- a/pkg/config/config_test.go +++ b/pkg/config/config_test.go @@ -30,6 +30,10 @@ func TestNewConfigFromFile(t *testing.T) { cfg := &Config{ LogLevel: "warn", LogOutput: "stdout", + LogRotateOutputPath: "", + LogRotationMaxSize: 100, + LogRotationMaxAge: 0, + LogRotationMaxBackups: 0, HTTPListen: ":9090", HTTPSListen: ":9443", IngressPublishService: "", @@ -114,6 +118,10 @@ func TestConfigWithEnvVar(t *testing.T) { cfg := &Config{ LogLevel: "warn", LogOutput: "stdout", + LogRotateOutputPath: "", + LogRotationMaxSize: 100, + LogRotationMaxAge: 0, + LogRotationMaxBackups: 0, HTTPListen: ":9090", HTTPSListen: ":9443", IngressPublishService: "",