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

Commite0bffe9

Browse files
authored
Merge pull request#15 from github/juruen/iologging
add iologger for debugging purposes
2 parentsfa0e36c +6d63777 commite0bffe9

File tree

3 files changed

+126
-3
lines changed

3 files changed

+126
-3
lines changed

‎cmd/server/main.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ package main
33
import (
44
"context"
55
"fmt"
6+
"io"
67
stdlog"log"
78
"os"
89
"os/signal"
910
"syscall"
1011

1112
"github.com/github/github-mcp-server/pkg/github"
13+
iolog"github.com/github/github-mcp-server/pkg/log"
1214
gogithub"github.com/google/go-github/v69/github"
1315
"github.com/mark3labs/mcp-go/server"
1416
log"github.com/sirupsen/logrus"
@@ -33,7 +35,8 @@ var (
3335
iferr!=nil {
3436
stdlog.Fatal("Failed to initialize logger:",err)
3537
}
36-
iferr:=runStdioServer(logger);err!=nil {
38+
logCommands:=viper.GetBool("enable-command-logging")
39+
iferr:=runStdioServer(logger,logCommands);err!=nil {
3740
stdlog.Fatal("failed to run stdio server:",err)
3841
}
3942
},
@@ -45,9 +48,11 @@ func init() {
4548

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

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

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

7277
logger:=log.New()
78+
logger.SetLevel(log.DebugLevel)
7379
logger.SetOutput(file)
7480

7581
returnlogger,nil
7682
}
7783

78-
funcrunStdioServer(logger*log.Logger)error {
84+
funcrunStdioServer(logger*log.Logger,logCommandsbool)error {
7985
// Create app context
8086
ctx,stop:=signal.NotifyContext(context.Background(),os.Interrupt,syscall.SIGTERM)
8187
deferstop()
@@ -97,7 +103,14 @@ func runStdioServer(logger *log.Logger) error {
97103
// Start listening for messages
98104
errC:=make(chanerror,1)
99105
gofunc() {
100-
errC<-stdioServer.Listen(ctx,os.Stdin,os.Stdout)
106+
in,out:=io.Reader(os.Stdin),io.Writer(os.Stdout)
107+
108+
iflogCommands {
109+
loggedIO:=iolog.NewIOLogger(in,out,logger)
110+
in,out=loggedIO,loggedIO
111+
}
112+
113+
errC<-stdioServer.Listen(ctx,in,out)
101114
}()
102115

103116
// Output github-mcp-server string

‎pkg/log/io.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package log
2+
3+
import (
4+
"io"
5+
6+
log"github.com/sirupsen/logrus"
7+
)
8+
9+
// IOLogger is a wrapper around io.Reader and io.Writer that can be used
10+
// to log the data being read and written from the underlying streams
11+
typeIOLoggerstruct {
12+
reader io.Reader
13+
writer io.Writer
14+
logger*log.Logger
15+
}
16+
17+
// NewIOLogger creates a new IOLogger instance
18+
funcNewIOLogger(r io.Reader,w io.Writer,logger*log.Logger)*IOLogger {
19+
return&IOLogger{
20+
reader:r,
21+
writer:w,
22+
logger:logger,
23+
}
24+
}
25+
26+
// Read reads data from the underlying io.Reader and logs it.
27+
func (l*IOLogger)Read(p []byte) (nint,errerror) {
28+
ifl.reader==nil {
29+
return0,io.EOF
30+
}
31+
n,err=l.reader.Read(p)
32+
ifn>0 {
33+
l.logger.Infof("[stdin]: received %d bytes: %s",n,string(p[:n]))
34+
}
35+
returnn,err
36+
}
37+
38+
// Write writes data to the underlying io.Writer and logs it.
39+
func (l*IOLogger)Write(p []byte) (nint,errerror) {
40+
ifl.writer==nil {
41+
return0,io.ErrClosedPipe
42+
}
43+
l.logger.Infof("[stdout]: sending %d bytes: %s",len(p),string(p))
44+
returnl.writer.Write(p)
45+
}

‎pkg/log/io_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package log
2+
3+
import (
4+
"bytes"
5+
"strings"
6+
"testing"
7+
8+
log"github.com/sirupsen/logrus"
9+
"github.com/stretchr/testify/assert"
10+
)
11+
12+
funcTestLoggedReadWriter(t*testing.T) {
13+
t.Run("Read method logs and passes data",func(t*testing.T) {
14+
// Setup
15+
inputData:="test input data"
16+
reader:=strings.NewReader(inputData)
17+
18+
// Create logger with buffer to capture output
19+
varlogBuffer bytes.Buffer
20+
logger:=log.New()
21+
logger.SetOutput(&logBuffer)
22+
logger.SetFormatter(&log.TextFormatter{
23+
DisableTimestamp:true,
24+
})
25+
26+
lrw:=NewIOLogger(reader,nil,logger)
27+
28+
// Test Read
29+
buf:=make([]byte,100)
30+
n,err:=lrw.Read(buf)
31+
32+
// Assertions
33+
assert.NoError(t,err)
34+
assert.Equal(t,len(inputData),n)
35+
assert.Equal(t,inputData,string(buf[:n]))
36+
assert.Contains(t,logBuffer.String(),"[stdin]")
37+
assert.Contains(t,logBuffer.String(),inputData)
38+
})
39+
40+
t.Run("Write method logs and passes data",func(t*testing.T) {
41+
// Setup
42+
outputData:="test output data"
43+
varwriteBuffer bytes.Buffer
44+
45+
// Create logger with buffer to capture output
46+
varlogBuffer bytes.Buffer
47+
logger:=log.New()
48+
logger.SetOutput(&logBuffer)
49+
logger.SetFormatter(&log.TextFormatter{
50+
DisableTimestamp:true,
51+
})
52+
53+
lrw:=NewIOLogger(nil,&writeBuffer,logger)
54+
55+
// Test Write
56+
n,err:=lrw.Write([]byte(outputData))
57+
58+
// Assertions
59+
assert.NoError(t,err)
60+
assert.Equal(t,len(outputData),n)
61+
assert.Equal(t,outputData,writeBuffer.String())
62+
assert.Contains(t,logBuffer.String(),"[stdout]")
63+
assert.Contains(t,logBuffer.String(),outputData)
64+
})
65+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp