Skip to content

Commit

Permalink
gosimviewer: show syscalls
Browse files Browse the repository at this point in the history
Does not work too great because the logs show up under
machine=os,goroutine=1 which means you cannot yet filter for syscalls by
a given machine or goroutine.

Usage:

    go run github.com/jellevandenhooff/gosim/cmd/gosim test -v -run TestEtcd -simtrace=stack,syscall -jsonlogout=/tmp/logs.txt ./examples/etcd
    go run github.com/jellevandenhooff/gosim/cmd/gosim viewer -log=/tmp/logs.txt
  • Loading branch information
jellevandenhooff committed Nov 30, 2024
1 parent 6ac9b4d commit 6105da7
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 14 deletions.
1 change: 1 addition & 0 deletions internal/gosimlog/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type Log struct {
Stackframes []*Stackframe `json:"stackframes"`
Machine string `json:"machine"`
Goroutine int `json:"goroutine"`
TraceKind string `json:"traceKind"`

// map[string]any for extra fields
}
Expand Down
37 changes: 26 additions & 11 deletions internal/gosimviewer/index.html.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,30 @@ a {
</style>
</head>
<body>
<div style="display: flex; overflow: hide; height: 100%">
<div id="root" style="display: flex; overflow: hide; height: 100%">
<div style="width: 50%; display: flex; flex-direction: column;">
<div>
{{ $level := .LogLevel }}
{{ $focus := .Focus }}
<pre>focus: {{ if .Focus }}{{ .Focus }} <a href="/?level={{ $level }}">all logs</a>{{ else }}all logs{{ end }}</pre>
<pre>log level:{{ range .LogLevels }} {{ if eq . $level }}{{ . }}{{ else }}<a href="/?level={{ . }}&focus={{ $focus }}">{{ . }}</a>{{ end }}{{ end }}</pre>
<span style="font-family: monospace">
focus: {{ if .Focus }}{{ .Focus }} <a href="#" onclick="setFilter({focus: '' })">all logs</a>{{ else }}all logs{{ end }}</pre>;
log level:{{ range .LogLevels }} {{ if eq . $level }}{{ . }}{{ else }}<a href="#" onclick="setFilter({level: {{ . }} })">{{ . }}</a>{{ end }}{{ end }}</pre>;
<label for="syscalls">syscalls: </label><input id="syscalls" type="checkbox" onclick="setFilter({syscalls: event.target.checked})" {{ if .Syscalls }}checked{{ end }}/>
</span>
</div>
<div style="overflow: scroll; font-family: monospace;">
{{ range .Logs }}
<span>
{{ .Step }}
<a href="/?level={{ $level }}&focus=machine:{{ .Machine }}">{{ .Machine }}</a>/<a href="/?level={{ $level }}&focus=goroutine:{{ .Goroutine }}">{{.Goroutine}}</a>
<a href="#" onclick="setFilter({focus: 'machine:{{ .Machine }}'})">{{ .Machine }}</a>/<a href="#" onclick="setFilter({focus: 'goroutine:{{ .Goroutine }}'})">{{.Goroutine}}</a>
{{.Time | Time }}
{{ .Level }}
<a href="#" onclick="show({index: {{ .Index }}, source: {{ .Source }} })">{{ .Source | Source }}</a>
&gt;
<pre style="display: inline">{{ .Msg }}</pre>
<pre style="display: inline; text-wrap: wrap;">{{ .Msg }}</pre>
</span><br>
{{ end }}
{{ if .Truncated }}and more...{{ end }}
</div>
</div>
<div style="width: 50%; display: flex; flex-direction: column;">
Expand Down Expand Up @@ -64,12 +68,23 @@ function scrollTo(file, line) {
element.scrollIntoViewIfNeeded({block: "center"});
}
}
htmx.onLoad(function(e) {
tippy(e.querySelectorAll('[data-tooltip]'), {
duration: 0,
maxWidth: "none",
content: function(e) { return e.getAttribute('data-tooltip'); },
});
function setFilter(update) {
var current = {
focus: {{ .Focus }},
level: {{ .LogLevel }},
syscalls: {{ .Syscalls }},
};
Object.assign(current, update);
var path = "/?focus=" + encodeURIComponent(current.focus) +
"&level=" + encodeURIComponent(current.level) +
"&syscalls=" + encodeURIComponent(current.syscalls);
window.location = path;
}
tippy.delegate("#root", {
target: '[data-tooltip]',
duration: 0,
maxWidth: "none",
content: function(e) { return e.getAttribute('data-tooltip'); },
});
</script>
</body>
Expand Down
26 changes: 26 additions & 0 deletions internal/gosimviewer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,27 @@ func (s *Server) Index(w http.ResponseWriter, r *http.Request) {
q := r.URL.Query()
focusStr := q.Get("focus")
levelStr := q.Get("level")
syscallsStr := q.Get("syscalls")

logs := s.Logs

var syscalls bool
if syscallsStr != "" {
var err error
syscalls, err = strconv.ParseBool(syscallsStr)
if err != nil {
http.Error(w, fmt.Sprintf("parsing syscalls: %s", err.Error()), http.StatusBadRequest)
return
}
}

logs = filter(logs, func(l *gosimlog.Log) bool {
if l.TraceKind == "syscall" && !syscalls {
return false
}
return true
})

level := slog.LevelInfo
if levelStr != "" {
if err := level.UnmarshalText([]byte(levelStr)); err != nil {
Expand Down Expand Up @@ -113,11 +131,19 @@ func (s *Server) Index(w http.ResponseWriter, r *http.Request) {
}
}

truncated := false
if limit := 1000; len(logs) > limit {
logs = logs[:limit]
truncated = true
}

if err := templates.ExecuteTemplate(w, "index.html.tmpl", map[string]any{
"Logs": logs,
"Focus": focusStr,
"LogLevels": []slog.Level{slog.LevelDebug, slog.LevelInfo, slog.LevelWarn, slog.LevelError},
"LogLevel": level,
"Syscalls": syscalls,
"Truncated": truncated,
}); err != nil {
http.Error(w, fmt.Sprintf("writing template: %s", err.Error()), http.StatusInternalServerError)
return
Expand Down
6 changes: 3 additions & 3 deletions internal/simulation/os_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"log"
"log/slog"
"math/rand"
"net/netip"
Expand Down Expand Up @@ -75,9 +75,9 @@ func (l *LinuxOS) doShutdown() {
l.files = nil
}

func logf(fmt string, args ...any) {
func logf(format string, args ...any) {
if logInitialized && gosimruntime.TraceSyscall.Enabled() {
log.Printf(fmt, args...)
slog.Info(fmt.Sprintf(format, args...), "traceKind", "syscall")
}
}

Expand Down
1 change: 1 addition & 0 deletions internal/tests/behavior/log_meta_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ func TestLogTraceSyscall(t *testing.T) {
t.Fatal(err)
}

// TODO: make sure we check traceKind?
// TODO: support snapshotting these logs?
// TODO: include machine etc.?
if diff := cmp.Diff(metatesting.SimplifyParsedLog(metatesting.ParseLog(run.LogOutput)), []string{
Expand Down

0 comments on commit 6105da7

Please sign in to comment.