phos

package module
v0.0.3 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: GPL-3.0 Imports: 13 Imported by: 0

README

Phos

The Phos library is meant to be a simple-to-use, difficult-to-misuse tracing library.

Quickstart

import "github.com/johan-st/phos"

ctx, span := phos.NewSpan(ctx, "handler",
    phos.WithAttrs(slog.String("route", "/api")),
    phos.WithKind(phos.Server),
)
defer span.End()

phos.Attrs(ctx, slog.String("user", id))
phos.Event(ctx, "cache.hit")
err := doSomething()
if err != nil {
    phos.Fail(ctx, err, slog.String("phase", "handler"))
    return
}

Set a default exporter (optional), or use WithExporter on the request context:

restore := phos.SetExporter(myExporter)
defer restore()

ctx = phos.WithExporter(ctx, myExporter)

Before process exit, start draining and wait until Phos is closed:

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

phos.DrainAndClose(ctx)
phos.WaitForClosed()

While draining, new root spans return no-op spans, but child spans on still-open local parents are still allowed. If the drain context expires first, Phos closes the remaining open span trees bottom-up and records the event "phos.Shutdown timeout reached" on affected spans.

HTTP propagation (W3C Trace Context):

phos.InjectTraceContext(ctx, phos.HTTPHeaderCarrier{Header: resp.Header()})
ctx = phos.ExtractTraceContext(ctx, phos.HTTPHeaderCarrier{Header: req.Header})

References

https://www.w3.org/TR/trace-context

Documentation

Overview

Package phos provides lightweight request-scoped tracing with optional export, W3C Trace Context propagation, and CLI-oriented trace rendering.

Spans are stored in context: use NewSpan and call Span.End exactly once per span; Span.End is idempotent. While a span is open, Span.Attrs, Span.Event, and Span.Error are safe for concurrent use; after Span.End, further mutations are ignored. Span.Fail records a terminal error and ends the span.

Use WithExporter to attach an Exporter to a context (e.g. per request). Use SetExporter for a process-wide default when no context exporter is set. SetExporter uses an internal read-write lock so it is safe to call concurrently with NewSpan and span completion.

Once a span ends it is no longer returned by SpanFromContext. Helper calls such as Attrs, Event, Error, and Fail therefore become no-ops when a context only carries an ended span.

Call DrainAndClose to start shutdown admission control. While draining, new root spans return no-op spans but child spans on still-open local parents are still allowed. Call WaitForClosed before process exit to wait until all open local span trees have closed.

Propagation helpers InjectTraceContext and ExtractTraceContext work with any Carrier implementation, such as HTTPHeaderCarrier or MapCarrier.

Index

Examples

Constants

View Source
const (
	TraceParentHeader = "traceparent"
	TraceStateHeader  = "tracestate"
)

Variables

This section is empty.

Functions

func Attrs

func Attrs(ctx context.Context, attrs ...slog.Attr)

Attrs records attributes in the span. Attributes are key-value pairs that describe the span.

func DrainAndClose added in v0.0.3

func DrainAndClose(ctx context.Context)

DrainAndClose begins shutdown admission control without blocking.

Once draining has started, new root spans return noop spans while child spans on still-open local parents are allowed. If ctx is canceled before all open roots end naturally, Phos closes the remaining trees bottom-up and records the event "phos.Shutdown timeout reached" on affected spans.

func Error

func Error(ctx context.Context, err error, attrs ...slog.Attr)

Error records an error in the span. An error is a terminal, timestamped occurrence in the span.

func Event

func Event(ctx context.Context, name string, attrs ...slog.Attr)

Event records an event in the span. An event is a non-terminal, timestamped occurrence in the span.

func ExtractTraceContext

func ExtractTraceContext(ctx context.Context, carrier Carrier) context.Context

func Fail

func Fail(ctx context.Context, err error, attrs ...slog.Attr)

Fail records a terminal error and ends the span.

func InjectTraceContext

func InjectTraceContext(ctx context.Context, carrier Carrier)

func RenderTrace

func RenderTrace(spans []Snapshot) string

RenderTrace renders one trace as a CLI-friendly timeline.

func RenderTraces

func RenderTraces(spans []Snapshot) string

RenderTraces renders all spans grouped by trace in a CLI-friendly timeline.

func SetExporter

func SetExporter(exp Exporter) func()

SetExporter replaces the package-level exporter and returns a restore function for callers that need to put the previous exporter back. It is safe for concurrent use with NewSpan and span completion.

func WaitForClosed added in v0.0.3

func WaitForClosed()

WaitForClosed blocks until Phos reaches the closed state.

func WithExporter

func WithExporter(ctx context.Context, exp Exporter) context.Context

WithExporter attaches an exporter to the given context. If the exporter is nil, a no-op exporter is attached.

Types

type Carrier

type Carrier interface {
	Get(key string) string
	Set(key string, value string)
	Keys() []string
}

type Exporter

type Exporter interface {
	Export(snapshot Snapshot)
}

Exporter receives completed span snapshots.

Export must be safe for concurrent use. Phos considers export complete when Export returns, so exporters should avoid blocking indefinitely. Any exporter-specific buffering or shutdown coordination is owned by the exporter implementation, not Phos.

