-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
op-node: event tracers with diagram generation
- Loading branch information
1 parent
c085872
commit fb8fe3f
Showing
3 changed files
with
424 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}) | ||
} |
Oops, something went wrong.