logging

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Apr 10, 2023 License: Apache-2.0 Imports: 29 Imported by: 3

Documentation

Overview

Package logging contains logging related utilities.

Index

Examples

Constants

This section is empty.

Variables

View Source
var DefaultLogDir = filepath.Join(os.TempDir(), "serviceweaver", "logs")

DefaultLogDir is the default directory where Service Weaver log files are stored.

Functions

func NewTestLogger

func NewTestLogger(t testing.TB) *slog.Logger

NewTestLogger returns a new logger for tests.

func Parse

func Parse(query Query) (*cel.Ast, error)

Parse parses and type-checks a query.

func Shorten

func Shorten(s string) string

Shorten returns a short prefix of the provided string.

func ShortenComponent

func ShortenComponent(component string) string

ShortenComponent shortens the given component name to be of the format <pkg>.<IfaceType>. (Recall that the full component name is of the format <path1>/<path2>/.../<pathN>/<IfaceType>.)

func StderrLogger

func StderrLogger(opts Options) *slog.Logger

StderrLogger returns a logger that pretty prints log entries to stderr.

Types

type FileStore

type FileStore struct {
	// contains filtered or unexported fields
}

FileStore stores log entries in files.

func NewFileStore

func NewFileStore(dir string) (*FileStore, error)

NewFileStore returns a LogStore that writes files to the specified directory.

func (*FileStore) Add

func (fs *FileStore) Add(e *protos.LogEntry)

Add stores the specified log entry, assigning a timestamp to it if necessary.

func (*FileStore) Close

func (fs *FileStore) Close() error

Close closes the specified log-store, including any opened files.

type LogHandler added in v0.2.0

type LogHandler struct {
	Opts  Options                      // configures the log entries
	Write func(entry *protos.LogEntry) // called on every log entry
}

LogHandler implements a custom slog.Handler.

func (*LogHandler) Enabled added in v0.2.0

func (h *LogHandler) Enabled(context.Context, slog.Level) bool

Enabled implements the slog.Handler interface.

func (*LogHandler) Handle added in v0.2.0

func (h *LogHandler) Handle(rec slog.Record) error

Handle implements the slog.Handler interface.

func (*LogHandler) WithAttrs added in v0.2.0

func (h *LogHandler) WithAttrs(attrs []slog.Attr) slog.Handler

WithAttrs implements the slog.Handler interface.

func (*LogHandler) WithGroup added in v0.2.0

func (h *LogHandler) WithGroup(string) slog.Handler

WithGroup implements the slog.Handler interface.

TODO(rgrandl): Implement it, so the users have the same experience as slog if they decide to use WithGroup.

type Options

type Options struct {
	App        string // Service Weaver application (e.g., "todo")
	Deployment string // Service Weaver deployment (e.g., "36105c89-85b1...")
	Component  string // Service Weaver component (e.g., "Todo")
	Weavelet   string // Service Weaver weavelet id (e.g., "36105c89-85b1...")

	// Pre-assigned attributes. These will be attached to each log entry
	// generated by the logger. This slice will never be appended to in place.
	Attrs []string
}

Options configures the log entries produced by a logger.

type PrettyPrinter

type PrettyPrinter struct {
	// contains filtered or unexported fields
}

PrettyPrinter pretty prints log entries. You can safely use a PrettyPrinter from multiple goroutines.

func NewPrettyPrinter

func NewPrettyPrinter(color bool) *PrettyPrinter

NewPrettyPrinter returns a new PrettyPrinter. If color is true, the pretty printer colorizes its output using ANSII escape codes.

func (*PrettyPrinter) Format

func (pp *PrettyPrinter) Format(e *protos.LogEntry) string

Format formats a log entry as a single line of human-readable text. Here are some examples of what pretty printed log entries look like:

I0921 10:07:31.733831 distributor 076cb5f1 distributor.go:164] Registering versions...
I0921 10:07:31.759352 distributor 076cb5f1 anneal.go:155     ] Deploying versions...
I0921 10:07:31.759696 manager     076cb5f1 manager.go:125    ] Starting versions...
I0921 10:07:31.836563 manager     076cb5f1 manager.go:137    ] Success starting...
I0921 10:07:31.849647 distributor 076cb5f1 anneal.go:184     ] Successfully deployed...
I0921 10:07:31.862637 distributor 076cb5f1 distributor.go:169] Successfully registered...
I0921 10:07:31.862754 controller  076cb5f1 anneal.go:331     ] Successfully distributed...

type Query

type Query = string

Query is a filter for log entries.

Syntax

Queries are written using a subset of the CEL language 1. Thus, every syntactically valid query is also a syntactically valid CEL program. Specifically, a query is a CEL program over the following fields:

  • app: string
  • version: string
  • full_version: string
  • component: string
  • full_component: string
  • node: string
  • full_node: string
  • time: timestamp
  • level: string
  • source: string
  • msg: string
  • attrs: map[string]string

A query is restricted to:

  • boolean algebra (!, &&, ||),
  • equalities and inequalities (==, !=, <, <=, >, >=),
  • the string operations "contains" and "matches",
  • map indexing (attrs["foo"]) and membership ("foo" in attrs), and
  • constant strings, timestamps, and ints.

All equalities and inequalities must look like `app == "todo"` or `attrs["foo"] == "bar"`; i.e. a field or attribute on the left and a constant on the right.

Semantics

Queries have the same semantics as CEL programs except for one small exception. An attribute expression like `attrs["foo"]` has an implicit membership test `"foo" in attrs`. For example, the query

attrs["foo"] == "bar"

is evaluated like the CEL program

"foo" in attrs && attrs["foo"] == "bar"

TODO(mwhittaker): Expand the set of valid queries. For example, we can allow more constant expressions on the right hand side of a comparison. We can also allow fields on the right and constants on the left.

type Reader

type Reader interface {
	// Read returns the next log entry, or io.EOF when there are no more log
	// entries. Calling Read on a closed reader will return an error. If a
	// non-nil error is returned, the returned entry is guaranteed to be nil.
	Read(context.Context) (*protos.LogEntry, error)

	// Close closes the Reader. Close can safely be called multiple times.
	Close()
}

Reader is a log entry iterator. A Reader is not thread-safe; its methods cannot be called concurrently.

Example
ctx := context.Background()
reader := getLogReader()
defer reader.Close()
for {
	entry, err := reader.Read(ctx)
	if errors.Is(err, io.EOF) {
		// No more log entries.
		return
	} else if err != nil {
		fmt.Fprintln(os.Stderr, err)
		return
	}
	fmt.Println(entry)
}
Output:

type Source

type Source interface {
	// Query returns a log entry reader.
	//
	// Log entries produced by a single component replica are guaranteed to be
	// returned in increasing timestamp order, but log entries across component
	// replicas are interleaved in timestamp order only on a best-effort basis.
	//
	// If follow is true, then the returned reader follows logs like `tail -f`.
	// Otherwise, log entries that are created during an executing query may or
	// may not be returned. Similarly, the returned reader does not return old
	// log entries that have been garbage collected.
	Query(ctx context.Context, q Query, follow bool) (Reader, error)
}

Source is a log source. You can use a source to cat and follow logs, filtering log entries using a query. A Source can safely be used concurrently from multiple goroutines.

func FileSource

func FileSource(dir string) Source

FileSource returns a new Source that reads logs from files saved by a FileStore.

Jump to

Keyboard shortcuts

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