Help us shape the future of Go! Take the 2026 Go Developer Survey

analytics

package
v1.54.0 Latest Latest
Warning

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

Go to latest
Published: Sep 17, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

Documentation

Overview

Package analytics provides terminal escape code extraction and analysis

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func DescribeSGR

func DescribeSGR(params string) string

DescribeSGR returns a human-readable description of SGR parameters

func DescribeSimpleEscape

func DescribeSimpleEscape(secondByte byte) string

DescribeSimpleEscape returns a description for a simple 2-byte escape

func GetDECPrivateModeDescription

func GetDECPrivateModeDescription(mode string) string

GetDECPrivateModeDescription returns a human-readable description for a DEC private mode

func GetEraseInDisplayDescription

func GetEraseInDisplayDescription(params string) string

Erase in Display descriptions

func GetEraseInLineDescription

func GetEraseInLineDescription(params string) string

Erase in Line descriptions

func GetGlobalEscapeWriterDroppedCount added in v1.54.0

func GetGlobalEscapeWriterDroppedCount() int64

GetGlobalEscapeWriterDroppedCount reports events lost to writer backpressure.

func GetOSCDescription

func GetOSCDescription(cmd string) string

GetOSCDescription returns a human-readable description for an OSC command

func SetGlobalEscapeWriter

func SetGlobalEscapeWriter(w EscapeEventWriter)

SetGlobalEscapeWriter replaces the process-wide escape event writer. Called once at server startup after the batch writer is created.

Types

type EscapeCategory

type EscapeCategory string

EscapeCategory represents the type of escape sequence

const (
	CategoryCSI     EscapeCategory = "CSI"     // Control Sequence Introducer \x1b[
	CategoryOSC     EscapeCategory = "OSC"     // Operating System Command \x1b]
	CategoryDCS     EscapeCategory = "DCS"     // Device Control String \x1bP
	CategoryPM      EscapeCategory = "PM"      // Privacy Message \x1b^
	CategoryAPC     EscapeCategory = "APC"     // Application Program Command \x1b_
	CategorySOS     EscapeCategory = "SOS"     // Start of String \x1bX
	CategoryC1      EscapeCategory = "C1"      // C1 control codes
	CategorySimple  EscapeCategory = "Simple"  // Simple 2-char escapes
	CategoryDECPriv EscapeCategory = "DECPriv" // DEC Private modes \x1b[?
	CategorySGR     EscapeCategory = "SGR"     // Select Graphic Rendition (colors/styles)
	CategoryCursor  EscapeCategory = "Cursor"  // Cursor positioning
	CategoryErase   EscapeCategory = "Erase"   // Screen/line erase
	CategoryScroll  EscapeCategory = "Scroll"  // Scroll region
	CategoryCharset EscapeCategory = "Charset" // Character set selection
	CategoryUnknown EscapeCategory = "Unknown" // Unknown sequence
)

type EscapeCodeEntry

type EscapeCodeEntry struct {
	Code          string         `json:"code"`          // Hex-encoded sequence
	HumanReadable string         `json:"humanReadable"` // Description
	Category      EscapeCategory `json:"category"`      // Type of sequence
	Count         int64          `json:"count"`         // How many times seen
	FirstSeen     time.Time      `json:"firstSeen"`     // First occurrence
	LastSeen      time.Time      `json:"lastSeen"`      // Most recent occurrence
	SessionIDs    []string       `json:"sessionIds"`    // Sessions that produced this code
}

EscapeCodeEntry represents a tracked escape sequence

type EscapeCodeParser

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

EscapeCodeParser extracts escape sequences from terminal output

func NewEscapeCodeParser

func NewEscapeCodeParser(store *EscapeCodeStore, sessionID string) *EscapeCodeParser

NewEscapeCodeParser creates a new parser with the given store and session ID

func (*EscapeCodeParser) GetStats

func (p *EscapeCodeParser) GetStats() ParserStats

GetStats returns lifetime counters for this parser.

func (*EscapeCodeParser) IsEnabled

func (p *EscapeCodeParser) IsEnabled() bool

