wirelog

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Sep 22, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package wirelog counts what the surface actually puts on the wire.

A TUI over SSH is not slow because it renders slowly. It is slow because every frame it renders becomes bytes on a link with a round trip in it, and nobody who has ever tuned one could say from memory how many bytes a second of streaming costs, or whether an idle prompt costs anything at all. This package answers that with a number instead of a hunch: it wraps the writer the terminal program paints through, counts bytes and write calls, and appends one line per second to a file.

It is a DEVELOPER'S instrument and nothing else. There is no settings row, no flag and no slash command, because there is no question a person using codeaf would ask that this answers — the audience is whoever is holding the SSH story and needs to know whether a change made it cheaper. It turns on only when CODEAF_WIRE_LOG names a file, and when it does not, the surface never learns it exists: FromEnv returns a nil *Meter, the caller leaves the output writer nil, and Bubble Tea paints straight into os.Stdout exactly as it did before. The cost of the meter when it is off is one LookupEnv at boot.

The log is deliberately dumb — four space-separated integers per line, one line per wall-clock second, silent seconds included as zeros so a reader can tell "nothing was drawn" from "the process was gone":

# unix_ms bytes writes total_bytes
1755400000000 41230 60 41230
1755400001000 0 0 41230

A second's bytes and writes are what left the program during THAT second; total_bytes is cumulative since the meter opened. Seconds are wall-clock seconds and not "seconds since start" so that a harness driving the surface from outside can line its own phase boundaries up against them without the two sides having to agree on when zero was.

Index

Constants

View Source
const EnvVar = "CODEAF_WIRE_LOG"

EnvVar names the file the meter appends to. Empty or unset means no meter.

It is an environment variable rather than a flag on purpose: a flag is a promise to a user, and this is a wire we tap while developing. Undocumented in the help output, in the settings screen and in the user-facing docs by design — the day it becomes something a person should reach for, it earns a name there and stops being this.

Variables

This section is empty.

Functions

This section is empty.

Types

type Meter

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

Meter is the terminal's writer with a counter on it.

It satisfies charmbracelet/x/term.File (ReadWriteCloser plus Fd) because Bubble Tea type-asserts its output to exactly that before it will put the terminal in raw mode, ask for the window size, or believe the terminal has color. A plain io.Writer wrapper measures a surface that is no longer the surface — cooked mode, no size, ASCII profile — so the wrapper carries the file descriptor through and the measurement stays about the real thing.

The zero value is not usable; a nil *Meter is, in the sense that the caller checks for it and never wraps at all.

func FromEnv

func FromEnv(out *os.File) *Meter

FromEnv returns a meter on out when EnvVar names a file, and nil when it does not — which is the whole opt-in.

A nil *Meter is returned as a nil *Meter and not as an io.Writer, because a typed nil inside an interface is not nil and the caller's `if meter != nil` would then wrap stdout in a meter that panics on first paint.

A file that cannot be opened returns nil too, with the reason on stderr. The alternative is refusing to start a chat because a debugging aid could not write its log, and no measurement is worth a door that will not open.

func Open

func Open(path string, out *os.File) (*Meter, error)

Open starts a meter on out that appends to path.

Appending rather than truncating: a harness that runs the surface twice against one log gets both runs, and the gap between them is visible as the missing seconds it actually was.

func (*Meter) Close

func (m *Meter) Close() error

Close writes the last, partial second and closes the log.

It does NOT close the terminal. A meter is a tap on a wire that belongs to the process, and closing the process's stdout on the way out of a chat would take the shell prompt with it.

func (*Meter) Fd

func (m *Meter) Fd() uintptr

Fd is why this type exists rather than a bare io.Writer wrapper: it is the descriptor raw mode, the window size and the color probe are all asked about.

func (*Meter) Read

func (m *Meter) Read(p []byte) (int, error)

Read is the other half of term.File. Bubble Tea reads its input from stdin and never from here, but the interface asks and an honest answer is one line.

func (*Meter) Total

func (m *Meter) Total() int64

Total reports bytes written since the meter opened. For tests and for anything that wants the number without parsing the file back.

func (*Meter) Write

func (m *Meter) Write(p []byte) (int, error)

Write paints and counts, in that order.

Jump to

Keyboard shortcuts

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