Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

slog: structured logging #1

Closed
wants to merge 11 commits into from
13 changes: 0 additions & 13 deletions .travis.yml

This file was deleted.

36 changes: 36 additions & 0 deletions attrs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package btclog

import (
"context"
"encoding/hex"
"log/slog"
)

// Hex is a convenience function for a hex-encoded log attributes.
func Hex(key string, value []byte) slog.Attr {
h := hex.EncodeToString(value)

return slog.String(key, h)
}

type attrsKey struct{}

// WithCtx returns a copy of the context with which the logging attributes are
// associated.
//
// Usage:
//
// ctx := log.WithCtx(ctx, "height", 1234)
// ...
// log.Info(ctx, "Height processed") // Will contain attribute: height=1234
func WithCtx(ctx context.Context, attrs ...any) context.Context {
return context.WithValue(ctx, attrsKey{}, mergeAttrs(ctx, attrs))
}

// mergeAttrs returns the attributes from the context merged with the provided attributes.
func mergeAttrs(ctx context.Context, attrs []any) []any {
resp, _ := ctx.Value(attrsKey{}).([]any) // We know the type.
resp = append(resp, attrs...)

return resp
}
51 changes: 51 additions & 0 deletions buffer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Adapted from go/src/log/slog/internal/buffer.go

package btclog

import "sync"

type buffer []byte

// bufferPool defines a concurrent safe free list of byte slices used to provide
// temporary buffers for formatting log messages prior to outputting them.
var bufferPool = sync.Pool{
New: func() any {
b := make([]byte, 0, 1024)
return (*buffer)(&b)
},
}

// newBuffer returns a byte slice from the free list. A new buffer is allocated
// if there are not any available on the free list. The returned byte slice
// should be returned to the fee list by using the recycleBuffer function when
// the caller is done with it.
func newBuffer() *buffer {
return bufferPool.Get().(*buffer)
}

// free puts the provided byte slice, which should have been obtained via the
// newBuffer function, back on the free list.
func (b *buffer) free() {
// To reduce peak allocation, return only smaller buffers to the pool.
const maxBufferSize = 16 << 10
if cap(*b) <= maxBufferSize {
*b = (*b)[:0]
bufferPool.Put(b)
}
}

func (b *buffer) writeByte(p byte) {
*b = append(*b, p)
}

func (b *buffer) writeBytes(p []byte) {
*b = append(*b, p...)
}

func (b *buffer) writeString(s string) {
*b = append(*b, s...)
}
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/lightninglabs/btclog

go 1.21
Loading