From bc19d6592fad172faaacdd0b8a42a17c35cc5daf Mon Sep 17 00:00:00 2001 From: Oscar Zhou <100548325+oscarzhou-portainer@users.noreply.github.com> Date: Wed, 5 Feb 2025 12:17:51 +1300 Subject: [PATCH] fix(libstack): cannot open std edge stack log page [BE-11603] (#384) --- pkg/libstack/compose/composeplugin.go | 6 ++- pkg/libstack/compose/logwriter.go | 58 +++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 pkg/libstack/compose/logwriter.go diff --git a/pkg/libstack/compose/composeplugin.go b/pkg/libstack/compose/composeplugin.go index 7b6a639c4..3162c6ab7 100644 --- a/pkg/libstack/compose/composeplugin.go +++ b/pkg/libstack/compose/composeplugin.go @@ -31,8 +31,10 @@ const PortainerEdgeStackLabel = "io.portainer.edge_stack_id" var mu sync.Mutex func init() { - // Redirect Compose logging to zerolog - logrus.SetOutput(log.Logger) + logrus.SetOutput(&LogrusToZerologWriter{}) + logrus.SetFormatter(&logrus.TextFormatter{ + DisableTimestamp: true, + }) } func withCli( diff --git a/pkg/libstack/compose/logwriter.go b/pkg/libstack/compose/logwriter.go new file mode 100644 index 000000000..477433552 --- /dev/null +++ b/pkg/libstack/compose/logwriter.go @@ -0,0 +1,58 @@ +package compose + +import ( + "strings" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +// LogrusToZerologWriter is a custom logrus writer that writes logrus logs to zerolog. +// logrus is the logging library used by Docker Compose. +type LogrusToZerologWriter struct{} + +func (ltzw *LogrusToZerologWriter) Write(p []byte) (n int, err error) { + logMessage := string(p) + logMessage = strings.TrimSuffix(logMessage, "\n") + + // Parse the log level and message from the logrus log. + // This assumes logrus's default text format. + var level, message string + if strings.HasPrefix(logMessage, "time=") { + // Example logrus log: `time="2023-10-01T12:34:56Z" level=info msg="This is a log message" key=value` + parts := strings.SplitN(logMessage, " ", 4) + if len(parts) >= 3 { + level = strings.TrimPrefix(parts[1], "level=") + message = strings.TrimPrefix(parts[2], "msg=") + message = strings.Trim(message, `"`) + } + } else { + // Fallback for simpler log formats. + level = "info" + message = logMessage + } + + // Map logrus levels to zerolog levels. + var zlogLevel zerolog.Level + switch level { + case "debug": + zlogLevel = zerolog.DebugLevel + case "info": + zlogLevel = zerolog.InfoLevel + case "warn", "warning": + zlogLevel = zerolog.WarnLevel + case "error": + zlogLevel = zerolog.ErrorLevel + case "fatal": + zlogLevel = zerolog.FatalLevel + case "panic": + zlogLevel = zerolog.PanicLevel + default: + zlogLevel = zerolog.InfoLevel + } + + // Log the message using zerolog. + log.WithLevel(zlogLevel).Msg(message) + + return len(p), nil +}