pl

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

pl Go Reference codecov experimental

pl tails and pretty-prints JSONL logs produced by zap (the zap.NewProductionConfig JSON encoder, as used by go-faster/sdk).

It also understands OpenTelemetry log records in the logs data model JSON form (the Severity/Body/Attributes/Scope shape emitted by go-faster/sdk's console log exporter). Both formats are detected per line and rendered the same way, so a stream that mixes them — as oteldb emits — reads uniformly:

  • Body becomes the message, the instrumentation Scope name the logger;
  • SeverityText (or the numeric SeverityNumber) becomes the level;
  • Attributes become key=value fields, with the code.* ones folded into the caller and exception.message/exception.stacktrace shown as the error;
  • non-zero TraceID/SpanID are surfaced as trace_id/span_id for correlation, while resource attributes and zero ids are omitted as noise.

When go-faster/sdk's zctx runs in otelzap mode (zctx.WithOpenTelemetryZap), zap lines carry the trace correlation as a reflected ctx object rather than flat fields. pl flattens that object so span_id/trace_id (and any other context-scoped members) read as ordinary fields — identical to zctx's default mode — again dropping all-zero ids.

Install

go install github.com/go-faster/pl/cmd/pl@latest

Usage

Pipe logs in:

my-service 2>&1 | pl

Follow a file (tail -f style):

pl -f service.log

Read a file once and exit:

pl service.log

Output is colorized when stdout is a terminal. Non-JSON lines are passed through untouched, so mixed output is safe. Disable colors with --no-color or by setting NO_COLOR.

Isolate a single trace with --trace-id; it keeps only lines whose trace_id matches (case-insensitively), whichever format they arrive in — a flat zap trace_id, zctx's reflected ctx object, or an OTEL TraceID:

pl --trace-id a30d8906e0e519424360816608e11188 service.log
Flags
-f, --follow         follow the file, waiting for new lines (like tail -f)
    --no-color       disable ANSI colors
    --no-time        omit timestamps from the output
    --level          minimum level to display (debug|info|warn|error)
    --trace-id       show only lines whose trace_id matches (case-insensitive)
    --timezone       convert timestamps to this timezone (e.g. UTC, Local, America/New_York)
    --otel-resource  include OpenTelemetry resource attributes (OTEL logs only)
    --otel-func      include the function name in the caller (OTEL logs only)

--otel-resource prints the resource attributes on their own indented lines below the entry, in a color distinct from the inline fields, so they stay readable instead of crowding the message:

20:02:07.563 I app ClickHouse disabled (oteldb/app.go:114)
	host.name=198f0b5f008f
	service.name=oteldb
	telemetry.sdk.version=1.44.0
Level styles

Levels render as a single colored character by default — D, I, W, E, and C for dpanic/panic/fatal:

03:00:00.099 D verbose detail
03:00:00.200 I metrics Starting attempt=3
03:00:00.299 W disk low note="needs attention"
03:00:00.400 E boom err=x
03:00:00.500 C giving up

When used as a library, override per-level label and color via Formatter.LevelStyles (levels absent from the map keep their defaults):

f := &pl.Formatter{
    Color: true,
    LevelStyles: map[zapcore.Level]pl.LevelStyle{
        zapcore.WarnLevel: {Label: "WARN", Color: "\033[33m"},
    },
}

Documentation

Overview

Package pl tails and pretty-prints JSONL logs produced by zap (the zap.NewProductionConfig JSON encoder used by go-faster/sdk) as well as OpenTelemetry log records in the logs data model JSON form. Each line is detected and normalized onto a shared rendering path, so a stream mixing the two formats reads uniformly.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DefaultLevelStyles

func DefaultLevelStyles() map[zapcore.Level]LevelStyle

DefaultLevelStyles returns the built-in level styles: a single-character label and a color per level (D/I/W/E, and C for dpanic/panic/fatal).

Types

type Formatter

type Formatter struct {
	// Color enables ANSI colors in the output.
	Color bool
	// MinLevel, when set, drops lines below this level.
	MinLevel zapcore.Level
	// TraceID, when set, drops every line whose trace_id does not match,
	// isolating a single trace across a stream. The comparison is
	// case-insensitive and matches whether the id came from a zap trace_id
	// field, zctx's reflected ctx object, or an OTEL TraceID. Lines that carry
	// no trace_id — including non-JSON passthrough lines — are dropped.
	TraceID string
	// TimeFormat is the layout for the timestamp. Defaults to "15:04:05.000".
	TimeFormat string
	// NoTime omits the timestamp from the output entirely.
	NoTime bool
	// Location, when set, converts timestamps to this timezone before
	// formatting. A nil Location uses the timestamp's own location.
	Location *time.Location
	// LevelStyles overrides how levels are rendered. Levels absent from the map
	// fall back to DefaultLevelStyles; a nil map uses the defaults entirely.
	LevelStyles map[zapcore.Level]LevelStyle
	// OTELResource includes OpenTelemetry resource attributes (service.name,
	// host.name, ...) as fields. They are dropped by default because they repeat
	// identically on every line. Only affects OTEL log records.
	OTELResource bool
	// OTELFunc includes the function name (the code.function.name attribute) in
	// the caller of OpenTelemetry log records. Dropped by default as it
	// duplicates the source location.
	OTELFunc bool
	// contains filtered or unexported fields
}

Formatter renders a single zap JSON log line into a human-readable form.

func (*Formatter) Follow

func (f *Formatter) Follow(ctx context.Context, path string, w io.Writer) error

Follow tails the file at path (like tail -f), formatting new lines as they are appended. It handles truncation/rotation by reopening when the file shrinks. It blocks until ctx is canceled.

func (*Formatter) Format

func (f *Formatter) Format(line []byte) (out string, ok bool)

Format parses a single JSON log line and returns its pretty representation.

The returned bool reports whether the line should be printed. Lines that are not valid zap JSON are returned unchanged (and ok is true) so that mixed output is preserved. Lines below MinLevel are dropped (ok is false).

func (*Formatter) Process

func (f *Formatter) Process(ctx context.Context, r io.Reader, w io.Writer) error

Process reads newline-delimited logs from r, formats each line with f and writes the result to w until r is exhausted or ctx is canceled.

func (*Formatter) SetMinLevel

func (f *Formatter) SetMinLevel(l zapcore.Level)

SetMinLevel sets the minimum level to display.

type LevelStyle

type LevelStyle struct {
	// Label is the text shown for the level (e.g. "I" for info).
	Label string
	// Color is the ANSI escape sequence applied to the label. Empty means no
	// color. Ignored when the Formatter has Color disabled.
	Color string
}

LevelStyle controls how a single log level is rendered.

Directories

Path Synopsis
cmd
pl command
Command pl tails and pretty-prints JSONL logs produced by zap (the zap.NewProductionConfig JSON encoder used by go-faster/sdk).
Command pl tails and pretty-prints JSONL logs produced by zap (the zap.NewProductionConfig JSON encoder used by go-faster/sdk).

Jump to

Keyboard shortcuts

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