From 79f9af592fedb1bade8285029c5d990cd6c806f2 Mon Sep 17 00:00:00 2001 From: Bailey Hayes Date: Mon, 28 Jul 2025 19:49:59 -0400 Subject: [PATCH] fix: replace logrus with slog - Adjust some logs to use structured outputs - Set stdioserver log prefix as const - Do not export test func removeTimeAttr Signed-off-by: Bailey Hayes --- go.mod | 1 - go.sum | 4 --- internal/ghmcp/server.go | 26 ++++++++++++------- pkg/log/io.go | 10 +++---- pkg/log/io_test.go | 22 ++++++++-------- third-party-licenses.darwin.md | 1 - third-party-licenses.linux.md | 1 - third-party-licenses.windows.md | 1 - .../github.com/sirupsen/logrus/LICENSE | 21 --------------- 9 files changed, 33 insertions(+), 54 deletions(-) delete mode 100644 third-party/github.com/sirupsen/logrus/LICENSE diff --git a/go.mod b/go.mod index 3df6bf3d5..b89daa174 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,6 @@ require ( github.com/josephburnett/jd v1.9.2 github.com/mark3labs/mcp-go v0.32.0 github.com/migueleliasweb/go-github-mock v1.3.0 - github.com/sirupsen/logrus v1.9.3 github.com/spf13/cobra v1.9.1 github.com/spf13/viper v1.20.1 github.com/stretchr/testify v1.10.0 diff --git a/go.sum b/go.sum index d77cdf0d9..b445b1b6b 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,6 @@ github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7 h1:cYCy18SHPKRkv github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= @@ -83,7 +81,6 @@ github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqj github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= @@ -98,7 +95,6 @@ golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0 golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= diff --git a/internal/ghmcp/server.go b/internal/ghmcp/server.go index d993b130a..8ac3d91b1 100644 --- a/internal/ghmcp/server.go +++ b/internal/ghmcp/server.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "log" + "log/slog" "net/http" "net/url" "os" @@ -21,7 +22,6 @@ import ( "github.com/mark3labs/mcp-go/mcp" "github.com/mark3labs/mcp-go/server" "github.com/shurcooL/githubv4" - "github.com/sirupsen/logrus" ) type MCPServerConfig struct { @@ -49,6 +49,8 @@ type MCPServerConfig struct { Translator translations.TranslationHelperFunc } +const stdioServerLogPrefix = "stdioserver" + func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) { apiHost, err := parseAPIHost(cfg.Host) if err != nil { @@ -203,17 +205,22 @@ func RunStdioServer(cfg StdioServerConfig) error { stdioServer := server.NewStdioServer(ghServer) - logrusLogger := logrus.New() + var slogHandler slog.Handler + var logOutput io.Writer if cfg.LogFilePath != "" { file, err := os.OpenFile(cfg.LogFilePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) if err != nil { return fmt.Errorf("failed to open log file: %w", err) } - - logrusLogger.SetLevel(logrus.DebugLevel) - logrusLogger.SetOutput(file) - } - stdLogger := log.New(logrusLogger.Writer(), "stdioserver", 0) + logOutput = file + slogHandler = slog.NewTextHandler(logOutput, &slog.HandlerOptions{Level: slog.LevelDebug}) + } else { + logOutput = os.Stderr + slogHandler = slog.NewTextHandler(logOutput, &slog.HandlerOptions{Level: slog.LevelInfo}) + } + logger := slog.New(slogHandler) + logger.Info("starting server", "version", cfg.Version, "host", cfg.Host, "dynamicToolsets", cfg.DynamicToolsets, "readOnly", cfg.ReadOnly) + stdLogger := log.New(logOutput, stdioServerLogPrefix, 0) stdioServer.SetErrorLogger(stdLogger) if cfg.ExportTranslations { @@ -227,7 +234,7 @@ func RunStdioServer(cfg StdioServerConfig) error { in, out := io.Reader(os.Stdin), io.Writer(os.Stdout) if cfg.EnableCommandLogging { - loggedIO := mcplog.NewIOLogger(in, out, logrusLogger) + loggedIO := mcplog.NewIOLogger(in, out, logger) in, out = loggedIO, loggedIO } // enable GitHub errors in the context @@ -241,9 +248,10 @@ func RunStdioServer(cfg StdioServerConfig) error { // Wait for shutdown signal select { case <-ctx.Done(): - logrusLogger.Infof("shutting down server...") + logger.Info("shutting down server", "signal", "context done") case err := <-errC: if err != nil { + logger.Error("error running server", "error", err) return fmt.Errorf("error running server: %w", err) } } diff --git a/pkg/log/io.go b/pkg/log/io.go index de2210278..44b8dc17a 100644 --- a/pkg/log/io.go +++ b/pkg/log/io.go @@ -3,7 +3,7 @@ package log import ( "io" - log "github.com/sirupsen/logrus" + "log/slog" ) // IOLogger is a wrapper around io.Reader and io.Writer that can be used @@ -11,11 +11,11 @@ import ( type IOLogger struct { reader io.Reader writer io.Writer - logger *log.Logger + logger *slog.Logger } // NewIOLogger creates a new IOLogger instance -func NewIOLogger(r io.Reader, w io.Writer, logger *log.Logger) *IOLogger { +func NewIOLogger(r io.Reader, w io.Writer, logger *slog.Logger) *IOLogger { return &IOLogger{ reader: r, writer: w, @@ -30,7 +30,7 @@ func (l *IOLogger) Read(p []byte) (n int, err error) { } n, err = l.reader.Read(p) if n > 0 { - l.logger.Infof("[stdin]: received %d bytes: %s", n, string(p[:n])) + l.logger.Info("[stdin]: received bytes", "count", n, "data", string(p[:n])) } return n, err } @@ -40,6 +40,6 @@ func (l *IOLogger) Write(p []byte) (n int, err error) { if l.writer == nil { return 0, io.ErrClosedPipe } - l.logger.Infof("[stdout]: sending %d bytes: %s", len(p), string(p)) + l.logger.Info("[stdout]: sending bytes", "count", len(p), "data", string(p)) return l.writer.Write(p) } diff --git a/pkg/log/io_test.go b/pkg/log/io_test.go index 0d0cd8959..2661de164 100644 --- a/pkg/log/io_test.go +++ b/pkg/log/io_test.go @@ -5,7 +5,8 @@ import ( "strings" "testing" - log "github.com/sirupsen/logrus" + "log/slog" + "github.com/stretchr/testify/assert" ) @@ -17,11 +18,7 @@ func TestLoggedReadWriter(t *testing.T) { // Create logger with buffer to capture output var logBuffer bytes.Buffer - logger := log.New() - logger.SetOutput(&logBuffer) - logger.SetFormatter(&log.TextFormatter{ - DisableTimestamp: true, - }) + logger := slog.New(slog.NewTextHandler(&logBuffer, &slog.HandlerOptions{ReplaceAttr: removeTimeAttr})) lrw := NewIOLogger(reader, nil, logger) @@ -44,11 +41,7 @@ func TestLoggedReadWriter(t *testing.T) { // Create logger with buffer to capture output var logBuffer bytes.Buffer - logger := log.New() - logger.SetOutput(&logBuffer) - logger.SetFormatter(&log.TextFormatter{ - DisableTimestamp: true, - }) + logger := slog.New(slog.NewTextHandler(&logBuffer, &slog.HandlerOptions{ReplaceAttr: removeTimeAttr})) lrw := NewIOLogger(nil, &writeBuffer, logger) @@ -63,3 +56,10 @@ func TestLoggedReadWriter(t *testing.T) { assert.Contains(t, logBuffer.String(), outputData) }) } + +func removeTimeAttr(groups []string, a slog.Attr) slog.Attr { + if a.Key == slog.TimeKey && len(groups) == 0 { + return slog.Attr{} + } + return a +} diff --git a/third-party-licenses.darwin.md b/third-party-licenses.darwin.md index 6a9f895cb..2017f8132 100644 --- a/third-party-licenses.darwin.md +++ b/third-party-licenses.darwin.md @@ -26,7 +26,6 @@ Some packages may only be included on certain architectures or operating systems - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.9.0/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - - [github.com/sirupsen/logrus](https://pkg.go.dev/github.com/sirupsen/logrus) ([MIT](https://github.com/sirupsen/logrus/blob/v1.9.3/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/v0.3.0/LICENSE)) - [github.com/spf13/afero](https://pkg.go.dev/github.com/spf13/afero) ([Apache-2.0](https://github.com/spf13/afero/blob/v1.14.0/LICENSE.txt)) - [github.com/spf13/cast](https://pkg.go.dev/github.com/spf13/cast) ([MIT](https://github.com/spf13/cast/blob/v1.7.1/LICENSE)) diff --git a/third-party-licenses.linux.md b/third-party-licenses.linux.md index 6a9f895cb..2017f8132 100644 --- a/third-party-licenses.linux.md +++ b/third-party-licenses.linux.md @@ -26,7 +26,6 @@ Some packages may only be included on certain architectures or operating systems - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.9.0/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - - [github.com/sirupsen/logrus](https://pkg.go.dev/github.com/sirupsen/logrus) ([MIT](https://github.com/sirupsen/logrus/blob/v1.9.3/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/v0.3.0/LICENSE)) - [github.com/spf13/afero](https://pkg.go.dev/github.com/spf13/afero) ([Apache-2.0](https://github.com/spf13/afero/blob/v1.14.0/LICENSE.txt)) - [github.com/spf13/cast](https://pkg.go.dev/github.com/spf13/cast) ([MIT](https://github.com/spf13/cast/blob/v1.7.1/LICENSE)) diff --git a/third-party-licenses.windows.md b/third-party-licenses.windows.md index 505c2d83e..db56a248c 100644 --- a/third-party-licenses.windows.md +++ b/third-party-licenses.windows.md @@ -27,7 +27,6 @@ Some packages may only be included on certain architectures or operating systems - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.9.0/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - - [github.com/sirupsen/logrus](https://pkg.go.dev/github.com/sirupsen/logrus) ([MIT](https://github.com/sirupsen/logrus/blob/v1.9.3/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/v0.3.0/LICENSE)) - [github.com/spf13/afero](https://pkg.go.dev/github.com/spf13/afero) ([Apache-2.0](https://github.com/spf13/afero/blob/v1.14.0/LICENSE.txt)) - [github.com/spf13/cast](https://pkg.go.dev/github.com/spf13/cast) ([MIT](https://github.com/spf13/cast/blob/v1.7.1/LICENSE)) diff --git a/third-party/github.com/sirupsen/logrus/LICENSE b/third-party/github.com/sirupsen/logrus/LICENSE deleted file mode 100644 index f090cb42f..000000000 --- a/third-party/github.com/sirupsen/logrus/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Simon Eskildsen - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE.