This PR refines the next-generation proxy internals and workspace
documentation:
- Reworks internal/logger to expose clearer slog-style APIs:
- Replaces Vf/Df/Wf/Ef with Info/Debug/Warn/Error.
- Adds structured key/value log arguments.
- Adds version to every log record.
- Uses standard slog level labels (DEBUG, INFO, WARN, ERROR).
- Keeps compatibility for existing printf-style messages.
- Renames proxy configuration abstractions:
- Environment → ProxyEnvironment.
- NewEnvironment → NewProxyEnvironment.
- Regenerates/renames the counterfeiter fake to FakeProxyEnvironment.
- Updates all proxy bootstrap, load balancer, protocol, signal, debug,
and utility call sites for the new logger and
environment APIs.
- Consolidates proxy codebase navigation:
- Deletes docs/proxy/proxy-files.md.
- Moves the useful file/module map details into
.openclaw/memory/srs-codebase-map.md.
- Replaces agent instruction symlinks with explicit workspace
instruction files for Claude, Codex, and Kiro.
- Updates OpenClaw tool notes with Codex commit-prefix guidance.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
104 lines
2.1 KiB
Go
104 lines
2.1 KiB
Go
// Copyright (c) 2026 Winlin
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
package logger
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log/slog"
|
|
"os"
|
|
"strings"
|
|
|
|
"srsx/internal/version"
|
|
)
|
|
|
|
type logger interface {
|
|
Log(ctx context.Context, msg string, args ...any)
|
|
}
|
|
|
|
type loggerPlus struct {
|
|
logger *slog.Logger
|
|
level slog.Level
|
|
}
|
|
|
|
func newLoggerPlus(opts ...func(*loggerPlus)) *loggerPlus {
|
|
v := &loggerPlus{}
|
|
for _, opt := range opts {
|
|
opt(v)
|
|
}
|
|
return v
|
|
}
|
|
|
|
func (v *loggerPlus) Log(ctx context.Context, msg string, args ...any) {
|
|
attrs := []any{
|
|
"pid", os.Getpid(),
|
|
"version", version.Version(),
|
|
}
|
|
|
|
if cid := ContextID(ctx); cid != "" {
|
|
attrs = append(attrs, "cid", cid)
|
|
}
|
|
|
|
// Keep compatibility with the old *f call sites while exposing the new
|
|
// slog-style API. New code should pass structured key/value args.
|
|
if len(args) > 0 && strings.Contains(msg, "%") {
|
|
msg = fmt.Sprintf(msg, args...)
|
|
args = nil
|
|
}
|
|
attrs = append(attrs, args...)
|
|
v.logger.Log(ctx, v.level, msg, attrs...)
|
|
}
|
|
|
|
var debugLogger logger
|
|
|
|
func Debug(ctx context.Context, msg string, args ...any) {
|
|
debugLogger.Log(ctx, msg, args...)
|
|
}
|
|
|
|
var infoLogger logger
|
|
|
|
func Info(ctx context.Context, msg string, args ...any) {
|
|
infoLogger.Log(ctx, msg, args...)
|
|
}
|
|
|
|
var warnLogger logger
|
|
|
|
func Warn(ctx context.Context, msg string, args ...any) {
|
|
warnLogger.Log(ctx, msg, args...)
|
|
}
|
|
|
|
var errorLogger logger
|
|
|
|
func Error(ctx context.Context, msg string, args ...any) {
|
|
errorLogger.Log(ctx, msg, args...)
|
|
}
|
|
|
|
// newJSONLogger builds a slog.Logger that writes JSON records to w.
|
|
func newJSONLogger(w io.Writer) *slog.Logger {
|
|
h := slog.NewJSONHandler(w, &slog.HandlerOptions{
|
|
Level: slog.LevelDebug,
|
|
})
|
|
return slog.New(h)
|
|
}
|
|
|
|
func init() {
|
|
debugLogger = newLoggerPlus(func(l *loggerPlus) {
|
|
l.logger = newJSONLogger(os.Stdout)
|
|
l.level = slog.LevelDebug
|
|
})
|
|
infoLogger = newLoggerPlus(func(l *loggerPlus) {
|
|
l.logger = newJSONLogger(os.Stdout)
|
|
l.level = slog.LevelInfo
|
|
})
|
|
warnLogger = newLoggerPlus(func(l *loggerPlus) {
|
|
l.logger = newJSONLogger(os.Stderr)
|
|
l.level = slog.LevelWarn
|
|
})
|
|
errorLogger = newLoggerPlus(func(l *loggerPlus) {
|
|
l.logger = newJSONLogger(os.Stderr)
|
|
l.level = slog.LevelError
|
|
})
|
|
}
|