IsEnabled returns whether parsing is enabled

func (*EscapeCodeParser) Parse

func (p *EscapeCodeParser) Parse(data []byte, sessionSeq int64) []byte

Parse extracts all escape sequences from data and records them to the store. sessionSeq is the cumulative PTY byte offset at the start of this chunk. Returns the original data unchanged (passthrough).

func (*EscapeCodeParser) ParseStage2

func (p *EscapeCodeParser) ParseStage2(data []byte, sessionSeq int64)

ParseStage2 performs a secondary parse pass over data (a coalesced transport frame) and emits EscapeEventRecord entries with Stage=StageTransport. sessionSeq is the cumulative transport byte offset at the start of this frame. ParseStage2 uses its own independent chunk counter (stage2ChunkSeqNum) for sampling so that calling it independently does not interfere with the Stage 1 counter.

func (*EscapeCodeParser) RunCorrelatorEviction

func (p *EscapeCodeParser) RunCorrelatorEviction(ctx context.Context)

RunCorrelatorEviction runs the attached correlator's eviction loop until ctx is cancelled. No-op if no correlator or writer is configured (e.g. capture_level=off). Blocks the calling goroutine — callers that need this to run in the background must launch it themselves (e.g. `go p.RunCorrelatorEviction(ctx)`, ideally tracked with the same WaitGroup used for their other background work so a "Stop" method can block until this has actually exited too). Recovers from panics so a bug here can't take down the whole process.

func (*EscapeCodeParser) SetCorrelator

func (p *EscapeCodeParser) SetCorrelator(c *MangleCorrelator)

SetCorrelator attaches a MangleCorrelator to this parser for Stage 1/2 mangle detection.

func (*EscapeCodeParser) SetEnabled

func (p *EscapeCodeParser) SetEnabled(enabled bool)

SetEnabled enables or disables escape code parsing

func (*EscapeCodeParser) SetEventWriter

func (p *EscapeCodeParser) SetEventWriter(w EscapeEventWriter, captureLevel string, redactOSC bool, samplingRate float64)

SetEventWriter configures the event writer and capture settings.

func (*EscapeCodeParser) SetProjectPath added in v1.54.0

func (p *EscapeCodeParser) SetProjectPath(path string)

SetProjectPath records the canonical project path alongside future events.

func (*EscapeCodeParser) SetStableSessionID

func (p *EscapeCodeParser) SetStableSessionID(id string)

SetStableSessionID overrides the session identifier recorded on emitted events. Used to switch from the tmux session name (used at construction time) to the stable session UUID once it is known, so escape_event rows can be correlated with the same session identifier the rest of the app uses. Safe to call at any time, including concurrently with Parse/ParseStage2 on a running stream — the name matches ResponseStream.SetStableSessionID, which wraps it, so both ends of this wiring are textually distinguishable from tmux-name-keyed setters (like detection.StatusDetector.SetSessionID) called nearby at the same call site.

type EscapeCodeStats

type EscapeCodeStats struct {
	Enabled        bool                     `json:"enabled"`
	TotalCodes     int64                    `json:"totalCodes"`     // Total codes recorded
	UniqueCodes    int                      `json:"uniqueCodes"`    // Unique sequences
	CategoryCounts map[EscapeCategory]int64 `json:"categoryCounts"` // Count by category
	TopCodes       []EscapeCodeEntry        `json:"topCodes"`       // Most frequent codes
	RecentCodes    []EscapeCodeEntry        `json:"recentCodes"`    // Recently seen codes
}

EscapeCodeStats provides aggregated statistics

type EscapeCodeStore

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

EscapeCodeStore provides thread-safe storage for escape code analytics

func GetGlobalStore

func GetGlobalStore() *EscapeCodeStore

GetGlobalStore returns the singleton escape code store

func NewEscapeCodeStore

func NewEscapeCodeStore() *EscapeCodeStore

NewEscapeCodeStore creates a new store with default settings

func (*EscapeCodeStore) Clear

func (s *EscapeCodeStore) Clear()

Clear removes all entries

func (*EscapeCodeStore) Export

