@@ -13,6 +13,8 @@ import (
1313 "slices"
1414 "sync"
1515 "time"
16+
17+ "golang.org/x/time/rate"
1618)
1719
1820// Logging levels.
@@ -83,10 +85,10 @@ type LoggingHandler struct {
8385 // Ensures that the buffer reset is atomic with the write (see Handle).
8486 // A pointer so that clones share the mutex. See
8587 // https://github.com/golang/example/blob/master/slog-handler-guide/README.md#getting-the-mutex-right.
86- mu * sync.Mutex
87- lastMessageSent time. Time // for rate-limiting
88- buf * bytes.Buffer
89- handler slog.Handler
88+ mu * sync.Mutex
89+ limiter * rate. Limiter // for rate-limiting
90+ buf * bytes.Buffer
91+ handler slog.Handler
9092}
9193
9294// ensureLogger returns l if non-nil, otherwise a discard logger.
@@ -118,6 +120,9 @@ func NewLoggingHandler(ss *ServerSession, opts *LoggingHandlerOptions) *LoggingH
118120 }
119121 if opts != nil {
120122 lh .opts = * opts
123+ if opts .MinInterval > 0 {
124+ lh .limiter = rate .NewLimiter (rate .Every (opts .MinInterval ), 1 )
125+ }
121126 }
122127 return lh
123128}
@@ -157,11 +162,7 @@ func (h *LoggingHandler) Handle(ctx context.Context, r slog.Record) error {
157162
158163func (h * LoggingHandler ) handle (ctx context.Context , r slog.Record ) error {
159164 // Observe the rate limit.
160- // TODO(jba): use golang.org/x/time/rate.
161- h .mu .Lock ()
162- skip := time .Since (h .lastMessageSent ) < h .opts .MinInterval
163- h .mu .Unlock ()
164- if skip {
165+ if h .limiter != nil && ! h .limiter .Allow () {
165166 return nil
166167 }
167168
@@ -184,10 +185,6 @@ func (h *LoggingHandler) handle(ctx context.Context, r slog.Record) error {
184185 return err
185186 }
186187
187- h .mu .Lock ()
188- h .lastMessageSent = time .Now ()
189- h .mu .Unlock ()
190-
191188 params := & LoggingMessageParams {
192189 Logger : h .opts .LoggerName ,
193190 Level : slogLevelToMCP (r .Level ),
0 commit comments