aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristine Dodrill <me@christine.website>2020-10-17 23:30:25 -0400
committerGitHub <noreply@github.com>2020-10-17 23:30:25 -0400
commita6db9b65dec79d2f447469ab600ba02b0cfa9be9 (patch)
tree9aa0d03ae76d9f2c7faf513a3446feb31719fcc9
parent025dded3767c4ae58f595fc45653f6774588f895 (diff)
downloadxesite-a6db9b65dec79d2f447469ab600ba02b0cfa9be9.tar.xz
xesite-a6db9b65dec79d2f447469ab600ba02b0cfa9be9.zip
add ln post (#237)
-rw-r--r--blog/ln-the-natural-logger-2020-10-17.markdown100
1 files changed, 100 insertions, 0 deletions
diff --git a/blog/ln-the-natural-logger-2020-10-17.markdown b/blog/ln-the-natural-logger-2020-10-17.markdown
new file mode 100644
index 0000000..abfae6b
--- /dev/null
+++ b/blog/ln-the-natural-logger-2020-10-17.markdown
@@ -0,0 +1,100 @@
+---
+title: "ln - The Natural Log Function"
+date: 2020-10-17
+tags:
+ - golang
+ - go
+---
+
+# ln - The Natural Log Function
+
+One of the most essential things in software is a good interface for logging
+data to places. Logging is a surprisingly hard problem and there are many
+approaches to doing it. This time, we're going to talk about my favorite logging
+library in Go that uses my favorite function I've ever written in Go.
+
+Today we're talking about [ln](https://github.com/Xe/ln), the natural log
+function. ln works with key value pairs and logs them to somewhere. By default
+it logs things to standard out. Here is how you use it:
+
+```go
+package main
+
+import (
+ "context"
+
+ "within.website/ln"
+)
+
+func main() {
+ ctx := context.Background()
+ ln.Log(ctx, ln.Fmt("hello %s", "world"), ln.F{"demo": "usage"})
+}
+```
+
+ln works with key value pairs called [F](https://godoc.org/within.website/ln#F).
+This type allows you to log just about _anything_ you want, including custom
+data types with an [Fer](https://godoc.org/within.website/ln#Fer). This will let
+you annotate your data types so that you can automatically extract the important
+information into your logs while automatically filtering out passwords or other
+secret data. Here's an example:
+
+```go
+type User struct {
+ ID int
+ Username string
+ Password []byte
+}
+
+func (u User) F() ln.F {
+ return ln.F{
+ "user_id": u.ID,
+ "user_name": u.Username,
+ }
+}
+```
+
+Then if you create that user somehow, you can log the ID and username without
+logging the password on accident:
+
+```go
+var theDude User = abides()
+
+ln.Log(ctx, ln.Info("created new user"), theDude)
+```
+
+This will create a log line that looks something like this:
+
+```
+level=info msg="created new user" user_name="The Dude" user_id=1337
+```
+
+[You can also put values in contexts! See <a
+href="https://github.com/Xe/ln/blob/master/ex/http.go#L21">here</a> for more
+detail on how this works.](conversation://Mara/hacker)
+
+The way this is all glued together is that F itself is an Fer, meaning that the
+Log/Error functions take a variadic set of Fers. This is where my favorite Go
+function comes into play, it is the implementation of the Fer interface for F.
+Here is that function verbatim:
+
+```go
+// F makes F an Fer
+func (f F) F() F {
+ return f
+}
+```
+
+I love how this function looks like some kind of abstract art. This function
+holds this library together.
+
+If you end up using ln for your projects in the future, please let me know what
+your experience is like. I would love to make this library the best it can
+possibly be. It is not a nanosecond scale zero allocation library (I think those
+kind of things are a bit of a waste of time, because most of the time your
+logging library is NOT going to be your bottleneck), but it is designed to have
+very usable defaults and solve the problem good enough that you shouldn't need
+to care. There are a few useful tools in the
+[ex](https://godoc.org/within.website/ln/ex) package nested in ln. The biggest
+thing is the HTTP middleware, which has saved me a lot of effort when writing
+web services in Go.