mirror of
https://github.com/saymrwulf/swisspost-evoting-go-poc.git
synced 2026-09-03 20:13:43 +00:00
The foundation for the "watch the mathematics execute" cockpit. Each meaningful crypto operation will emit one Event carrying its LaTeX notation plus the real runtime values, tagged with party + phase. One stream feeds both a terminal view (ASCII/Unicode) and a browser view (typeset KaTeX) — no double-maintenance. - Off by default with near-zero cost: Emit/EmitFunc return immediately when no sink is attached (atomic fast path), so instrumentation is free in normal runs. - Sinks: ChanSink (buffered, drops rather than stalling the ceremony), SliceSink (tests). Short() elides ~77-digit values for compact display. Tests: disabled-is-cheap, monotonic sequence + context stamping, elision. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
64 lines
1.4 KiB
Go
64 lines
1.4 KiB
Go
package trace
|
|
|
|
import "sync"
|
|
|
|
// Short elides a long value for compact display: keeps the first and last few
|
|
// characters. Renderers that want the full value use the raw Values map.
|
|
func Short(s string) string {
|
|
const head, tail = 8, 6
|
|
if len(s) <= head+tail+1 {
|
|
return s
|
|
}
|
|
return s[:head] + "…" + s[len(s)-tail:]
|
|
}
|
|
|
|
// ChanSink forwards events to a buffered channel, dropping if the consumer is
|
|
// too slow (tracing must never stall the ceremony). Dropped counts are tracked.
|
|
type ChanSink struct {
|
|
C chan Event
|
|
dropped uint64
|
|
mu sync.Mutex
|
|
}
|
|
|
|
// NewChanSink creates a ChanSink with the given buffer size.
|
|
func NewChanSink(buffer int) *ChanSink {
|
|
return &ChanSink{C: make(chan Event, buffer)}
|
|
}
|
|
|
|
func (s *ChanSink) Handle(e Event) {
|
|
select {
|
|
case s.C <- e:
|
|
default:
|
|
s.mu.Lock()
|
|
s.dropped++
|
|
s.mu.Unlock()
|
|
}
|
|
}
|
|
|
|
// Dropped returns how many events were dropped due to a full buffer.
|
|
func (s *ChanSink) Dropped() uint64 {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
return s.dropped
|
|
}
|
|
|
|
// SliceSink collects events in memory (used in tests).
|
|
type SliceSink struct {
|
|
mu sync.Mutex
|
|
Events []Event
|
|
}
|
|
|
|
func (s *SliceSink) Handle(e Event) {
|
|
s.mu.Lock()
|
|
s.Events = append(s.Events, e)
|
|
s.mu.Unlock()
|
|
}
|
|
|
|
// Snapshot returns a copy of the collected events.
|
|
func (s *SliceSink) Snapshot() []Event {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
out := make([]Event, len(s.Events))
|
|
copy(out, s.Events)
|
|
return out
|
|
}
|