func (s *EscapeCodeStore) Export() ([]byte, error)

Export returns all data as JSON

func (*EscapeCodeStore) GetAll

func (s *EscapeCodeStore) GetAll() []EscapeCodeEntry

GetAll returns all entries

func (*EscapeCodeStore) GetByCategory

func (s *EscapeCodeStore) GetByCategory(category EscapeCategory) []EscapeCodeEntry

GetByCategory returns entries for a specific category

func (*EscapeCodeStore) GetBySession

func (s *EscapeCodeStore) GetBySession(sessionID string) []EscapeCodeEntry

GetBySession returns entries for a specific session

func (*EscapeCodeStore) GetStats

func (s *EscapeCodeStore) GetStats() EscapeCodeStats

GetStats returns aggregated statistics

func (*EscapeCodeStore) IsEnabled

func (s *EscapeCodeStore) IsEnabled() bool

IsEnabled returns whether tracking is enabled

func (*EscapeCodeStore) Record

func (s *EscapeCodeStore) Record(sessionID string, rawBytes []byte, category EscapeCategory, description string)

Record adds or updates an escape code entry

func (*EscapeCodeStore) SetEnabled

func (s *EscapeCodeStore) SetEnabled(enabled bool)

SetEnabled enables or disables tracking

type EscapeEventRecord

type EscapeEventRecord struct {
	SessionID         string
	ProjectPath       string
	Stage             Stage
	SequenceType      string // "CSI", "OSC", "DCS", etc.
	SequenceSubtype   string // e.g. "SGR", "cursor-up", "clipboard"
	SequenceSignature string // privacy-safe normalized command, e.g. "CSI:?25h" or "OSC:52"
	ByteLen           int
	PayloadHash       string // SHA-256 hex prefix, empty if redacted
	RawBytes          []byte // nil unless capture_level=full
	Mangled           bool
	MangleType        string // "truncated", "mutated", "stripped"
	WallTime          time.Time
	SessionSeq        int64 // cumulative PTY byte offset at start of chunk
}

EscapeEventRecord holds a single observed escape sequence event.

type EscapeEventWriter

type EscapeEventWriter interface {
	WriteEscapeEvent(ctx context.Context, event EscapeEventRecord)
}

EscapeEventWriter is the interface for persisting escape events.

func GetGlobalEscapeWriter

func GetGlobalEscapeWriter() EscapeEventWriter

GetGlobalEscapeWriter returns the process-wide escape event writer.

type EscapeEventWriterStats added in v1.54.0

type EscapeEventWriterStats interface {
	DroppedCount() int64
}

EscapeEventWriterStats is implemented by writers that expose capture loss.

type MangleCorrelator

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

func NewMangleCorrelator

func NewMangleCorrelator(maxAge time.Duration, maxSize int) *MangleCorrelator

NewMangleCorrelator creates a correlator with the given TTL and max pending size.

func (*MangleCorrelator) CheckStage2

func (c *MangleCorrelator) CheckStage2(sessionID, sequenceType, hash string, byteLen int) (bool, string)

CheckStage2 checks whether the next Stage 2 observation for this (sessionID, sequenceType) pair — the next ordinal — matches its corresponding Stage 1 observation. Returns (mangled bool, mangleType string). mangleType is one of: "", "truncated", "mutated". If no Stage 1 observation is found at that ordinal, returns (false, "") — absence is not definitive; the eviction pass handles the "never arrived" (stripped) case.

func (*MangleCorrelator) EvictExpired

func (c *MangleCorrelator) EvictExpired(ctx context.Context, writer EscapeEventWriter)

EvictExpired removes observations older than maxAge and emits them as "stripped" escape events. Call this periodically (e.g., every maxAge/2).

