detached ece7682

runtime_observer.go RawHistoryFolder

1package ports
2
3import (
4	"errors"
5	"sync/atomic"
6)
7
8// RuntimeMarkSchema is the version of the process-local performance trace.
9const RuntimeMarkSchema uint16 = 1
10
11// RuntimeMarkKind identifies a process-local runtime boundary. It deliberately
12// contains no protocol payload, cells, or rendering policy.
13type RuntimeMarkKind string
14
15const (
16	RuntimeInputInjected        RuntimeMarkKind = "input_injected"
17	RuntimeResizeRequested      RuntimeMarkKind = "resize_requested"
18	RuntimeResizeCommitted      RuntimeMarkKind = "resize_committed"
19	RuntimeCaptureStart         RuntimeMarkKind = "capture_start"
20	RuntimeCaptureEnd           RuntimeMarkKind = "capture_end"
21	RuntimeComposeStart         RuntimeMarkKind = "compose_start"
22	RuntimeComposeEnd           RuntimeMarkKind = "compose_end"
23	RuntimeDiffStart            RuntimeMarkKind = "diff_start"
24	RuntimeDiffEnd              RuntimeMarkKind = "diff_end"
25	RuntimeQueueEnqueued        RuntimeMarkKind = "queue_enqueued"
26	RuntimeQueueDequeued        RuntimeMarkKind = "queue_dequeued"
27	RuntimeACKBlockedStart      RuntimeMarkKind = "ack_blocked_start"
28	RuntimeACKBlockedEnd        RuntimeMarkKind = "ack_blocked_end"
29	RuntimeEmitStart            RuntimeMarkKind = "emit_start"
30	RuntimeEmitEnd              RuntimeMarkKind = "emit_end"
31	RuntimeAdapterSendStart     RuntimeMarkKind = "adapter_send_start"
32	RuntimeAdapterSendEnd       RuntimeMarkKind = "adapter_send_end"
33	RuntimeAdapterReceiveStart  RuntimeMarkKind = "adapter_receive_start"
34	RuntimeAdapterReceiveEnd    RuntimeMarkKind = "adapter_receive_end"
35	RuntimeTerminalFlushed      RuntimeMarkKind = "terminal_flushed"
36	RuntimeScreenSnapshot       RuntimeMarkKind = "screen_snapshot"
37	RuntimeScreenDelta          RuntimeMarkKind = "screen_delta"
38	RuntimeScreenResetRequested RuntimeMarkKind = "screen_reset_requested"
39	RuntimeTransportDiagnostic  RuntimeMarkKind = "transport_diagnostic"
40)
41
42// RuntimeMark is a process-local observation record. Tick is intentionally
43// left zero by producers: the concrete process observer owns timestamping.
44type RuntimeMark struct {
45	Schema      uint16
46	ProcessID   string
47	Component   string
48	Scenario    string
49	Run         uint64
50	Sequence    uint64
51	RequestID   uint64
52	Epoch       uint64
53	Kind        RuntimeMarkKind
54	Tick        int64
55	Bytes       uint64
56	Fragments   uint64
57	Retransmits uint64
58	Pending     uint64
59	AckRTTNanos int64
60	Valid       bool
61}
62
63// RuntimeObserver receives process-local marks. Implementations must not let
64// a producer provide a timestamp in another clock domain.
65type RuntimeObserver interface{ ObserveRuntime(RuntimeMark) }
66
67// SerializedRuntimeObserver is the only observer contract accepted by runtime
68// transport and use-case hot paths. ObserveRuntime must return without waiting
69// for sink I/O. Flush and Close wait until every accepted mark has reached the
70// concrete observer; Close is idempotent and rejects later marks.
71type SerializedRuntimeObserver interface {
72	RuntimeObserver
73	Flush()
74	Close()
75}
76
77// RuntimeMarkValid reports whether a mark has all correlation fields required
78// by the JSONL schema. Tick is checked separately by the timestamp owner.
79func RuntimeMarkValid(mark RuntimeMark) bool {
80	if mark.Schema != RuntimeMarkSchema || mark.Component == "" || mark.Scenario == "" || mark.Run == 0 || mark.Sequence == 0 || mark.RequestID == 0 || mark.Epoch == 0 {
81		return false
82	}
83	switch mark.Kind {
84	case RuntimeInputInjected, RuntimeResizeRequested, RuntimeResizeCommitted,
85		RuntimeCaptureStart, RuntimeCaptureEnd, RuntimeComposeStart, RuntimeComposeEnd,
86		RuntimeDiffStart, RuntimeDiffEnd, RuntimeQueueEnqueued, RuntimeQueueDequeued,
87		RuntimeACKBlockedStart, RuntimeACKBlockedEnd, RuntimeEmitStart, RuntimeEmitEnd,
88		RuntimeAdapterSendStart, RuntimeAdapterSendEnd, RuntimeAdapterReceiveStart,
89		RuntimeAdapterReceiveEnd, RuntimeTerminalFlushed, RuntimeScreenSnapshot,
90		RuntimeScreenDelta, RuntimeScreenResetRequested, RuntimeTransportDiagnostic:
91		return true
92	default:
93		return false
94	}
95}
96
97// RuntimeCorrelation identifies one attempted operation. It is deliberately
98// copied to both endpoints of a span; process ID remains owned by the sink.
99type RuntimeCorrelation struct {
100	Scenario                        string
101	Run, Sequence, RequestID, Epoch uint64
102}
103
104// RuntimeCorrelationInputs are supplied once by process orchestration. They
105// are deliberately data-only: consumer APIs continue to receive only their
106// one RuntimeObserver argument and never a clock or tick.
107type RuntimeCorrelationInputs struct {
108	Scenario string
109	Run      uint64
110}
111
112// NewRuntimeCorrelationObserver binds every mark from one OS process to its
113// harness manifest scenario/run. Operation IDs remain producer-owned when
114// supplied; missing IDs are assigned from the process-wide allocator.
115func NewRuntimeCorrelationObserver(observer RuntimeObserver, inputs RuntimeCorrelationInputs) (RuntimeObserver, error) {
116	if observer == nil || inputs.Scenario == "" || inputs.Run == 0 {
117		return nil, errors.New("invalid runtime correlation inputs")
118	}
119	return &runtimeCorrelationObserver{observer: observer, inputs: inputs}, nil
120}
121
122type runtimeCorrelationObserver struct {
123	observer RuntimeObserver
124	inputs   RuntimeCorrelationInputs
125}
126
127func (o *runtimeCorrelationObserver) ObserveRuntime(mark RuntimeMark) {
128	if o == nil || o.observer == nil {
129		return
130	}
131	mark.Scenario, mark.Run = o.inputs.Scenario, o.inputs.Run
132	if mark.Sequence == 0 {
133		mark.Sequence = runtimeMarkSequence.Add(1)
134	}
135	if mark.RequestID == 0 {
136		mark.RequestID = mark.Sequence
137	}
138	if mark.Epoch == 0 {
139		mark.Epoch = mark.RequestID
140	}
141	o.observer.ObserveRuntime(mark)
142}
143
144var runtimeMarkSequence atomic.Uint64
145
146// NewRuntimeCorrelation makes a unique, process-local operation identity.
147// Components with a domain request/epoch should use those values directly via
148// NewRuntimeMarkWithCorrelation instead of inventing a second identity.
149func NewRuntimeCorrelation() RuntimeCorrelation {
150	sequence := runtimeMarkSequence.Add(1)
151	return RuntimeCorrelation{Scenario: "runtime", Run: 1, Sequence: sequence, RequestID: sequence, Epoch: sequence}
152}
153
154// NewRuntimeMarkWithCorrelation returns a timestamp-free mark carrying the
155// supplied operation identity. Start/end callers must reuse correlation.
156func NewRuntimeMarkWithCorrelation(component string, correlation RuntimeCorrelation, kind RuntimeMarkKind, bytes uint64, valid bool) RuntimeMark {
157	return RuntimeMark{Schema: RuntimeMarkSchema, Component: component, Scenario: correlation.Scenario, Run: correlation.Run, Sequence: correlation.Sequence, RequestID: correlation.RequestID, Epoch: correlation.Epoch, Kind: kind, Bytes: bytes, Valid: valid}
158}
159
160// NewRuntimeMark is retained for one-shot marks. Unlike the old helper it
161// never returns constant correlation IDs.
162func NewRuntimeMark(component string, kind RuntimeMarkKind, bytes uint64, valid bool) RuntimeMark {
163	return NewRuntimeMarkWithCorrelation(component, NewRuntimeCorrelation(), kind, bytes, valid)
164}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close