top | item 45220981

(no title)

aleksi | 5 months ago

Well, is fmt.Stringer supported? The result might surprise you:

  req := expvar.NewInt("requests")
  req.Add(1)
  
  attr := slog.Any("requests", req)
  
  slog.New(slog.NewTextHandler(os.Stderr, nil)).Info("text", attr)
  slog.New(slog.NewJSONHandler(os.Stderr, nil)).Info("json", attr)
This code produces

  time=2025-09-12T13:15:42.125+02:00 level=INFO msg=text requests=1
  {"time":"2025-09-12T13:15:42.125555+02:00","level":"INFO","msg":"json","requests":{}}
So the code that uses slog but does not know what handler will be used can't rely on it lazily calling the `String() string` method: half of the standard handlers do that, half don't.

discuss

order

0x696C6961|5 months ago

If you need more control, you can create a wrapper type that implements `slog.LogValuer`

    type StringerValue struct {
        fmt.Stringer
    }

    func (v StringerValue) LogValue() slog.Value {
        return slog.StringValue(v.String())
    }

Usage example:

    slog.Any("requests", StringerValue{req})

There might be a case for making the expvar types implement `slog.LogValuer` directly.

aleksi|5 months ago

So clearly not all values are supported.

And I know that I can create a wrapper for unsupported types. My problem is exactly that – I don't know what types are supported. Is error supported, for example? Should I create a wrapper for it? And, as a handler author, should I support it directly or not?

Philip-J-Fry|5 months ago

That seems to work as expected?

The output of data is handled by the handler. Such behaviour is clearly outlined in the documentation by the JSONHandler. I wouldn't expect a JSONHandler to use Stringer. I'd expect it to use the existing JSON interfaces, which it does.

I'd expect the Text handler to use TextMarshaller. Which it does. Or Stringer, which it does implicitly via fmt.Sprintf.

aleksi|5 months ago

My problem with that is that it makes it impossible to use slog logger safely without knowing what handler is being used. Which kind of defeats the purpose of defining the common structured logging interface.