add ln post (#237)
This commit is contained in:
parent
025dded376
commit
a6db9b65de
|
@ -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.
|
Loading…
Reference in New Issue