Deliberately scans only c.pending, not the ordinal-counter maps (see PruneStaleOrdinals) — this runs on StartEviction's frequent maxAge/2 ticker (2.5s for the production TTL), so its critical section stays as short as live pprof/Pyroscope evidence showed matters: on a production instance running ~50-100 concurrent sessions, mutex-contention profiling attributed 1,229 events / 224.6s of waiter delay to this function — ~183ms average per event, far too long for a map scan this small to explain on its own. Cross-referencing the same window's CPU profile (17% in runtime.gcBgMarkWorker/scanSpan) and `uptime`'s load average (32 runnable threads on an 18-core machine) pins the real cause on scheduler/GC preemption while the lock is held, not this critical section's own cost — so the fix here is to minimize exposure (shrink what runs under the frequent lock), not to restructure the lock itself; the systemic fix is reducing allocation/goroutine pressure elsewhere.

func (*MangleCorrelator) ObserveTransport added in v1.54.0

func (c *MangleCorrelator) ObserveTransport(sessionID string)

ObserveTransport records that a transport is actively carrying output for the session. This prevents sessions with no consumer from being reported as stripped merely because Stage 2 was never expected.

func (*MangleCorrelator) PendingCount

func (c *MangleCorrelator) PendingCount() int

PendingCount returns the number of unmatched Stage 1 observations (for monitoring).

func (*MangleCorrelator) PruneStaleOrdinals added in v1.54.0

func (c *MangleCorrelator) PruneStaleOrdinals()

PruneStaleOrdinals removes stage1Ordinals/stage2Ordinals/ordinalLastSeen entries for (session, type) pairs that have gone quiet for longer than maxAge: a session that ended (or a sequence type it stopped emitting) leaves these with no further writer to ever clean them up otherwise. Split out of EvictExpired (see its doc comment) so this second map scan doesn't add to the lock hold time of the frequent maxAge/2 eviction tick — StartEviction calls this on its own, much less frequent, ordinalPruneEveryNTicks cadence instead, since staleness here is only ever session-idle-scale, not sequence-TTL-scale.

func (*MangleCorrelator) RecordStage1

func (c *MangleCorrelator) RecordStage1(sessionID, sequenceType, hash string, byteLen int)

RecordStage1 records a Stage 1 observation for later correlation. It is assigned the next ordinal for this (sessionID, sequenceType) pair.

func (*MangleCorrelator) RecordStage1WithMetadata added in v1.54.0

func (c *MangleCorrelator) RecordStage1WithMetadata(sessionID, projectPath, sequenceType, sequenceSignature, hash string, byteLen int)

RecordStage1WithMetadata preserves project and normalized command attribution when an unmatched observation is later emitted as stripped.

func (*MangleCorrelator) StartEviction

func (c *MangleCorrelator) StartEviction(ctx context.Context, writer EscapeEventWriter)

StartEviction starts a background goroutine that calls EvictExpired periodically, and PruneStaleOrdinals every ordinalPruneEveryNTicks-th tick. Returns when ctx is cancelled.

type NoopEscapeEventWriter

type NoopEscapeEventWriter struct{}

NoopEscapeEventWriter discards all events (used when capture_level=off).

func (NoopEscapeEventWriter) WriteEscapeEvent

func (n NoopEscapeEventWriter) WriteEscapeEvent(_ context.Context, _ EscapeEventRecord)

type ParsedEscapeCode

type ParsedEscapeCode struct {
	RawBytes    []byte         // Original bytes
	Category    EscapeCategory // Type of sequence
	Description string         // Human-readable description
	StartOffset int            // Position in original data
	EndOffset   int            // End position in original data
}

ParsedEscapeCode represents a single parsed escape sequence

type ParserStats

type ParserStats struct {
	TotalSequences int64
	TotalMangled   int64
	Dropped        int64
}

ParserStats holds lifetime counters for a parser session.

type Stage

type Stage string

Stage identifies which pipeline stage observed a sequence.

const (
	StagePTYRead   Stage = "pty_read"
	StageTransport Stage = "transport"
	StageBrowser   Stage = "browser"
)

type Stage1Observation

type Stage1Observation struct {
	PayloadHash       string
	ByteLen           int
	WallTime          time.Time
	SessionID         string
	ProjectPath       string
	SequenceType      string
	SequenceSignature string
}

Stage1Observation records a sequence seen at Stage 1 (PTY read) for later correlation with Stage 2.

Jump to

Keyboard shortcuts

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