Skip to content

Commit

Permalink
adjust log level at runtime (#1133)
Browse files Browse the repository at this point in the history
* adjust log level at runtime

* fix logger bug
  • Loading branch information
suchen-sci committed Nov 10, 2023
1 parent bb9e904 commit a146612
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 15 deletions.
42 changes: 42 additions & 0 deletions cmd/client/commandv2/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,47 @@ func LogsCmd() *cobra.Command {
}
cmd.Flags().IntVar(&n, "tail", 500, "Lines of recent log file to display. Defaults to 500, use -1 to show all lines")
cmd.Flags().BoolVarP(&follow, "follow", "f", false, "Specify if the logs should be streamed.")
cmd.AddCommand(setLogLevelCmd())
cmd.AddCommand(getLogLevelCmd())
return cmd
}

func setLogLevelCmd() *cobra.Command {
examples := []general.Example{
{Desc: "Set log level to info", Command: "egctl logs set-level info"},
{Desc: "Set log level to debug", Command: "egctl logs set-level debug"},
}

cmd := &cobra.Command{
Use: "set-level",
Short: "Set Easegress log level",
Example: createMultiExample(examples),
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
level := args[0]
p := general.LogsLevelURL + "/" + level
if _, err := general.HandleRequest(http.MethodPut, p, nil); err != nil {
general.ExitWithError(err)
}
fmt.Println("Set log level to", level)
},
}
return cmd
}

func getLogLevelCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "get-level",
Short: "Get Easegress log level",
Example: createExample("Get current log level.", "egctl logs get-level"),
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
body, err := general.HandleRequest(http.MethodGet, general.LogsLevelURL, nil)
if err != nil {
general.ExitWithError(err)
}
fmt.Println(string(body))
},
}
return cmd
}
2 changes: 2 additions & 0 deletions cmd/client/general/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ const (

// LogsURL is the URL of logs.
LogsURL = APIURL + "/logs"
// LogsLevelURL is the URL of logs level.
LogsLevelURL = APIURL + "/logs/level"

// HTTPProtocol is prefix for HTTP protocol
HTTPProtocol = "http:https://"
Expand Down
37 changes: 37 additions & 0 deletions pkg/api/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ import (
"net/http"
"os"
"strconv"
"strings"

"github.com/fsnotify/fsnotify"
"github.com/go-chi/chi/v5"
"github.com/megaease/easegress/v2/pkg/logger"
"go.uber.org/zap"
)

func (s *Server) logsAPIEntries() []*Entry {
Expand All @@ -36,6 +39,16 @@ func (s *Server) logsAPIEntries() []*Entry {
Method: "GET",
Handler: s.getLogs,
},
{
Path: "/logs/level/{level}",
Method: "PUT",
Handler: s.setLogLevel,
},
{
Path: "/logs/level",
Method: "GET",
Handler: s.getLogLevel,
},
}
}

Expand Down Expand Up @@ -76,6 +89,30 @@ func newLogFile(r *http.Request, filePath string) (*logFile, error) {
}, nil
}

func (s *Server) getLogLevel(w http.ResponseWriter, r *http.Request) {
level := logger.GetLogLevel()
w.WriteHeader(http.StatusOK)
w.Write([]byte(level))
}

func (s *Server) setLogLevel(w http.ResponseWriter, r *http.Request) {
level := chi.URLParam(r, "level")
if level == "" {
HandleAPIError(w, r, http.StatusBadRequest, errors.New("level is required"))
return
}
level = strings.ToLower(level)
if level == "debug" {
logger.SetLogLevel(zap.DebugLevel)
} else if level == "info" {
logger.SetLogLevel(zap.InfoLevel)
} else {
HandleAPIError(w, r, http.StatusBadRequest, fmt.Errorf("invalid level %s, only support to set log level to info or debug", level))
return
}
w.WriteHeader(http.StatusOK)
}

func (s *Server) getLogs(w http.ResponseWriter, r *http.Request) {
flusher := w.(http.Flusher)
var err error
Expand Down
37 changes: 22 additions & 15 deletions pkg/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,17 @@ import (
"github.com/megaease/easegress/v2/pkg/util/fasttime"
)

func init() {
globalLogLevel = zap.NewAtomicLevel()
globalLogLevel.SetLevel(zap.InfoLevel)
}

// Init initializes logger.
func Init(opt *option.Options) {
if opt.Debug {
globalLogLevel.SetLevel(zap.DebugLevel)
}

initDefault(opt)
initHTTPFilter(opt)
initRestAPI(opt)
Expand Down Expand Up @@ -92,10 +101,20 @@ var (
httpFilterAccessLogger *zap.SugaredLogger
httpFilterDumpLogger *zap.SugaredLogger
restAPILogger *zap.SugaredLogger
globalLogLevel zap.AtomicLevel

stdoutLogPath string
)

// SetLogLevel sets log level. Only support debug and info.
func SetLogLevel(level zapcore.Level) {
globalLogLevel.SetLevel(level)
}

func GetLogLevel() string {
return globalLogLevel.String()
}

// GetLogPath returns the path of stdout log.
func GetLogPath() string {
return stdoutLogPath
Expand All @@ -105,15 +124,8 @@ func GetLogPath() string {
func EtcdClientLoggerConfig(opt *option.Options, filename string) *zap.Config {
encoderConfig := defaultEncoderConfig()

level := zap.NewAtomicLevel()
if opt.Debug {
level.SetLevel(zapcore.DebugLevel)
} else {
level.SetLevel(zapcore.InfoLevel)
}

cfg := &zap.Config{
Level: level,
Level: globalLogLevel,
Encoding: "console",
EncoderConfig: encoderConfig,
OutputPaths: []string{"stdout"},
Expand Down Expand Up @@ -149,11 +161,6 @@ func defaultEncoderConfig() zapcore.EncoderConfig {
func initDefault(opt *option.Options) {
encoderConfig := defaultEncoderConfig()

lowestLevel := zap.InfoLevel
if opt.Debug {
lowestLevel = zap.DebugLevel
}

var err error
var gressLF io.Writer = os.Stdout
if opt.AbsLogDir != "" {
Expand All @@ -167,11 +174,11 @@ func initDefault(opt *option.Options) {
opts := []zap.Option{zap.AddCaller(), zap.AddCallerSkip(1)}

stderrSyncer := zapcore.AddSync(os.Stderr)
stderrCore := zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), stderrSyncer, lowestLevel)
stderrCore := zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), stderrSyncer, globalLogLevel)
stderrLogger = zap.New(stderrCore, opts...).Sugar()

gressSyncer := zapcore.AddSync(gressLF)
gressCore := zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), gressSyncer, lowestLevel)
gressCore := zapcore.NewCore(zapcore.NewConsoleEncoder(encoderConfig), gressSyncer, globalLogLevel)
gressLogger = zap.New(gressCore, opts...).Sugar()

defaultCore := gressCore
Expand Down

0 comments on commit a146612

Please sign in to comment.