Logging: structured slog messages throughout, and WithLogger options so callers choose the logger
Log messages are lower-case event names with their details as key/value
attributes ("error" for errors), in place of formatted strings.
Loggable package take a WithLogger option as part of their "New*" call,
defaulting to slog.Default(). Each tags its lines with its `component`.
Some debug loggers print directly rather than using slog when in
terminal logging mode.
This commit is contained in:
1 parent
0b5fde9563
commit
043e307663
49 files changed
+598
-248
No files matched your search
@@ -33,15 +33,38 @@ type Server struct {
|
||||
hub *websocket.Hub
|
||||
}
|
||||
|
||||
// Option configures a Server.
|
||||
type Option func(*Server)
|
||||
|
||||
// WithLogger makes the server log to logger instead of slog.Default().
|
||||
func WithLogger(logger *slog.Logger) Option {
|
||||
return func(s *Server) {
|
||||
s.log = logger
|
||||
}
|
||||
}
|
||||
|
||||
// New builds a server for hub's plain TCP clients. Run starts it; it shuts
|
||||
// hub down when it stops, so hub should not be shared with another server.
|
||||
// Push to hub to reach the server's clients.
|
||||
func New(conf *config.JSCServer, hub *websocket.Hub, log *slog.Logger) *Server {
|
||||
return &Server{
|
||||
// Push to hub to reach the server's clients. It logs to slog.Default()
|
||||
// unless given WithLogger.
|
||||
func New(conf *config.JSCServer, hub *websocket.Hub, opts ...Option) *Server {
|
||||
server := &Server{
|
||||
conf: conf,
|
||||
log: log,
|
||||
hub: hub,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(server)
|
||||
}
|
||||
return server
|
||||
}
|
||||
|
||||
// logger returns the logger the server logs to, tagged with its component.
|
||||
func (s *Server) logger() *slog.Logger {
|
||||
log := s.log
|
||||
if log == nil {
|
||||
log = slog.Default()
|
||||
}
|
||||
return log.With("component", "tcp")
|
||||
}
|
||||
|
||||
// Run listens on the configured host and port and serves plain TCP clients
|
||||
@@ -71,14 +94,14 @@ func (s *Server) serve(ctx context.Context, listen net.Listener) error {
|
||||
})
|
||||
defer stop()
|
||||
|
||||
s.log.Info("listening", "addr", listen.Addr().String())
|
||||
s.logger().Info("listening", "addr", listen.Addr().String())
|
||||
acceptErr := s.accept(ctx, connCtx, listen)
|
||||
if ctx.Err() != nil {
|
||||
acceptErr = nil // cancelling ctx is how the server is stopped
|
||||
}
|
||||
listen.Close() //nolint:errcheck,gosec // closed already when ctx was cancelled
|
||||
|
||||
s.log.Info("shutting down")
|
||||
s.logger().Info("shutting down")
|
||||
shutdownCtx := context.Background()
|
||||
if s.conf.Timeouts.ShutdownTimeout > 0 {
|
||||
var cancel context.CancelFunc
|
||||
@@ -117,7 +140,7 @@ func (s *Server) accept(
|
||||
|
||||
// Back off and retry e.g. when out of file descriptors.
|
||||
delay = min(max(2*delay, 5*time.Millisecond), time.Second)
|
||||
s.log.Warn("tcp accept failed", "error", err, "retry_in", delay)
|
||||
s.logger().Warn("tcp accept failed", "error", err, "retry_in", delay)
|
||||
|
||||
select {
|
||||
case <-time.After(delay):
|
||||
@@ -131,7 +154,7 @@ func (s *Server) accept(
|
||||
if limiter != nil {
|
||||
ip := remoteIP(newConn)
|
||||
if allowed, _ := limiter.Allow(ip); !allowed {
|
||||
s.log.Warn("tcp connection rate limited", "ip", ip)
|
||||
s.logger().Warn("tcp connection rate limited", "ip", ip)
|
||||
go reject(newConn, "rate limited")
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ func testConf(mutate func(*config.JSCServer)) *config.JSCServer {
|
||||
|
||||
// newServer returns a server for conf with its own hub.
|
||||
func newServer(conf *config.JSCServer) (*Server, *websocket.Hub) {
|
||||
h := websocket.NewHub(conf.WebSocket, discardLog)
|
||||
return New(conf, h, discardLog), h
|
||||
h := websocket.NewHub(conf.WebSocket, websocket.WithLogger(discardLog))
|
||||
return New(conf, h, WithLogger(discardLog)), h
|
||||
}
|
||||
|
||||
// startServer serves on a local port, returning the server's hub, its
|
||||
|
||||
Reference in new issue
Block a user