Skip to content

Commit fee0cab

Browse files
Add inspect link to spawn events in the inspector
1 parent 7b433a6 commit fee0cab

9 files changed

Lines changed: 182 additions & 34 deletions

File tree

.vscode/settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"amacneil",
66
"buildmode",
77
"BYTEA",
8+
"chancreate",
9+
"chansend",
810
"checkcgogensync",
911
"cloc",
1012
"clocincludetests",

pkg/inspector/server.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ func SpawnInspector(platform platforms.Platform, addr string) context.CancelFunc
2222
mux.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
2323
handleStatic(w, r)
2424
})
25+
mux.HandleFunc("/isolate/name/", func(w http.ResponseWriter, r *http.Request) {
26+
handleInspectPageByName(tmpl, platform, platformName, version, w, r)
27+
})
2528
mux.HandleFunc("/isolate/", func(w http.ResponseWriter, r *http.Request) {
2629
handleInspectPage(tmpl, platform, platformName, version, w, r)
2730
})
@@ -77,6 +80,7 @@ func loadTemplates() *template.Template {
7780
"hash": hash,
7881
"fmtLine": fmtLine,
7982
"formatAwait": formatAwait,
83+
"isSpawn": isSpawn,
8084
}).ParseFS(content, "templates/*.html"),
8185
)
8286
}
@@ -313,6 +317,83 @@ func handleInspectPage(
313317
writeHTML(tmpl, w, "inspect", data)
314318
}
315319

