Skip to content

Commit

Permalink
op-node: event tracers with diagram generation
Browse files Browse the repository at this point in the history
  • Loading branch information
protolambda committed Jul 9, 2024
1 parent c085872 commit fb8fe3f
Show file tree
Hide file tree
Showing 3 changed files with 424 additions and 0 deletions.
86 changes: 86 additions & 0 deletions op-node/rollup/event/tracer_sequence.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package event

import (
"fmt"
"strings"
)

type SequenceTracer struct {
StructTracer
}

var _ Tracer = (*SequenceTracer)(nil)

func NewSequenceTracer() *SequenceTracer {
return &SequenceTracer{}
}

func (st *SequenceTracer) Output(showDurations bool) string {
st.l.Lock()
defer st.l.Unlock()
out := new(strings.Builder)
out.WriteString(`
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Sequence trace</title>
</head>
<body>
Sequence:
<pre class="mermaid">
`)

// Docs: https://mermaid.js.org/syntax/sequenceDiagram.html
_, _ = fmt.Fprintln(out, "sequenceDiagram")
// make sure the System is always the left-most entry in the diagram
_, _ = fmt.Fprintln(out, " participant System")
// other participants are implied by the following events

denyList := make(map[uint64]struct{})
for _, e := range st.Entries {
if e.Kind == TraceDeriveEnd && !e.DeriveEnd.Effect {
denyList[e.DerivContext] = struct{}{}
}
}
for _, e := range st.Entries {
// omit entries which just passed through but did not have any effective processing
if e.DerivContext != 0 {
if _, ok := denyList[e.DerivContext]; ok {
continue
}
}
switch e.Kind {
case TraceDeriveStart:
_, _ = fmt.Fprintf(out, " %%%% deriver-start %d\n", e.DerivContext)
_, _ = fmt.Fprintf(out, " System ->> %s: derive %s (%d)\n", e.Name, e.EventName, e.EmitContext)
_, _ = fmt.Fprintf(out, " activate %s\n", e.Name)
case TraceDeriveEnd:
_, _ = fmt.Fprintf(out, " deactivate %s\n", e.Name)
if showDurations {
_, _ = fmt.Fprintf(out, " Note over %s: duration: %s\n", e.Name, strings.ReplaceAll(e.DeriveEnd.Duration.String(), "µ", "#181;"))
}
_, _ = fmt.Fprintf(out, " %%%% deriver-end %d\n", e.DerivContext)
case TraceRateLimited:
_, _ = fmt.Fprintf(out, " Note over %s: rate-limited\n", e.Name)
case TraceEmit:
_, _ = fmt.Fprintf(out, " %%%% emit originates from %d\n", e.DerivContext)
_, _ = fmt.Fprintf(out, " %s -->> System: emit %s (%d)\n", e.Name, e.EventName, e.EmitContext)
_, _ = fmt.Fprintln(out, " activate System")
_, _ = fmt.Fprintln(out, " deactivate System")
}
}

out.WriteString(`
</pre>
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.9.1/dist/mermaid.min.js"
integrity="sha384-WmdflGW9aGfoBdHc4rRyWzYuAjEmDwMdGdiPNacbwfGKxBW/SO6guzuQ76qjnSlr"
crossorigin="anonymous"></script>
<script>
mermaid.initialize({ startOnLoad: true, maxTextSize: 10000000 });
</script>
</body>
</html>
`)
return out.String()
}
101 changes: 101 additions & 0 deletions op-node/rollup/event/tracer_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package event

import (
"sync"
"time"
)

type TraceEntryKind int

const (
TraceDeriveStart TraceEntryKind = iota
TraceDeriveEnd
TraceRateLimited
TraceEmit
)

type TraceEntry struct {
Kind TraceEntryKind

Name string
DerivContext uint64

// Not present if Kind == TraceRateLimited
EmitContext uint64
// Not present if Kind == TraceRateLimited
EventName string

// Set to deriver start-time if derive-start/end, or emit-time if emitted. Not set if Kind == TraceRateLimited
EventTime time.Time

// Only present if Kind == TraceDeriveEnd
DeriveEnd struct {
Duration time.Duration
Effect bool
}
}

type StructTracer struct {
l sync.Mutex

Entries []TraceEntry
}

var _ Tracer = (*StructTracer)(nil)

func NewStructTracer() *StructTracer {
return &StructTracer{}
}

func (st *StructTracer) OnDeriveStart(name string, ev AnnotatedEvent, derivContext uint64, startTime time.Time) {
st.l.Lock()
defer st.l.Unlock()
st.Entries = append(st.Entries, TraceEntry{
Kind: TraceDeriveStart,
Name: name,
EventName: ev.Event.String(),
EmitContext: ev.EmitContext,
DerivContext: derivContext,
EventTime: startTime,
})
}

func (st *StructTracer) OnDeriveEnd(name string, ev AnnotatedEvent, derivContext uint64, startTime time.Time, duration time.Duration, effect bool) {
st.l.Lock()
defer st.l.Unlock()
st.Entries = append(st.Entries, TraceEntry{
Kind: TraceDeriveEnd,
Name: name,
EventName: ev.Event.String(),
EmitContext: ev.EmitContext,
DerivContext: derivContext,
EventTime: startTime,
DeriveEnd: struct {
Duration time.Duration
Effect bool
}{Duration: duration, Effect: effect},
})
}

func (st *StructTracer) OnRateLimited(name string, derivContext uint64) {
st.l.Lock()
defer st.l.Unlock()
st.Entries = append(st.Entries, TraceEntry{
Kind: TraceRateLimited,
Name: name,
DerivContext: derivContext,
})
}

func (st *StructTracer) OnEmit(name string, ev AnnotatedEvent, derivContext uint64, emitTime time.Time) {
st.l.Lock()
defer st.l.Unlock()
st.Entries = append(st.Entries, TraceEntry{
Kind: TraceEmit,
Name: name,
EventName: ev.Event.String(),
EmitContext: ev.EmitContext,
DerivContext: derivContext,
EventTime: emitTime,
})
}
Loading

0 comments on commit fb8fe3f

Please sign in to comment.