Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

add iologger for debugging purposes#15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
juruen merged 1 commit intomainfromjuruen/iologging
Mar 18, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletionscmd/server/main.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,12 +3,14 @@ package main
import (
"context"
"fmt"
"io"
stdlog "log"
"os"
"os/signal"
"syscall"

"github.com/github/github-mcp-server/pkg/github"
iolog "github.com/github/github-mcp-server/pkg/log"
gogithub "github.com/google/go-github/v69/github"
"github.com/mark3labs/mcp-go/server"
log "github.com/sirupsen/logrus"
Expand All@@ -33,7 +35,8 @@ var (
if err != nil {
stdlog.Fatal("Failed to initialize logger:", err)
}
if err := runStdioServer(logger); err != nil {
logCommands := viper.GetBool("enable-command-logging")
if err := runStdioServer(logger, logCommands); err != nil {
stdlog.Fatal("failed to run stdio server:", err)
}
},
Expand All@@ -45,9 +48,11 @@ func init() {

// Add global flags that will be shared by all commands
rootCmd.PersistentFlags().String("log-file", "", "Path to log file")
rootCmd.PersistentFlags().Bool("enable-command-logging", false, "When enabled, the server will log all command requests and responses to the log file")

// Bind flag to viper
viper.BindPFlag("log-file", rootCmd.PersistentFlags().Lookup("log-file"))
viper.BindPFlag("enable-command-logging", rootCmd.PersistentFlags().Lookup("enable-command-logging"))

// Add subcommands
rootCmd.AddCommand(stdioCmd)
Expand All@@ -70,12 +75,13 @@ func initLogger(outPath string) (*log.Logger, error) {
}

logger := log.New()
logger.SetLevel(log.DebugLevel)
logger.SetOutput(file)

return logger, nil
}

func runStdioServer(logger *log.Logger) error {
func runStdioServer(logger *log.Logger, logCommands bool) error {
// Create app context
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer stop()
Expand All@@ -97,7 +103,14 @@ func runStdioServer(logger *log.Logger) error {
// Start listening for messages
errC := make(chan error, 1)
go func() {
errC <- stdioServer.Listen(ctx, os.Stdin, os.Stdout)
in, out := io.Reader(os.Stdin), io.Writer(os.Stdout)

if logCommands {
loggedIO := iolog.NewIOLogger(in, out, logger)
in, out = loggedIO, loggedIO
}

errC <- stdioServer.Listen(ctx, in, out)
}()

// Output github-mcp-server string
Expand Down
3 changes: 3 additions & 0 deletionsgo.mod
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,10 +9,12 @@ require (
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1
github.com/spf13/viper v1.19.0
github.com/stretchr/testify v1.9.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
)

require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
Expand All@@ -21,6 +23,7 @@ require (
github.com/magiconair/properties v1.8.7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
Expand Down
45 changes: 45 additions & 0 deletionspkg/log/io.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
package log

import (
"io"

log "github.com/sirupsen/logrus"
)

// IOLogger is a wrapper around io.Reader and io.Writer that can be used
// to log the data being read and written from the underlying streams
type IOLogger struct {
reader io.Reader
writer io.Writer
logger *log.Logger
}

// NewIOLogger creates a new IOLogger instance
func NewIOLogger(r io.Reader, w io.Writer, logger *log.Logger) *IOLogger {
return &IOLogger{
reader: r,
writer: w,
logger: logger,
}
}

// Read reads data from the underlying io.Reader and logs it.
func (l *IOLogger) Read(p []byte) (n int, err error) {
if l.reader == nil {
return 0, io.EOF
}
n, err = l.reader.Read(p)
if n > 0 {
l.logger.Infof("[stdin]: received %d bytes: %s", n, string(p[:n]))
}
return n, err
}

// Write writes data to the underlying io.Writer and logs it.
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))
return l.writer.Write(p)
}
65 changes: 65 additions & 0 deletionspkg/log/io_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
package log

import (
"bytes"
"strings"
"testing"

log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
)

func TestLoggedReadWriter(t *testing.T) {
t.Run("Read method logs and passes data", func(t *testing.T) {
// Setup
inputData := "test input data"
reader := strings.NewReader(inputData)

// Create logger with buffer to capture output
var logBuffer bytes.Buffer
logger := log.New()
logger.SetOutput(&logBuffer)
logger.SetFormatter(&log.TextFormatter{
DisableTimestamp: true,
})

lrw := NewIOLogger(reader, nil, logger)

// Test Read
buf := make([]byte, 100)
n, err := lrw.Read(buf)

// Assertions
assert.NoError(t, err)
assert.Equal(t, len(inputData), n)
assert.Equal(t, inputData, string(buf[:n]))
assert.Contains(t, logBuffer.String(), "[stdin]")
assert.Contains(t, logBuffer.String(), inputData)
})

t.Run("Write method logs and passes data", func(t *testing.T) {
// Setup
outputData := "test output data"
var writeBuffer bytes.Buffer

// Create logger with buffer to capture output
var logBuffer bytes.Buffer
logger := log.New()
logger.SetOutput(&logBuffer)
logger.SetFormatter(&log.TextFormatter{
DisableTimestamp: true,
})

lrw := NewIOLogger(nil, &writeBuffer, logger)

// Test Write
n, err := lrw.Write([]byte(outputData))

// Assertions
assert.NoError(t, err)
assert.Equal(t, len(outputData), n)
assert.Equal(t, outputData, writeBuffer.String())
assert.Contains(t, logBuffer.String(), "[stdout]")
assert.Contains(t, logBuffer.String(), outputData)
})
}

[8]ページ先頭

©2009-2025 Movatter.jp