feat: gamemaster

This commit is contained in:
Ilia Denisov
2026-05-03 07:59:03 +02:00
committed by GitHub
parent a7cee15115
commit 3e2622757e
229 changed files with 41521 additions and 1098 deletions
+43
View File
@@ -0,0 +1,43 @@
package logging
import "context"
// requestIDKey is the unexported context key under which the HTTP layer
// stores the request id propagated from the X-Request-Id header.
type requestIDKey struct{}
// WithRequestID returns a child context that carries requestID. An empty
// requestID returns ctx unchanged so callers do not have to branch.
func WithRequestID(ctx context.Context, requestID string) context.Context {
if ctx == nil || requestID == "" {
return ctx
}
return context.WithValue(ctx, requestIDKey{}, requestID)
}
// RequestIDFromContext returns the request id stored on ctx by
// WithRequestID, or an empty string when no value is present.
func RequestIDFromContext(ctx context.Context) string {
if ctx == nil {
return ""
}
value, _ := ctx.Value(requestIDKey{}).(string)
return value
}
// ContextAttrs returns slog key-value pairs that materialise the frozen
// `gamemaster/README.md` §Observability log fields `request_id`,
// `trace_id`, and `span_id` from ctx. Pairs whose value is empty are
// omitted so logs stay tight.
func ContextAttrs(ctx context.Context) []any {
if ctx == nil {
return nil
}
var attrs []any
if requestID := RequestIDFromContext(ctx); requestID != "" {
attrs = append(attrs, "request_id", requestID)
}
attrs = append(attrs, TraceAttrsFromContext(ctx)...)
return attrs
}
+45
View File
@@ -0,0 +1,45 @@
// Package logging configures the Game Master process logger and provides
// context-aware helpers for trace fields.
package logging
import (
"context"
"fmt"
"log/slog"
"os"
"strings"
"go.opentelemetry.io/otel/trace"
)
// New constructs the process-wide JSON logger from level.
func New(level string) (*slog.Logger, error) {
var slogLevel slog.Level
if err := slogLevel.UnmarshalText([]byte(strings.TrimSpace(level))); err != nil {
return nil, fmt.Errorf("build logger: %w", err)
}
return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
Level: slogLevel,
})), nil
}
// TraceAttrsFromContext returns slog key-value pairs for the active
// OpenTelemetry span when ctx carries a valid span context. The keys match
// the frozen `gamemaster/README.md` §Observability log fields `trace_id`
// and `span_id`.
func TraceAttrsFromContext(ctx context.Context) []any {
if ctx == nil {
return nil
}
spanContext := trace.SpanContextFromContext(ctx)
if !spanContext.IsValid() {
return nil
}
return []any{
"trace_id", spanContext.TraceID().String(),
"span_id", spanContext.SpanID().String(),
}
}