bug

package module
v0.0.0-...-18436b7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2021 License: MIT Imports: 10 Imported by: 0

README

bug, a logger

bug is a simple & slow structured logger for context-aware Go programs. It writes JSONL to stdout by default. To log an event, call bug.Log. Use bug.With to add tags to the context. Use bug.WithSpan to measure the duration of a task.

package main

import (
  "context"
  "time"

  "github.com/jbarnette/bug"
)

func main() {
  ctx := context.Background()

  // log an event
  bug.Log(ctx, "hello",
    bug.Tag("world", true))

  // add shared tags
  ctx = bug.With(ctx,
    bug.Tag("shared", "value"))

  // measure elapsed time
  ctx, cancel := bug.WithSpan(ctx, "leaving")
  defer cancel()

  time.Sleep(1 * time.Second)
  bug.Log(ctx, "goodbye")
}
{"at":"hello","world":true}
{"at":"goodbye","shared":"value"}
{"at":"leaving","elapsed":1.00043627,"shared":"value"}

Error tags

bug.Error tags an event with the error's message and type. It ignores nil values.

bug.Log(ctx, "accept",
  bug.Error(err))
{"at":"accept","error":true,"error.message":"accept tcp 127.0.0.1:32827: use of closed network connection","error.type":"*net.OpError"}

Logfmt

You can filter bug's output through jbarnette/logfmt for a more humane view.

Documentation

Overview

Package bug provides a simple & slow structured logger. It writes JSONL to stdout.

Index

Examples

Constants

This section is empty.

Variables

View Source
var Now func() time.Time = time.Now

Now is called by Measure to measure elapsed time.

Functions

func HTTPPanicMiddleware

func HTTPPanicMiddleware(next http.Handler) http.Handler

HTTPPanicMiddleware returns an HTTP handler that recovers from a panic caused by the next handler. It logs a panic event including the value, type, and source location. After logging, the handler tries to respond with an internal server error.

func HTTPResponseMiddleware

func HTTPResponseMiddleware(next http.Handler) http.Handler

HTTPResponseMiddleware returns an HTTP handler that logs the response.

func Log

func Log(ctx context.Context, at string, taggers ...Tagger)

Log calls Write to write a log event.

Example
package main

import (
	"context"
	"os"

	"github.com/jbarnette/bug"
)

func main() {
	bug.Write = bug.JSONL(os.Stdout)
	ctx := context.Background()

	bug.Log(ctx, "hello",
		bug.Tag("greeting", true),
		bug.Tag("subject", "world"))

}
Output:

{"at":"hello","greeting":true,"subject":"world"}

func With

func With(parent context.Context, taggers ...Tagger) context.Context

With returns a copy of parent with additional taggers.

Example
package main

import (
	"context"
	"os"

	"github.com/jbarnette/bug"
)

func main() {
	bug.Write = bug.JSONL(os.Stdout)
	ctx := context.Background()

	bug.Log(ctx, "with-background")

	ctx = bug.With(ctx,
		bug.Tag("outer", "value"))

	bug.Log(ctx, "with-outer")

	ctx = bug.With(ctx,
		bug.Tag("inner", "value"))

	bug.Log(ctx, "with-inner",
		bug.Tag("inline", "value"))

}
Output:

{"at":"with-background"}
{"at":"with-outer","outer":"value"}
{"at":"with-inner","inline":"value","inner":"value","outer":"value"}

Types

type Span

type Span struct {
	context.Context
	// contains filtered or unexported fields
}

A Span is a context that covers the lifetime of an operation.

func SpanFrom

func SpanFrom(ctx context.Context) *Span

SpanFrom returns a pointer to the current span, if there is one.

func WithSpan

func WithSpan(parent context.Context, at string) (*Span, context.CancelFunc)

WithSpan returns a copy of parent with a CancelFunc that calls Log. The CancelFunc adds an "elapsed" tag, calculated by subtracting Now from the time when Span was called.

Example
package main

import (
	"context"
	"os"
	"time"

	"github.com/jbarnette/bug"
)

func main() {
	bug.Write = bug.JSONL(os.Stdout)
	ctx := context.Background()

	t := &time.Time{}
	bug.Now = func() time.Time { return *t }

	span, cancel := bug.WithSpan(ctx, "outside")
	defer cancel()

	span.Append(bug.Tag("outer", "value"))
	bug.Log(span, "inside", bug.Tag("inner", "value"))

	*t = t.Add(1 * time.Minute)

}
Output:

{"at":"inside","inner":"value"}
{"at":"outside","elapsed":60,"outer":"value"}

func (*Span) Append

func (s *Span) Append(taggers ...Tagger)

Append appends the provided taggers to the span's taggers.

func (*Span) Value

func (s *Span) Value(key interface{}) interface{}

Value implements context.Context with a special case to support SpanFrom.

type Tagger

type Tagger func(tag func(key string, value any))

A Tagger is a generator function for log event tags.

func Error

func Error(err error) Tagger

Error returns a tagger for the provided error. If the error is non-nil, the tagger generates error=true, error.message, and error.type tags.

Example
package main

import (
	"context"
	"errors"
	"os"

	"github.com/jbarnette/bug"
)

func main() {
	bug.Write = bug.JSONL(os.Stdout)
	ctx := context.Background()

	bug.Log(ctx, "no-boom",
		bug.Error(nil))

	err := errors.New("kaboom")

	bug.Log(ctx, "boom",
		bug.Error(err))

}
Output:

{"at":"no-boom"}
{"at":"boom","error":true,"error.message":"kaboom","error.type":"*errors.errorString"}

func Tag

func Tag(key string, value any) Tagger

Tag returns a tagger for the provided key and value. Pass it to Log or With.

type Writer

type Writer func(ctx context.Context, at string, tagger Tagger)

A Writer is a function that generates and writes a log event.

var Write Writer = JSONL(os.Stdout)

Write is called by Log to actually log an event.

func JSONL

func JSONL(w io.Writer) Writer

JSONL returns a log writer that writes JSON lines to w.

Example
package main

import (
	"context"
	"os"

	"github.com/jbarnette/bug"
)

type stringer struct{ string }

func (s stringer) String() string {
	return s.string
}

func main() {
	bug.Write = bug.JSONL(os.Stdout)
	ctx := context.Background()

	bug.Log(ctx, "func",
		bug.Tag("value", func() {}))

	bug.Log(ctx, "chan",
		bug.Tag("value", make(chan struct{})))

	bug.Log(ctx, "stringer",
		bug.Tag("value", stringer{"value"}))

}
Output:

{"at":"func","value":"💥"}
{"at":"chan","value":"💥"}
{"at":"stringer","value":"value"}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL