Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

op-node: Events diagrams generation #11101

Merged
merged 1 commit into from
Jul 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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