slog is neat
23 October, 2025Why did golang get a new logging framework after ~10 years?
Existing “log” package
- It’s like printf but there’s a timestamp!
- I can call Fatal and Panic; I guess that’s nice in main.
log.Println("Hello, 世界") log.Printf("I will see you in %s\n", time.Hour) log.Fatal("Oh no it's all gone wrong")2009/11/10 23:00:00 Hello, 世界 2009/11/10 23:00:00 I will see you in 1h0m0s 2009/11/10 23:00:00 Oh no it's all gone wrong- There is SetOutput; let’s come back to this later.
- I can get a default logger, but I can’t set a default logger.
What should libraries do?
This approach is pretty great if you’re in main.go, but what if you’re writing a package for reuse?
Should libraries log at all?
- Well, I can pass up errors (wrap them if you’re extra cool!).
- What about that thing that seems wrong but I’m suppressing? I don’t want to break compatibilities, but I’m pretty sure this is wrong.
- https://github.com/Azure/eno/pull/532
How do I get the logger?
- Use a package-level variable or function?
- Pass it everywhere and save it as a member?
- Shove it onto context?
- I have seen all of these approaches.
How do I log respectfully without over-logging?
What if I want to customize my log format?
- JSON or binary
- Coloring or emoji ✅
What about X
- zap and logrus are pretty neat. They introduced level, structure, sinks, and a lot of the stuff I am going to talk about below.
- But if I’m writing a library, how do I know what interface to get/log to?
- I have seen several instances where logging adapters are regularly rewritten, usually losing something each time.
- Sometimes it’s nice to just have the standard library.
Enter Slog
- There are package- and type-level log functions.
- There is a high-level interface you can implement behind (handlers).
- It includes text and JSON implementations.
- You can set the default! (Claim: just use the slog.Info/Error methods instead of passing loggers around most of the time.)
Levels
- Throw all your junk into debug! Main.go can set level and toss it.
- Indecisive? Warn away!
- Make up your own log levels and go crazy.
slog.Debug("Hello, 世界") slog.Info("I will see you in ", "time", time.Hour) slog.Warn("It's getting hot in here") slog.Error("Nuts", "error", fmt.Errorf("next time gadget")) slog.Log(context.TODO(), slog.Level(10), "more important than an error"2009/11/10 23:00:00 INFO I will see you in time=1h0m0s 2009/11/10 23:00:00 WARN It's getting hot in here 2009/11/10 23:00:00 ERROR Nuts error="next time gadget" 2009/11/10 23:00:00 ERROR+2 more important than an errorStructure
- String parsing stinks because we have Kusto and lots of other fancy databases!
- Request IDs, other tracing items, latencies as durations, and general metadata all live happily here.
- Attrs have lots of nice built-in types, and there are groups (I have not used groups).
- You can set attributes globally on the default or a particular log instance with With/WithAttrs.
slog.With("author", "pmiller") slog.Info("I will see you in ", "time", time.Hour, slog.Duration("strongtypedtime", time.Minute), slog.Float64("pi", math.Pi), slog.Group("plane", "make", "boeing", "model", "737")) attrs := []slog.Attr{ slog.String("author", "jsonpaul"), slog.String("program", "playground"), } handler := slog.NewJSONHandler(os.Stdout, nil).WithAttrs(attrs) slog.SetDefault(slog.New(handler)) slog.Info("I will see you in ", "time", time.Hour, slog.Duration("strongtypedtime", time.Minute), slog.Float64("pi", math.Pi), slog.Group("plane", "make", "boeing", "model", "737"))2009/11/10 23:00:00 INFO I will see you in time=1h0m0s strongtypedtime=1m0s pi=3.141592653589793 plane.make=boeing plane.model=737 {"time":"2009-11-10T23:00:00Z","level":"INFO","msg":"I will see you in ","author":"jsonpaul","program":"playground","time":3600000000000,"strongtypedtime":60000000000,"pi":3.141592653589793,"plane":{"make":"boeing","model":"737"}}Putting things on context?
- Okay, what if I want to add attributes that everything below me in the call stack can use? ChatGPT
- I can stick them on the context, but then the code I am calling has to pull them out.
- There is an InfoContext and equivalent for each helper.
- I didn’t find a great solution for this unless you control the handler too.
- Then you can use https://github.com/PumpkinSeed/slog-context. Example blog
- Written by someone named PumpkinSeed, so it must be good. I kind of wanted a standard library way to do it, though.
Handlers!
- The fools gave us an interface: Handle(context.Context, Record) error
- Maybe you don’t want JSON; maybe you want BSON or Thrift or whatever compact nonsense.
- Maybe you want to forward records to Kusto, Blob storage, Kafka, or Service Bus.
- You can do whatever you want!
- Sometimes you might just want to do an io.Writer, but then you lose per-record control.
- My Azure append blob example.
- [Started as a handler](https://github.com/paulgmiller/careme/blob/8621cce4cd5f240d881a0bf4e22cb26c281c8e8e/internal/logsink/appendblob.go
- Hit an interesting deadlock
- Went to a writer much simpler but regret it because now I might split log records
Awesome slog
- Lots more stuff here
- Want to log tests to console but put JSON somewhere else? slog-multi!
- Want to log directly to Teams? (WHY!) Here’s a forwarder. Maybe Datadog or Kafka make more sense.
- Miss Logrus? There’s an adapter
Comments2026 hikes
21 October, 2025What are we doing next year
- knox creek/ Throp mountain
- Finish the wonderland
- Gem Lake
- Cascade pass
- Freemont lookout
- Storm king mountain
Test doubles in golang
10 October, 2025type Doer interface { Do() (int,error) } type Dummy struct {} func (d Dummy) (int,error) { panic("im a dummy") } type Stub struct {} func (s Stub) (int, error) { return 5, nil } type Spy struct { count int } func (s Spy) Do (int, err) { s.count++ return 5, nil } func (s Spy) Count() int { return s.count} type Fake struct { Value int Errror error } func (f Fake) Do() (int, err) { return f.Value, f.Error }Mocks are evil. Don’t use mocks.
Comments
OLDER
- 18 Aug wireguard kubernetes
- 15 Aug kids are alright
- 09 Aug Chanterelle and Corn Chowder with Basil
- 08 Aug herbfarm
- 02 Aug Cocoa-Cajun Flank Steak Marinade
- 26 Jul enchantments
- 12 Jul dirty harry's balcony
- 05 Jul mailbox
- 10 Jun bandera fathers day 2025
- 29 May beer
- 28 May memorial day
- 13 Apr baseball
- 11 Apr maui
- 02 Mar Ski 2025 (Alpental and Summit East)
- 01 Mar Habenero Red Cabbage Coleslaw
- 15 Feb Palm springs
- 17 Jan Chats vs Channels
- 25 Dec Cancun
- 20 Dec Release Bets
- 25 Nov Vashon
- 16 Nov Kubecon SLC 2024
- 28 Oct Last Hike of 2024
- 01 Sep Labor Day
- 19 Aug Mt. St. Helens
- 04 Aug Bandera/Seafair
- 21 Jul Counter Programming
- 16 Jul Bets and Debts
- 01 Jul Chelan/Leavenworth
- 15 Jun Trout lake
- 03 May Derby Fun 2024
- 21 Apr Houston
- 15 Apr Evictions KEP
- 30 Mar Last Day of Skiing
- 02 Mar Cosmos db and sql
- 25 Feb Whistler
- 02 Feb utils packages
- 29 Dec Christmas Cruise
- 17 Dec december tiger
- 17 Dec gpts
- 07 Oct mt granite 2
- 14 Sep Art institue of chicago
- 13 Sep Snow Lake
- 29 Aug lake cresent
- 20 Aug granite mountain
- 16 Aug prosser/red mountain
- 15 Aug lake cresent plan
- 06 Aug rimrock
- 15 Jul mt washington
- 06 Jul Chelan and 4th of July
- 17 Jun rainy fathers day
- 07 Jun memeorial day hiking
- 24 May IPA Stack Rank
- 15 May Eritrea Partry
- 07 May west tiger 2 shit show
- 03 May 2023 derby
- 23 Apr Sage Hot Italian Sausge Pasta
- 23 Apr single dad weekend with the boys
- 23 Apr Tri tip marinade.
- 16 Apr Yakima spring break
- 16 Mar Concert formulas
- 14 Mar General Electric
- 14 Mar No Direction Home
- 23 Feb irrational beliefs
- 15 Feb Oahu West side february
- 21 Jan Bad User Flows
- 20 Jan miss universe costumes
- 09 Dec chatgpt designs kured.
- 19 Nov wierd dream
- 22 Oct Kulturekampf
- 08 Aug Benji Pack list
- 17 Jun Microsoft Teams ui is broken
- 11 Jan New PC build
- 05 Jan Pan Sauce
- 28 Oct Rodgers covid
- 28 Oct Vaccine Maximalism
- 26 Oct Project shed
- 15 Aug Summer stout
- 09 Jul Windows Arm
- 06 Jul Balloon Buns
- 20 May Corporate Training
- 27 Mar Betty Crocker Chocolate Chip Cookies
- 07 Feb Distributed Twitter.
- 01 Feb Backwards ESB Kit
- 10 Jan Wrestling stories.
- 08 Jan Bourbon
- 12 Dec Ranger accesories
- 01 Oct Sad Country Drinking songs
- 01 Oct Straight to Jubel
- 05 Sep Conversations with Benji
- 29 Jul Xml is a Joke
- 04 Jul Garage brewery improvments
- 30 Jun Reiben Betrunken Lowe II
- 23 Jun Citrabomination
- 26 May Beer pickles
- 26 May Carne Asada Street Tacos
- 25 May Life Lost
- 16 May Won't do what you tell me IPA
- 03 May Cheesy Shrimp and Grits
- 03 May This time is different
- 29 Mar Corona Testing in a distributed republic.
- 09 Mar Morbid Corona Bet
- 26 Feb Fullers ESBish
- 17 Feb GigaPilsner
- 17 Feb Lego Collection
- 14 Feb Reset Pull Request signoff
- 31 Jan Bitcoin Selfdriving Bet
- 14 Jan Golang thoughts
- 05 Jan Why Skiing
- 23 Dec Bolognese
- 05 Dec Oatmeal Stout
- 03 Nov To Test Drive.
- 24 Aug Cheif Curmudgeon
- 24 Aug Dusseldorf Alt
- 30 Jun A CI/CD we can believe in
- 25 Jun Productivity
- 13 Jun Classic Pine
- 11 Apr Horse Power per Dollar
- 30 Mar Darkly Mild
- 30 Mar West Wheat
- 17 Mar China Future
- 04 Mar Chicken Noodle Soup
- 04 Mar Injera (Tibsi)
- 04 Mar Street Corn
- 01 Mar 747 rail gun
- 14 Feb A man for all seasons
- 13 Feb Ramayana and women
- 08 Feb Wintana Wine
- 26 Jan Flying Kolsch
- 10 Jan Netlify and blog thoughts
- 01 Jan Lip reading
- 27 Dec Pivo Clone (christmas justice)
- 17 Dec Brewing water
- 07 Dec Rasberry Brew
- 29 Nov Ur Marzen
- 23 Nov Things we should tax.
- 18 Nov Brewie Repair
- 18 Nov Panaoramas
- 20 Oct Liberty Belles
- 15 Sep The Wreck Porter
- 11 Aug California Dunkel
- 04 Jul No Hard Feelings ESB
- 10 Jun Franks wheat
- 02 Jun Brewie Review
- 28 May Choosing Life
- 27 May Pence and Mens Lizard brains.
- 22 May Lesser Known Romans
- 26 Apr Cowboy Morality
- 22 Apr Diogenes. Original Troll
- 21 Apr Finish the wonderland
- 12 Apr Real Blockchain
- 11 Apr I-90 Summits
- 10 Apr PCT Pack list
- 09 Apr Zelda
- 08 Apr sci-fi stack rank
- 07 Apr Why a blog?
- 01 Apr Catholic Libertarianism
- 11 Feb My Father
- 01 Jan American Dunkelweizen
- 01 Jan Bust me bagpipes scotch.
- 01 Jan Exiled Scot
- 01 Jan Harry Henderson's Oak Aged Stout
- 01 Jan Hoptarded
- 01 Jan Ignoble India pale ale
- 01 Jan Low Brau
- 01 Jan Low Brau 2.
- 01 Jan Old Crotchety
- 01 Jan Old Hooker
- 01 Jan Original Sin Stout
- 01 Jan Riesen betrunken reden Lion
- 01 Jan Riesen betrunken reden Lion (2011-10-05 version)
- 01 Jan Samoan Pale Ale.
- 01 Jan Straight Jubel
- 01 Jan Straight Jubel (2011-11-23 version)
- 01 Jan Unfiltered Liberty
- 01 Jan Willy's IPA
- 01 Jan Wintana's Winter Wonder beer.
- 05 Sep Honeymoon
- 25 Dec Why we goto church
- 01 Jan About
- 01 Jan album
- 01 Jan Derby Fun
- 01 Jan Derby Fun 2
- 01 Jan Derby Fun 2022
- 01 Jan Dunkel Schokolad
- 01 Jan Grapefruit Fish
- 01 Jan Less Code
- 01 Jan My Interview question
- 01 Jan Norse fun

feed