Skip to content

Conversation

fosmjo
Copy link

@fosmjo fosmjo commented Jul 24, 2024

No description provided.

@Acconut
Copy link
Member

Acconut commented Jul 24, 2024

Thank you for this PR! I am supportive of this change, but we have to defer merging it until the next major release since this is a breaking change. At the time of writing, there is no concrete plan for the next major release.

@Acconut Acconut added the breaking change Backwards compatibility breaking change label Jul 24, 2024
@Acconut Acconut added this to the v3 milestone Sep 18, 2024
@Acconut Acconut mentioned this pull request Oct 8, 2024
@pcfreak30
Copy link
Contributor

pcfreak30 commented Jul 16, 2025

Im dropping this here as it might help someone and I have gotten rid of needing a fork of tusd due to it. I hope it helps someone as you can't really downgrade zap logger and so your in a rock/hard place.

func loggerToSlog(logger *zap.Logger) *slog.Logger {
	// Create a bridge
	bridge := NewSlogBridge(logger)

	// Create a handler that wraps the new slog handler but presents the old interface
	oldHandler := bridge.Handler()

	// Create an old-style logger with this handler
	return slog.New(oldHandler)
}
package main

import (
	"context"
	"go.uber.org/zap/exp/zapslog"
	"golang.org/x/exp/slog"
	newSlog "log/slog"
)

// SlogBridge bridges between the old and new slog versions
type SlogBridge struct {
	logger *newSlog.Logger // new slog.Logger
}

// NewSlogBridge creates a new bridge between slog versions
func NewSlogBridge(logger *zap.Logger) *SlogBridge {
	// Convert zap logger to new slog.Logger
	newSlogger := newSlog.New(zapslog.NewHandler(logger.Core()))
	return &SlogBridge{
		logger: newSlogger,
	}
}

// Handler returns a handler compatible with the old slog version
func (b *SlogBridge) Handler() slog.Handler {
	return &handlerBridge{newHandler: b.logger.Handler()}
}

func convertAttr(attr slog.Attr) newSlog.Attr {
	switch attr.Value.Kind() {
	case slog.KindBool:
		return newSlog.Bool(attr.Key, attr.Value.Bool())
	case slog.KindDuration:
		return newSlog.Duration(attr.Key, attr.Value.Duration())
	case slog.KindFloat64:
		return newSlog.Float64(attr.Key, attr.Value.Float64())
	case slog.KindInt64:
		return newSlog.Int64(attr.Key, attr.Value.Int64())
	case slog.KindString:
		return newSlog.String(attr.Key, attr.Value.String())
	case slog.KindTime:
		return newSlog.Time(attr.Key, attr.Value.Time())
	case slog.KindUint64:
		return newSlog.Uint64(attr.Key, attr.Value.Uint64())
	case slog.KindGroup:
		group := attr.Value.Group()
		attrs := make([]any, len(group))
		for i, a := range group {
			attrs[i] = convertAttr(a)
		}
		return newSlog.Group(attr.Key, attrs...)
	case slog.KindLogValuer:
		return convertAttr(slog.Attr{
			Key:   attr.Key,
			Value: attr.Value.Resolve(),
		})
	default:
		return newSlog.Any(attr.Key, attr.Value.Any())
	}
}

// handlerBridge implements the old slog.Handler interface using the new slog.Handler
type handlerBridge struct {
	newHandler newSlog.Handler
}

func (h *handlerBridge) Enabled(ctx context.Context, level slog.Level) bool {
	return h.newHandler.Enabled(ctx, newSlog.Level(level))
}

func (h *handlerBridge) Handle(ctx context.Context, r slog.Record) error {
	// Convert old Record to new Record
	newRecord := newSlog.NewRecord(
		r.Time,
		newSlog.Level(r.Level),
		r.Message,
		r.PC,
	)
	r.Attrs(func(attr slog.Attr) bool {
		newRecord.Add(convertAttr(attr))
		return true
	})
	return h.newHandler.Handle(ctx, newRecord)
}

func (h *handlerBridge) WithAttrs(attrs []slog.Attr) slog.Handler {
	newAttrs := make([]newSlog.Attr, len(attrs))
	for i, attr := range attrs {
		newAttrs[i] = convertAttr(attr)
	}
	return &handlerBridge{newHandler: h.newHandler.WithAttrs(newAttrs)}
}

func (h *handlerBridge) WithGroup(name string) slog.Handler {
	return &handlerBridge{newHandler: h.newHandler.WithGroup(name)}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Backwards compatibility breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants