reporting

package
v0.0.63 Latest Latest
Warning

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

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

Documentation

Overview

Package reporting is the single source of the four PLAN-17 report shapes — event, log, metrics, transcript-upload — published over NATS. Both entry points use it: the standalone `ape event`/`log`/`metrics`/ `transcript` commands and the PTY runners at finalize, so a supervised run and a self-reporting agent emit byte-compatible payloads on the same taxonomy (docs/reference/events.md).

Unlike the fire-and-forget eventing publisher, reporting publishes SYNCHRONOUSLY and surfaces failures: a publish rejected by the server (an identity the credential is not scoped for) is detected via nc.LastError() after a Flush round-trip and returned as an error, so the standalone commands can exit non-zero (PLAN-17 D5). The runner reuses the same builders but ignores the error (its taps stay fire-and-forget).

Every subject carries the <user> token decoded from the .creds identity (natsconn.Identity) — server-enforceable when the operator scopes publish permissions to `ape.*.<token>.>` — and every payload carries the resolved session id.

Index

Constants

View Source
const (

	// LevelDebug…LevelError are the valid `ape log` levels.
	LevelDebug = "debug"
	LevelInfo  = "info"
	LevelWarn  = "warn"
	LevelError = "error"

	// EventTranscriptUploaded is the companion event `ape transcript upload`
	// publishes with the uploaded blobs' digest map.
	EventTranscriptUploaded = "transcript-uploaded"
)

Subject roots. ape.evt is overridable (--events-subject-prefix); ape.log and ape.metrics are fixed, versioned, additive-only roots.

Variables

View Source
var ErrDisabled = errors.New("reporting: no NATS URL configured")

ErrDisabled is returned by Connect when no NATS URL is configured — the standalone commands map it to a usage/config exit code (exit 2).

Functions

func LevelValid

func LevelValid(level string) bool

LevelValid reports whether level is one of the four accepted log levels.

Types

type MetricsPayload

type MetricsPayload struct {
	DurationSeconds   float64
	NumTurns          int
	PerModel          map[string]eventing.ModelMetrics
	FirstTurnAt       string // RFC3339Nano, "" when unknown
	LastTurnAt        string
	ClaudeCodeVersion string
	RunID             string // set only in --run-id (manifest-totals) mode
}

MetricsPayload is the ape.metrics.<user>.<project>.<sid> payload's metric-specific fields (PLAN-17 D3). It carries per-model token counts + timestamps so a consumer can reprice against Claude Code API rates at any later moment (the "convert to API prices any moment" requirement): the per_model tokens times the date-aware price table equal cost_usd.

func BuildMetrics

func BuildMetrics(scan cost.ScanResult, runID string) MetricsPayload

BuildMetrics maps a scanned session set onto the metrics payload. Pure and deterministic given the scan — the runner and the CLI both call it, which is what makes a supervised run and a standalone `ape metrics` byte-identical (PLAN-17 exit gate).

type Options

type Options struct {
	// Identity is the decoded credential identity; its SubjectToken is the
	// <user> subject segment and Name/PublicKey fill the payload user block.
	Identity natsconn.Identity
	// Project is the project root; slugged into the <project> segment.
	Project string
	// EvtPrefix overrides the ape.evt root (default eventing.DefaultPrefix).
	EvtPrefix string
	// SubjectUser overrides the <user> token (test-only seam behind
	// --debug-subject-user, to prove server-enforced identity rejects a
	// forged token). Empty uses Identity.SubjectToken.
	SubjectUser string
}

Options configures a Reporter.

type Reporter

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

Reporter publishes the four report shapes on one connection.

func Connect

func Connect(ctx context.Context, cfg natsconn.Config, name string, opts Options) (*Reporter, error)

Connect opens a reporting connection for the standalone commands. It swaps the default stderr async-error handler for a silent one; publish rejections are detected synchronously via nc.LastError() and returned by the publish methods (PLAN-17 D5). Returns ErrDisabled when cfg carries no URL. The caller must Close the returned Reporter.

func New

func New(nc *nats.Conn, opts Options) *Reporter

New wraps an existing connection (the runner's shared conn). The returned Reporter does not own nc and Close is a no-op on it.

func (*Reporter) Close

func (r *Reporter) Close()

Close drains and closes the connection when the Reporter owns it.

func (*Reporter) Conn

func (r *Reporter) Conn() *nats.Conn

Conn exposes the underlying connection so a caller can build a blobstore backend against the same connection (the standalone `ape transcript` command selects nats-object vs uri-offload and passes the store to UploadTranscripts).

func (*Reporter) Event

func (r *Reporter) Event(sessionID, event string, payload json.RawMessage) error

Event publishes a caller-named session event on ape.evt.<user>.<project>.session.<sid>.<event>. payload is the caller's arbitrary JSON (nil when none).

func (*Reporter) Log

func (r *Reporter) Log(sessionID, level, msg string, fields map[string]string) error

Log publishes a structured log record on ape.log.<user>.<project>.<sid>.<level>.

func (*Reporter) Metrics

func (r *Reporter) Metrics(sessionID string, p MetricsPayload) error

Metrics publishes a metrics snapshot on ape.metrics.<user>.<project>.<sid>.

func (*Reporter) PublishTranscriptUploaded

func (r *Reporter) PublishTranscriptUploaded(sessionID string, result TranscriptResult) error

PublishTranscriptUploaded emits the companion ape.evt.<user>.<project>.session.<sid>.transcript-uploaded event carrying the uploaded blobs' digest map (keyed by file base name) so consumers learn about the blobs without polling the store.

func (*Reporter) UploadTranscripts

func (r *Reporter) UploadTranscripts(ctx context.Context, store blobstore.Store, sessionID string, files []cost.SessionFile) (TranscriptResult, error)

UploadTranscripts uploads a session's file set (main + sub-agents, content-addressed, zstd, idempotent) through store. Re-uploading a blob already present is a cheap no-op (Existed=true, same digest). It does not publish — call PublishTranscriptUploaded with the result to emit the companion event.

type TranscriptFile

type TranscriptFile struct {
	Path      string `json:"path"`
	SessionID string `json:"session_id"`
	Digest    string `json:"digest"`
	URI       string `json:"uri,omitempty"`
	Bytes     int64  `json:"bytes"`
	Existed   bool   `json:"existed"` // true when the blob was already present (dedup no-op)
}

TranscriptFile is one uploaded transcript in the result object.

type TranscriptResult

type TranscriptResult struct {
	SessionID string           `json:"session_id"`
	Files     []TranscriptFile `json:"files"`
}

TranscriptResult is `ape transcript upload`'s result object (stdout).

Jump to

Keyboard shortcuts

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