320+
func handleInspectPageByName(
321+
tmpl *template.Template,
322+
platform platforms.Platform,
323+
platformName string,
324+
version string,
325+
w http.ResponseWriter,
326+
r *http.Request,
327+
) {
328+
name := strings.TrimPrefix(r.URL.Path, "/isolate/name/")
329+
330+
if name == "" {
331+
writeHTMLError(
332+
tmpl,
333+
w,
334+
platformName,
335+
version,
336+
http.StatusBadRequest,
337+
"invalid isolate name",
338+
)
339+
return
340+
}
341+
342+
isolate, err := platform.InspectorGetByName(name)
343+
if err != nil {
344+
status := http.StatusInternalServerError
345+
346+
var notExistErr *platforms.PlatformIsolateDoesNotExistError
347+
if errors.As(err, &notExistErr) {
348+
status = http.StatusNotFound
349+
}
350+
351+
writeHTMLError(tmpl, w, platformName, version, status, err.Error())
352+
return
353+
}
354+
355+
traces, err := platform.InspectorTraces(isolate.ID)
356+
if err != nil {
357+
writeHTMLError(
358+
tmpl,
359+
w,
360+
platformName,
361+
version,
362+
http.StatusInternalServerError,
363+
err.Error(),
364+
)
365+
return
366+
}
367+
368+
dark := dark(r)
369+
hasSource := isolate.Source != ""
370+
371+
var sourceHTML template.HTML
372+
if hasSource {
373+
sourceHTML = syntaxHighlightCodeHTML(
374+
isolate.Source,
375+
isolate.Lang,
376+
isolate.Line,
377+
dark,
378+
)
379+
}
380+
381+
data := inspectPageData{
382+
navData: navData{
383+
Title: "Inspect #" + strconv.FormatUint(uint64(isolate.ID), 10),
384+
Version: version,
385+
Platform: platformName,
386+
},
387+
Isolate: isolate,
388+
Variables: formatContext(isolate.Context),
389+
Traces: formatTraces(traces, isolate.Lang, dark),
390+
SourceHTML: sourceHTML,
391+
HasSource: hasSource,
392+
}
393+
394+
writeHTML(tmpl, w, "inspect", data)
395+
}
396+
316397
func handleVariablesFragment(
317398
tmpl *template.Template,
318399
platform platforms.Platform,

pkg/inspector/templates/fragments.html

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,14 @@
149149
<details class="accordion" id="trace-{{ $id }}">
150150
<summary class="grid-a2212" id="trace-{{ $id }}-summary">
151151
<span id="trace-{{ $id }}-arrival">{{ .ArrivalUTC }}</span>
152-
<span id="trace-{{ $id }}-key">{{ .Key }}</span>
152+
<span id="trace-{{ $id }}-key">
153+
{{ .Key }}
154+
{{ if isSpawn .Key }}
155+
<a class="inspect-link" href="/isolate/name/{{ .Key }}"
156+
>Inspect &rarr;</a
157+
>
158+
{{ end }}
159+
</span>
153160
<span id="trace-{{ $id }}-before-line">
154161
{{ fmtLine .BeforeLine }}
155162
</span>

pkg/inspector/templates/style.css

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ a {
6363
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
6464
}
6565
.grid-a2212 {
66-
grid-template-columns: auto 1fr 1fr 0.5fr 0.5fr 1fr;
66+
grid-template-columns:
67+
1rem minmax(0, 1fr) minmax(0, 1fr) minmax(0, 0.5fr)
68+
minmax(0, 0.5fr) minmax(0, 1fr);
6769
gap: 1rem;
70+
align-items: center;
6871
}
6972
.col-full {
7073
grid-column: 1 / -1;
@@ -260,6 +263,11 @@ tr.clickable:hover {
260263
font-size: 0.875rem;
261264
list-style: none;
262265
}
266+
.accordion summary > span {
267+
overflow: hidden;
268+
text-overflow: ellipsis;
269+
white-space: nowrap;
270+
}
263271
.accordion summary::before {
264272
content: "▶";
265273
font-size: 0.625rem;
@@ -333,6 +341,12 @@ tr.clickable:hover {
333341
color: var(--fg);
334342
}
335343

344+
/* -=[Inspect Link]=- */
345+
.inspect-link {
346+
display: block;
347+
font-size: 0.75rem;
348+
}
349+
336350
/* -=[Animations]=- */
337351
.flash {
338352
animation: flash 0.3s ease-out;

pkg/inspector/templating.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ func fmtLine(line int) string {
113113
return strconv.Itoa(line)
114114
}
115115

116+
func isSpawn(key string) bool {
117+
return strings.HasPrefix(key, "spawn-")
118+
}
119+
116120
func formatContext(ctxBytes []byte) map[string]string {
117121
if len(ctxBytes) == 0 {
118122
return nil

pkg/platforms/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,7 @@ type Platform interface {
401401
InspectorVersion() (string, string)
402402
InspectorSummary() (WorkersSummary, error)
403403
InspectorGet(id uint) (IsolateState, error)
404+
InspectorGetByName(name string) (IsolateState, error)
404405
InspectorTraces(id uint) ([]Trace, error)
405406
InspectorList(before uint, after uint, limit uint) (IsolateListResult, error)
406407
}

pkg/platforms/postgres/postgres.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,29 @@ func (p Postgres) InspectorGet(id uint) (platforms.IsolateState, error) {
183183
return row, nil
184184
}
185185

186+
func (p Postgres) InspectorGetByName(name string) (platforms.IsolateState, error) {
187+
row, err := fetchOne(p.pool, `
188+
SELECT id, name, program, source, lang, line, tick, events, status, error,
189+
context, created_at
190+
FROM isolates
191+
WHERE name = $1
192+
`, pgx.RowToStructByName[platforms.IsolateState], name)
193+
if err != nil {
194+
if errors.Is(err, pgx.ErrNoRows) {
195+
return platforms.IsolateState{}, &platforms.PlatformIsolateDoesNotExistError{
196+
Name: name,
197+
}
198+
}
199+
200+
return platforms.IsolateState{}, &platforms.PlatformError{
201+
Message: "unable to get isolate " + name,
202+
Err: err,
203+
}
204+
}
205+
206+
return row, nil
207+
}
208+
186209
func (p Postgres) InspectorTraces(id uint) ([]platforms.Trace, error) {
187210
traces, err := fetchMany(p.pool, `
188211
SELECT id, isolate, key, before_pc, after_pc, line_before, line_after,

pkg/runtimes/dupher/blocks.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ func Goto(line int, name string) GotoBlock {
110110
func Impure(line int, stmt func(Context)) AwaitBlock {
111111
return Await(line,
112112
func(ctx Context) (platforms.Event, error) {
113-
return platforms.CheckpointEvent{Id: ctx.GenKey()}, nil
113+
key := "impure-" + ctx.GenKey()
114+
115+
return platforms.CheckpointEvent{Id: key}, nil
114116
},
115117
func(ctx Context, _ platforms.EventNotify) error {
116118
stmt(ctx)
@@ -131,12 +133,12 @@ func SubProgram(
131133
return nil, err
132134
}
133135

134-
id := ctx.GenKey()
136+
key := "spawn-" + program + "-" + ctx.GenKey()
135137

136138
return platforms.SpawnEvent{
137-
Id: id,
139+
Id: key,
138140
Program: program,
139-
Name: program + "-" + id,
141+
Name: key,
140142
Args: serArgs,
141143
}, nil
142144
},
@@ -149,10 +151,11 @@ func SubProgram(
149151
func Chan(line int, ret func(Context, string)) AwaitBlock {
150152
return Await(line,
151153
func(ctx Context) (platforms.Event, error) {
152-
id := ctx.GenKey()
153-
ret(ctx, id)
154+
key := "chan-" + ctx.GenKey()
155+
156+
ret(ctx, key)
154157

155-
return platforms.ChannelCreateEvent{Id: id}, nil
158+
return platforms.ChannelCreateEvent{Id: key}, nil
156159
},
157160
func(ctx Context, _ platforms.EventNotify) error {
158161
return nil
@@ -168,8 +171,10 @@ func Send(line int, id func(Context) string, value func(Context) any) AwaitBlock
168171
return nil, err
169172
}
170173

174+
key := "chansend-" + ctx.GenKey()
175+
171176
return platforms.ChannelSendEvent{
172-
Id: id(ctx),
177+
Id: key,
173178
Value: data,
174179
}, nil
175180
},
@@ -205,11 +210,12 @@ func WaitGroup(
205210
) AwaitBlock {
206211
return Await(line,
207212
func(ctx Context) (platforms.Event, error) {
208-
id := ctx.GenKey()
209-
ret(ctx, id)
213+
key := "wg-" + ctx.GenKey()
214+
215+
ret(ctx, key)
210216

211217
return platforms.WaitGroupCreateEvent{
212-
Id: id,
218+
Id: key,
213219
Value: value(ctx),
214220
}, nil
215221
},
@@ -261,10 +267,11 @@ func Wait(line int, id func(Context) string) AwaitBlock {
261267
func Mutex(line int, ret func(Context, string)) AwaitBlock {
262268
return Await(line,
263269
func(ctx Context) (platforms.Event, error) {
264-
id := ctx.GenKey()
265-
ret(ctx, id)
270+
key := "mutex-" + ctx.GenKey()
271+
272+
ret(ctx, key)
266273

267-
return platforms.MutexCreateEvent{Id: id}, nil
274+
return platforms.MutexCreateEvent{Id: key}, nil
268275
},
269276
func(ctx Context, _ platforms.EventNotify) error {
270277
return nil
@@ -314,6 +321,7 @@ func RecvAny(
314321
},
315322
}
316323
}
324+
317325
return AwaitBlock{line: line, futs: futs}
318326
}
319327

pkg/runtimes/dython/deepslate/blocks.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,12 @@ def impure_block(
169169
def _trigger(ctx: Context, notify: EventNotify) -> None:
170170
stmt(ctx)
171171

172-
return await_block(
173-
line,
174-
lambda ctx: CheckpointEvent(id=ctx.gen_key()),
175-
_trigger,
176-
)
172+
def _start(ctx: Context) -> Event:
173+
key = "impure-" + ctx.gen_key()
174+
175+
return CheckpointEvent(id=key)
176+
177+
return await_block(line, _start, _trigger)
177178

178179

179180
def sub_program(
@@ -186,12 +187,12 @@ def _start(ctx: Context) -> Event:
186187
child_ctx = Context(vars=args)
187188
ser_args = ser_ctx(child_ctx)
188189

189-
id_ = ctx.gen_key()
190+
key = "spawn-" + program_name + "-" + ctx.gen_key()
190191

191192
return SpawnEvent(
192-
id=id_,
193+
id=key,
193194
program=program_name,
194-
name=program_name + "-" + id_,
195+
name=key,
195196
args=ser_args,
196197
)
197198

@@ -203,10 +204,11 @@ def _trigger(ctx: Context, notify: EventNotify) -> None:
203204

204205
def chan(line: int, ret: Callable[[Context, str], None]) -> AwaitBlock:
205206
def _start(ctx: Context) -> Event:
206-
id_ = ctx.gen_key()
207-
ret(ctx, id_)
207+
key = "chan-" + ctx.gen_key()
208+
209+
ret(ctx, key)
208210

209-
return ChannelCreateEvent(id=id_)
211+
return ChannelCreateEvent(id=key)
210212

211213
def _trigger(ctx: Context, notify: EventNotify) -> None:
212214
pass
@@ -220,7 +222,10 @@ def send(
220222
value: Callable[[Context], Any],
221223
) -> AwaitBlock:
222224
def _start(ctx: Context) -> Event:
223-
return ChannelSendEvent(id=id(ctx), value=msgspec.msgpack.encode(value(ctx)))
225+
return ChannelSendEvent(
226+
id=id(ctx),
227+
value=msgspec.msgpack.encode(value(ctx)),
228+
)
224229

225230
def _trigger(ctx: Context, notify: EventNotify) -> None:
226231
pass
@@ -287,10 +292,11 @@ def wait_group(
287292
ret: Callable[[Context, str], None],
288293
) -> AwaitBlock:
289294
def _start(ctx: Context) -> Event:
290-
id_ = ctx.gen_key()
291-
ret(ctx, id_)
295+
key = "wg-" + ctx.gen_key()
296+
297+
ret(ctx, key)
292298

293-
return WaitGroupCreateEvent(id=id_, value=value(ctx))
299+
return WaitGroupCreateEvent(id=key, value=value(ctx))
294300

295301
def _trigger(ctx: Context, notify: EventNotify) -> None:
296302
pass
@@ -334,9 +340,11 @@ def _trigger(ctx: Context, notify: EventNotify) -> None:
334340

335341
def mutex(line: int, ret: Callable[[Context, str], None]) -> AwaitBlock:
336342
def _start(ctx: Context) -> Event:
337-
id_ = ctx.gen_key()
338-
ret(ctx, id_)
339-
return MutexCreateEvent(id=id_)
343+
key = "mutex-" + ctx.gen_key()
344+
345+
ret(ctx, key)
346+
347+
return MutexCreateEvent(id=key)
340348

341349
def _trigger(ctx: Context, notify: EventNotify) -> None:
342350
pass

0 commit comments

Comments
 (0)