type HTTPHeaderCarrier

type HTTPHeaderCarrier struct {
	Header http.Header
}

func (HTTPHeaderCarrier) Get

func (c HTTPHeaderCarrier) Get(key string) string

func (HTTPHeaderCarrier) Keys

func (c HTTPHeaderCarrier) Keys() []string

func (HTTPHeaderCarrier) Set

func (c HTTPHeaderCarrier) Set(key string, value string)

type InMemExportImporter

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

func NewInMemExportImporter

func NewInMemExportImporter() *InMemExportImporter

func (*InMemExportImporter) Export

func (e *InMemExportImporter) Export(data Snapshot)

func (*InMemExportImporter) Spans added in v0.0.3

func (e *InMemExportImporter) Spans() map[string]Snapshot

Spans returns a deep copy of all exported spans keyed by span ID.

type MapCarrier

type MapCarrier map[string]string

func (MapCarrier) Get

func (c MapCarrier) Get(key string) string

func (MapCarrier) Keys

func (c MapCarrier) Keys() []string

func (MapCarrier) Set

func (c MapCarrier) Set(key string, value string)

type NoopExporter

type NoopExporter struct{}

NoopExporter is an exporter that does nothing.

func (*NoopExporter) Export

func (e *NoopExporter) Export(_ Snapshot)

Export is a no-op.

type Snapshot

type Snapshot struct {
	ID        string          `json:"id"`
	Name      string          `json:"name"`
	ParentID  string          `json:"parent_id"`
	TraceID   string          `json:"trace_id"`
	TimeStart time.Time       `json:"time_start"`
	TimeEnd   time.Time       `json:"time_end"`
	Kind      SpanKind        `json:"kind"`
	Failed    bool            `json:"failed"`
	Attrs     []slog.Attr     `json:"attrs"`
	Links     []SnapshotLink  `json:"links"`
	Events    []SnapshotEvent `json:"events"`
	Errors    []SnapshotError `json:"errors"`
}

func (Snapshot) MarshalJSON added in v0.0.3

func (s Snapshot) MarshalJSON() ([]byte, error)

type SnapshotError

type SnapshotError struct {
	Err   error       `json:"-"`
	Attrs []slog.Attr `json:"attrs"`
}

func (SnapshotError) MarshalJSON

func (e SnapshotError) MarshalJSON() ([]byte, error)

type SnapshotEvent

type SnapshotEvent struct {
	Time  time.Time   `json:"time"`
	Name  string      `json:"name"`
	Attrs []slog.Attr `json:"attrs"`
}

func (SnapshotEvent) MarshalJSON added in v0.0.3

func (e SnapshotEvent) MarshalJSON() ([]byte, error)
type SnapshotLink struct {
	TraceID string      `json:"trace_id"`
	SpanID  string      `json:"span_id"`
	Attrs   []slog.Attr `json:"attrs"`
}

func (SnapshotLink) MarshalJSON added in v0.0.3

func (l SnapshotLink) MarshalJSON() ([]byte, error)

type Span

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

func NewSpan

func NewSpan(ctx context.Context, name string, opts ...SpanOption) (context.Context, *Span)
Example
package main

import (
	"context"
	"log/slog"

	"github.com/johan-st/phos"
)

func main() {
	ctx := context.Background()
	ctx, span := phos.NewSpan(ctx, "request", phos.WithAttrs(slog.String("method", "GET")))
	defer span.End()

	phos.Attrs(ctx, slog.String("user", "alice"))
	phos.Event(ctx, "authorized")

}

func SpanFromContext added in v0.0.3

func SpanFromContext(ctx context.Context) *Span

SpanFromContext returns the active span for the given context. If the context does not have an active span, nil is returned.

func (*Span) Attrs

func (s *Span) Attrs(attrs ...slog.Attr)

func (*Span) End

func (s *Span) End()

func (*Span) Error

func (s *Span) Error(err error, attrs ...slog.Attr)

func (*Span) Event

func (s *Span) Event(name string, attrs ...slog.Attr)

func (*Span) Fail

func (s *Span) Fail(err error, attrs ...slog.Attr)

func (*Span) Snapshot added in v0.0.3

func (s *Span) Snapshot() Snapshot

type SpanKind added in v0.0.3

type SpanKind int
const (
	Internal SpanKind = iota
	Server
	Client
	Producer
	Consumer
)

func (SpanKind) MarshalJSON added in v0.0.3

func (k SpanKind) MarshalJSON() ([]byte, error)

func (SpanKind) String added in v0.0.3

func (k SpanKind) String() string

type SpanOption added in v0.0.3

type SpanOption func(*spanConfig)

func WithAttrs added in v0.0.3

func WithAttrs(attrs ...slog.Attr) SpanOption

func WithKind added in v0.0.3

func WithKind(kind SpanKind) SpanOption
func WithLink(traceID, spanID string, attrs ...slog.Attr) SpanOption

type TraceParent

type TraceParent struct {
	Version string
	TraceID string
	Parent  string
	Flags   string
}

func ParseTraceParent

func ParseTraceParent(v string) (TraceParent, error)

func (TraceParent) String

func (t TraceParent) String() string

Directories

Path Synopsis
cmd
phos command

Jump to

Keyboard shortcuts

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