-
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
Comments -
2026 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
-
wireguard kubernetes
18 August, 2025What if you built your kubernetes cluster with wireguard/tailscale from the ground up.
- Api servers are always private except for wireguard port
- Use a side car for each api server pod https://tailscale.com/kb/1185/kubernetes#sample-sidecar. Drop a tailnet secret in ccp.
- like api server vnet integration pods show up in your tailnet/overlay even if they have no nodes. Can be hit directly with endpoint slices
- No konnectivity proxy ingress and egress goes direct to api server pods
- Could still have a internal load balancer for legacy nodes but ideally want none of that.
- Rest of ccp does not need to be in tailnet but could be
- Head scale lets you join the cluster. (can we use certs to verify this public key is from a baremetal node? We can’t be the ones giving them a secret?)
- Nodes are locked down except for wireguard port (use the top of rack)
- node wireguard nic get a /24 and we use a bridge to hand out pod ips. (could use cilium or soemthign else if you want net pols but don’t need it for ipam)
- node ip should be just the first ip.
- Do you need boostrapping tokens? If you’re on the network is that enough? Alot of tls becomes uncessary
- Can tailscale provide the load balancer service? https://tailscale.com/kb/1223/funnel to get things to kubenet.
Can we prove this out by 1) sidecarring api servers on a standalone 2) Creating a BYO CNI cluster 3) Adding a Demonset to VM nodes that boostraps tailscale and gets a /24 + brige plugin 4) Create a script that adds us to tailscale then gets a bootstrap token and joins api server from some random home machine?
Comments - Api servers are always private except for wireguard port
OLDER
- 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 gpts
- 17 Dec december tiger
- 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 single dad weekend with the boys
- 23 Apr Tri tip marinade.
- 23 Apr Sage Hot Italian Sausge Pasta
- 16 Apr Yakima spring break
- 16 Mar Concert formulas
- 14 Mar No Direction Home
- 14 Mar General Electric
- 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
- 05 May Derby Fun 2022
- 11 Jan New PC build
- 05 Jan Pan Sauce
- 28 Oct Vaccine Maximalism
- 28 Oct Rodgers covid
- 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 Straight to Jubel
- 01 Oct Sad Country Drinking songs
- 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 Carne Asada Street Tacos
- 26 May Beer pickles
- 25 May Life Lost
- 16 May Won't do what you tell me IPA
- 03 May This time is different
- 03 May Cheesy Shrimp and Grits
- 29 Mar Corona Testing in a distributed republic.
- 09 Mar Morbid Corona Bet
- 26 Feb Fullers ESBish
- 17 Feb Lego Collection
- 17 Feb GigaPilsner
- 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 Dusseldorf Alt
- 24 Aug Cheif Curmudgeon
- 30 Jun A CI/CD we can believe in
- 25 Jun Productivity
- 13 Jun Classic Pine
- 05 Jun My Interview question
- 11 May Dunkel Schokolad
- 05 May Derby Fun 2
- 11 Apr Horse Power per Dollar
- 30 Mar Darkly Mild
- 30 Mar West Wheat
- 28 Mar Less Code
- 17 Mar China Future
- 04 Mar Street Corn
- 04 Mar Injera (Tibsi)
- 04 Mar Chicken Noodle Soup
- 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
- 05 Dec Grapefruit Fish
- 29 Nov Ur Marzen
- 23 Nov Things we should tax.
- 18 Nov Panaoramas
- 18 Nov Brewie Repair
- 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 Norse fun
- 02 Jun Brewie Review
- 28 May Choosing Life
- 27 May Pence and Mens Lizard brains.
- 22 May Lesser Known Romans
- 05 May Derby Fun
- 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 Wintana's Winter Wonder beer.
- 01 Jan Willy's IPA
- 01 Jan Unfiltered Liberty
- 01 Jan Straight Jubel
- 01 Jan Straight Jubel (2011-11-23 version)
- 01 Jan Samoan Pale Ale.
- 01 Jan Riesen betrunken reden Lion
- 01 Jan Riesen betrunken reden Lion (2011-10-05 version)
- 01 Jan Original Sin Stout
- 01 Jan Old Hooker
- 01 Jan Old Crotchety
- 01 Jan Low Brau
- 01 Jan Low Brau 2.
- 01 Jan Ignoble India pale ale
- 01 Jan Hoptarded
- 01 Jan Harry Henderson's Oak Aged Stout
- 01 Jan Exiled Scot
- 01 Jan Bust me bagpipes scotch.
- 01 Jan American Dunkelweizen
- 05 Sep Honeymoon
- 25 Dec Why we goto church

feed