diff --git a/cloudotel/traceidhook.go b/cloudotel/traceidhook.go index f0084c80..f68bc770 100644 --- a/cloudotel/traceidhook.go +++ b/cloudotel/traceidhook.go @@ -14,11 +14,11 @@ const IDKey = "traceId" // TraceIDHook adds the trace ID (without the full trace resource name) to the request logger. // The trace ID can be used to filter on logs for the same trace across multiple projects. -// Experimental: May be removed in a future update. // -// Deprecated: As per https://docs.cloud.google.com/trace/docs/trace-log-integration the project specific -// trace format is now considered legacy. The new format fulfills the same need this hook -// exists in the first place so it will be removed in a future update. +// Deprecated: The cloudslog.Handler automatically injects trace fields from the OpenTelemetry +// span context into logging.googleapis.com/trace. Additionally, as per +// https://docs.cloud.google.com/trace/docs/trace-log-integration the preferred format for +// that field is now just the trace ID, making this separate hook redundant. func TraceIDHook(ctx context.Context, traceContext trace.SpanContext) context.Context { return cloudslog.With(ctx, slog.String(IDKey, traceContext.TraceID().String())) } diff --git a/cloudotel/tracemiddleware.go b/cloudotel/tracemiddleware.go index 24460f1f..3dd3d400 100644 --- a/cloudotel/tracemiddleware.go +++ b/cloudotel/tracemiddleware.go @@ -13,7 +13,7 @@ import ( gcppropagator "github.com/GoogleCloudPlatform/opentelemetry-operations-go/propagator" "go.einride.tech/cloudrunner/cloudpubsub" "go.einride.tech/cloudrunner/cloudstream" - "go.einride.tech/cloudrunner/cloudzap" + "go.einride.tech/cloudrunner/cloudzap" //nolint:staticcheck // SA1019: internal use of deprecated package pending removal "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/trace" "go.uber.org/zap" //nolint:gomodguard // legacy zap dependency for trace middleware @@ -26,8 +26,14 @@ type TraceHook func(context.Context, trace.SpanContext) context.Context // TraceMiddleware that ensures incoming traces are forwarded and included in logging. type TraceMiddleware struct { // ProjectID of the project the service is running in. + // + // Deprecated: No longer used. As per https://docs.cloud.google.com/trace/docs/trace-log-integration + // the preferred trace format is now just the trace ID, not projects/PROJECT_ID/traces/TRACE_ID. ProjectID string // TraceHook is an optional callback that gets called with the parsed trace context. + // + // Deprecated: The cloudslog.Handler automatically injects trace fields from the + // OpenTelemetry span context, making custom trace hooks for log enrichment redundant. TraceHook TraceHook // EnablePubsubTracing, disabled by default, reads trace parent from Pub/Sub message attributes. EnablePubsubTracing bool @@ -126,13 +132,17 @@ func (i *TraceMiddleware) withLogTracing(ctx context.Context, spanCtx trace.Span ctx = i.TraceHook(ctx, spanCtx) } fields := make([]zap.Field, 0, 3) + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.Trace(spanCtx.TraceID().String())) if spanCtx.SpanID().String() != "" { + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.SpanID(spanCtx.SpanID().String())) } if spanCtx.IsSampled() { + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.TraceSampled(spanCtx.IsSampled())) } + //nolint:staticcheck // SA1019: deprecated, pending removal return cloudzap.WithLoggerFields(ctx, fields...) } diff --git a/cloudrequestlog/details.go b/cloudrequestlog/details.go index 5fb78b88..36d38ce8 100644 --- a/cloudrequestlog/details.go +++ b/cloudrequestlog/details.go @@ -12,6 +12,9 @@ import ( ) // ErrorDetails creates a zap.Field that logs the gRPC error details of the provided error. +// +// Deprecated: Returns a zap.Field which ties consumers to the deprecated zap dependency. +// There is no drop-in slog replacement yet. This function will be removed in a future version. func ErrorDetails(err error) zap.Field { if err == nil { return zap.Skip() diff --git a/cloudtrace/idhook.go b/cloudtrace/idhook.go index 47354e85..973309f0 100644 --- a/cloudtrace/idhook.go +++ b/cloudtrace/idhook.go @@ -13,7 +13,11 @@ const IDKey = "traceId" // IDHook adds the trace ID (without the full trace resource name) to the request logger. // The trace ID can be used to filter on logs for the same trace across multiple projects. -// Experimental: May be removed in a future update. +// +// Deprecated: The cloudslog.Handler automatically injects trace fields from the OpenTelemetry +// span context into logging.googleapis.com/trace. Additionally, as per +// https://docs.cloud.google.com/trace/docs/trace-log-integration the preferred format for +// that field is now just the trace ID, making this separate hook redundant. func IDHook(ctx context.Context, traceContext Context) context.Context { return cloudslog.With(ctx, slog.String(IDKey, traceContext.TraceID)) } diff --git a/cloudtrace/middleware.go b/cloudtrace/middleware.go index e635c49e..f75726d6 100644 --- a/cloudtrace/middleware.go +++ b/cloudtrace/middleware.go @@ -5,17 +5,25 @@ import ( "net/http" "go.einride.tech/cloudrunner/cloudstream" - "go.einride.tech/cloudrunner/cloudzap" - "go.uber.org/zap" //nolint:gomodguard // legacy zap dependency for trace middleware + "go.einride.tech/cloudrunner/cloudzap" //nolint:staticcheck // SA1019: internal use of deprecated package pending removal + "go.uber.org/zap" //nolint:gomodguard // legacy zap dependency for trace middleware "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) // Middleware that ensures incoming traces are forwarded and included in logging. +// +// Deprecated: Use cloudotel.TraceMiddleware instead. type Middleware struct { // ProjectID of the project the service is running in. + // + // Deprecated: No longer used. As per https://docs.cloud.google.com/trace/docs/trace-log-integration + // the preferred trace format is now just the trace ID, not projects/PROJECT_ID/traces/TRACE_ID. ProjectID string // TraceHook is an optional callback that gets called with the parsed trace context. + // + // Deprecated: The cloudslog.Handler automatically injects trace fields from the + // OpenTelemetry span context, making custom trace hooks for log enrichment redundant. TraceHook func(context.Context, Context) context.Context } @@ -99,12 +107,16 @@ func (i *Middleware) withLogTracing(ctx context.Context, header string) context. ctx = i.TraceHook(ctx, traceContext) } fields := make([]zap.Field, 0, 3) + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.Trace(traceContext.TraceID)) if traceContext.SpanID != "" { + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.SpanID(traceContext.SpanID)) } if traceContext.Sampled { + //nolint:staticcheck // SA1019: deprecated, pending removal fields = append(fields, cloudzap.TraceSampled(traceContext.Sampled)) } + //nolint:staticcheck // SA1019: deprecated, pending removal return cloudzap.WithLoggerFields(ctx, fields...) } diff --git a/cloudzap/context.go b/cloudzap/context.go index 1045a449..6bf9fe26 100644 --- a/cloudzap/context.go +++ b/cloudzap/context.go @@ -9,17 +9,24 @@ import ( type loggerContextKey struct{} // WithLogger adds a logger to the current context. +// +// Deprecated: cloudrunner.Run configures the default slog logger with cloudslog.Handler. +// Use slog.InfoContext, slog.WarnContext, etc. instead of a context-based zap logger. func WithLogger(ctx context.Context, logger *zap.Logger) context.Context { return context.WithValue(ctx, loggerContextKey{}, logger) } // GetLogger returns the logger for the current context. +// +// Deprecated: Use slog.InfoContext, slog.WarnContext, etc. with the default slog logger instead. func GetLogger(ctx context.Context) (*zap.Logger, bool) { logger, ok := ctx.Value(loggerContextKey{}).(*zap.Logger) return logger, ok } // WithLoggerFields attaches structured fields to a new logger in the returned child context. +// +// Deprecated: Use cloudslog.With to attach attributes to the context instead. func WithLoggerFields(ctx context.Context, fields ...zap.Field) context.Context { logger, ok := ctx.Value(loggerContextKey{}).(*zap.Logger) if !ok { diff --git a/cloudzap/doc.go b/cloudzap/doc.go index 5240cc77..1547cb13 100644 --- a/cloudzap/doc.go +++ b/cloudzap/doc.go @@ -1,2 +1,6 @@ // Package cloudzap provides primitives for structured logging with go.uber.org/zap. +// +// Deprecated: Use log/slog with the cloudslog package instead. The cloudslog.Handler +// automatically handles trace correlation, error reporting, and Cloud Logging field +// formatting without requiring explicit middleware or field injection. package cloudzap diff --git a/cloudzap/encoderconfig.go b/cloudzap/encoderconfig.go index e467e69e..f092c444 100644 --- a/cloudzap/encoderconfig.go +++ b/cloudzap/encoderconfig.go @@ -9,6 +9,8 @@ import ( // NewEncoderConfig creates a new zapcore.EncoderConfig for structured JSON logging to Cloud Logging. // See: https://cloud.google.com/logging/docs/agent/logging/configuration#special-fields. +// +// Deprecated: Use cloudslog.NewHandler instead, which handles Cloud Logging field formatting. func NewEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ TimeKey: "time", diff --git a/cloudzap/level.go b/cloudzap/level.go index 0c016c04..5615ec8b 100644 --- a/cloudzap/level.go +++ b/cloudzap/level.go @@ -8,6 +8,8 @@ import ( // LevelToSeverity converts a zapcore.Level to its corresponding Cloud Logging severity level. // See: https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#logseverity. +// +// Deprecated: Use slog.Level directly with cloudslog.NewHandler, which maps levels automatically. func LevelToSeverity(l zapcore.Level) string { switch l { case zapcore.DebugLevel: @@ -30,6 +32,8 @@ func LevelToSeverity(l zapcore.Level) string { } // LevelToSlog converts a [zapcore.Level] to a [slog.Level]. +// +// Deprecated: Use slog.Level directly with cloudslog.LoggerConfig. func LevelToSlog(l zapcore.Level) slog.Level { switch l { case zapcore.DebugLevel: diff --git a/cloudzap/logger.go b/cloudzap/logger.go index 57e65dcd..5655240b 100644 --- a/cloudzap/logger.go +++ b/cloudzap/logger.go @@ -9,6 +9,8 @@ import ( ) // LoggerConfig configures the application logger. +// +// Deprecated: Use cloudslog.LoggerConfig instead. type LoggerConfig struct { // Development indicates if the logger should output human-readable output for development. Development bool `default:"true" onGCE:"false"` @@ -19,6 +21,8 @@ type LoggerConfig struct { } // NewLogger creates a new Logger. +// +// Deprecated: Use cloudslog.NewHandler instead. func NewLogger(config LoggerConfig) (*zap.Logger, error) { if config.Development { zapConfig := zap.NewDevelopmentConfig() diff --git a/cloudzap/middleware.go b/cloudzap/middleware.go index 898148da..746d1038 100644 --- a/cloudzap/middleware.go +++ b/cloudzap/middleware.go @@ -9,6 +9,10 @@ import ( "google.golang.org/grpc" ) +// Middleware injects a zap logger into the request context. +// +// Deprecated: The default slog logger configured by cloudrunner.Run handles logging +// without requiring middleware. Use slog.InfoContext, slog.WarnContext, etc. instead. type Middleware struct { Logger *zap.Logger } diff --git a/cloudzap/trace.go b/cloudzap/trace.go index ef8ac3ef..2bc34331 100644 --- a/cloudzap/trace.go +++ b/cloudzap/trace.go @@ -10,14 +10,26 @@ const ( traceSampledKey = "logging.googleapis.com/trace_sampled" ) +// Trace creates a zap field for the Cloud Logging trace field. +// +// Deprecated: Use log/slog with the cloudslog package instead. The cloudslog.Handler +// automatically injects trace fields from the OpenTelemetry span context. func Trace(traceID string) zap.Field { return zap.String(traceKey, traceID) } +// SpanID creates a zap field for the Cloud Logging span ID field. +// +// Deprecated: Use log/slog with the cloudslog package instead. The cloudslog.Handler +// automatically injects span ID from the OpenTelemetry span context. func SpanID(spanID string) zap.Field { return zap.String(spanIDKey, spanID) } +// TraceSampled creates a zap field for the Cloud Logging trace sampled field. +// +// Deprecated: Use log/slog with the cloudslog package instead. The cloudslog.Handler +// automatically injects trace sampled from the OpenTelemetry span context. func TraceSampled(sampled bool) zap.Field { return zap.Bool(traceSampledKey, sampled) } diff --git a/logger.go b/logger.go index 58e73325..571ee7cf 100644 --- a/logger.go +++ b/logger.go @@ -4,11 +4,15 @@ import ( "context" "go.einride.tech/cloudrunner/cloudrequestlog" - "go.einride.tech/cloudrunner/cloudzap" - "go.uber.org/zap" //nolint:gomodguard // legacy zap dependency for backwards compatibility + "go.einride.tech/cloudrunner/cloudzap" //nolint:staticcheck // SA1019: internal use of deprecated package pending removal + "go.uber.org/zap" //nolint:gomodguard // legacy zap dependency for backwards compatibility ) // Logger returns the logger for the current context. +// +// Deprecated: Use slog.InfoContext, slog.WarnContext, slog.ErrorContext, etc. instead. +// The default slog logger is configured with cloudslog.Handler which automatically +// handles trace correlation and Cloud Logging field formatting. func Logger(ctx context.Context) *zap.Logger { logger, ok := cloudzap.GetLogger(ctx) if !ok { @@ -18,6 +22,8 @@ func Logger(ctx context.Context) *zap.Logger { } // WithLoggerFields attaches structured fields to a new logger in the returned child context. +// +// Deprecated: Use cloudslog.With to attach slog attributes to the context instead. func WithLoggerFields(ctx context.Context, fields ...zap.Field) context.Context { logger, ok := cloudzap.GetLogger(ctx) if !ok { diff --git a/options.go b/options.go index 3cd42502..7c069d57 100644 --- a/options.go +++ b/options.go @@ -45,7 +45,10 @@ func WithGRPCServerOptions(grpcServerOptions ...grpc.ServerOption) Option { // WithTraceHook configures the run context with a trace hook. // -// Deprecated: use WithOtelTraceHook instead. +// Deprecated: As per https://docs.cloud.google.com/trace/docs/trace-log-integration +// the project specific cloud logging trace format is now considered legacy +// and the new format is the same as what this function was doing. Will be removed +// in a future update. func WithTraceHook(traceHook func(context.Context, cloudtrace.Context) context.Context) Option { return func(run *runContext) { run.useLegacyTracing = true diff --git a/run.go b/run.go index b861675b..236bfed4 100644 --- a/run.go +++ b/run.go @@ -20,8 +20,8 @@ import ( "go.einride.tech/cloudrunner/cloudruntime" "go.einride.tech/cloudrunner/cloudserver" "go.einride.tech/cloudrunner/cloudslog" - "go.einride.tech/cloudrunner/cloudtrace" //nolint:staticcheck // SA1019: internal use of deprecated package - "go.einride.tech/cloudrunner/cloudzap" + "go.einride.tech/cloudrunner/cloudtrace" //nolint:staticcheck // SA1019: internal use of deprecated package pending removal + "go.einride.tech/cloudrunner/cloudzap" //nolint:staticcheck // SA1019: internal use of deprecated package pending removal "google.golang.org/grpc" ) @@ -30,7 +30,7 @@ type runConfig struct { // Runtime contains runtime config. Runtime cloudruntime.Config // Logger contains logger config. - Logger cloudzap.LoggerConfig + Logger cloudzap.LoggerConfig //nolint:staticcheck // SA1019: deprecated, pending removal // Profiler contains profiler config. Profiler cloudprofiler.Config // TraceExporter contains trace exporter config. @@ -91,27 +91,27 @@ func Run(fn func(context.Context) error, options ...Option) (err error) { return nil } - run.traceMiddleware.ProjectID = run.config.Runtime.ProjectID - if run.traceMiddleware.TraceHook == nil { - run.traceMiddleware.TraceHook = cloudtrace.IDHook + run.traceMiddleware.ProjectID = run.config.Runtime.ProjectID //nolint:staticcheck // SA1019: deprecated + if run.traceMiddleware.TraceHook == nil { //nolint:staticcheck // SA1019: deprecated + run.traceMiddleware.TraceHook = cloudtrace.IDHook //nolint:staticcheck // SA1019: deprecated } - run.otelTraceMiddleware.ProjectID = run.config.Runtime.ProjectID + run.otelTraceMiddleware.ProjectID = run.config.Runtime.ProjectID //nolint:staticcheck // SA1019: deprecated run.otelTraceMiddleware.EnablePubsubTracing = run.config.Runtime.EnablePubsubTracing run.serverMiddleware.Config = run.config.Server run.requestLoggerMiddleware.Config = run.config.RequestLogger ctx = withRunContext(ctx, &run) ctx = cloudruntime.WithConfig(ctx, run.config.Runtime) - logger, err := cloudzap.NewLogger(run.config.Logger) + logger, err := cloudzap.NewLogger(run.config.Logger) //nolint:staticcheck // SA1019: deprecated, pending removal if err != nil { return fmt.Errorf("cloudrunner.Run: %w", err) } run.loggerMiddleware.Logger = logger - ctx = cloudzap.WithLogger(ctx, logger) + ctx = cloudzap.WithLogger(ctx, logger) //nolint:staticcheck // SA1019: deprecated, pending removal // Set the global default log/slog logger. slog.SetDefault(slog.New(cloudslog.NewHandler(cloudslog.LoggerConfig{ ProjectID: run.config.Runtime.ProjectID, Development: run.config.Logger.Development, - Level: cloudzap.LevelToSlog(run.config.Logger.Level), + Level: cloudzap.LevelToSlog(run.config.Logger.Level), //nolint:staticcheck // SA1019: deprecated ProtoMessageSizeLimit: run.config.RequestLogger.MessageSizeLimit, ReportErrors: run.config.Logger.ReportErrors, }))) @@ -182,12 +182,12 @@ type runContext struct { config runConfig configOptions []cloudconfig.Option grpcServerOptions []grpc.ServerOption - loggerMiddleware cloudzap.Middleware + loggerMiddleware cloudzap.Middleware //nolint:staticcheck // SA1019: deprecated, pending removal serverMiddleware cloudserver.Middleware clientMiddleware cloudclient.Middleware requestLoggerMiddleware cloudrequestlog.Middleware useLegacyTracing bool - traceMiddleware cloudtrace.Middleware + traceMiddleware cloudtrace.Middleware //nolint:staticcheck // SA1019: deprecated, pending removal otelTraceMiddleware cloudotel.TraceMiddleware securityHeadersMiddleware cloudserver.SecurityHeadersMiddleware }