Skip to content

Commit 675e6a4

Browse files
authored
Merge pull request #377 from JuliaParallel/jps/update-viz-docs
Update scheduler visualization docs
2 parents be403f3 + 345b70b commit 675e6a4

File tree

4 files changed

+40
-37
lines changed

4 files changed

+40
-37
lines changed

docs/src/logging.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ called. Let's construct one:
3232

3333
```julia
3434
ctx = Context()
35-
ml = TimspanLogging.MultiEventLog()
35+
ml = TimespanLogging.MultiEventLog()
3636

3737
# Add the BytesAllocd consumer to the log as `:bytes`
3838
ml[:bytes] = Dagger.Events.BytesAllocd()

docs/src/scheduler-visualization.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,24 @@ easiest way to get started with the web dashboard for new users.
1616
For manual usage, the following snippet of code will suffice:
1717

1818
```julia
19+
using Dagger, DaggerWebDash, TimespanLogging
20+
1921
ctx = Context() # or `ctx = Dagger.Sch.eager_context()` for eager API usage
20-
ml = Dagger.MultiEventLog()
22+
ml = TimespanLogging.MultiEventLog()
2123

2224
## Add some logging events of interest
2325

24-
ml[:core] = Dagger.Events.CoreMetrics()
25-
ml[:id] = Dagger.Events.IDMetrics()
26-
ml[:timeline] = Dagger.Events.TimelineMetrics()
26+
ml[:core] = TimespanLogging.Events.CoreMetrics()
27+
ml[:id] = TimespanLogging.Events.IDMetrics()
28+
ml[:timeline] = TimespanLogging.Events.TimelineMetrics()
2729
# ...
2830

2931
# (Optional) Enable profile flamegraph generation with ProfileSVG
3032
ml[:profile] = DaggerWebDash.ProfileMetrics()
3133
ctx.profile = true
3234

3335
# Create a LogWindow; necessary for real-time event updates
34-
lw = Dagger.Events.LogWindow(20*10^9, :core)
36+
lw = TimespanLogging.Events.LogWindow(20*10^9, :core)
3537
ml.aggregators[:logwindow] = lw
3638

3739
# Create the D3Renderer server on port 8080
@@ -40,20 +42,20 @@ d3r = DaggerWebDash.D3Renderer(8080)
4042
## Add some plots! Rendered top-down in order
4143

4244
# Show an overview of all generated events as a Gantt chart
43-
push!(d3r, GanttPlot(:core, :id, :esat, :psat; title="Overview"))
45+
push!(d3r, DaggerWebDash.GanttPlot(:core, :id, :esat, :psat; title="Overview"))
4446

4547
# Show various numerical events as line plots over time
46-
push!(d3r, LinePlot(:core, :wsat, "Worker Saturation", "Running Tasks"))
47-
push!(d3r, LinePlot(:core, :loadavg, "CPU Load Average", "Average Running Threads"))
48-
push!(d3r, LinePlot(:core, :bytes, "Allocated Bytes", "Bytes"))
49-
push!(d3r, LinePlot(:core, :mem, "Available Memory", "% Free"))
48+
push!(d3r, DaggerWebDash.LinePlot(:core, :wsat, "Worker Saturation", "Running Tasks"))
49+
push!(d3r, DaggerWebDash.LinePlot(:core, :loadavg, "CPU Load Average", "Average Running Threads"))
50+
push!(d3r, DaggerWebDash.LinePlot(:core, :bytes, "Allocated Bytes", "Bytes"))
51+
push!(d3r, DaggerWebDash.LinePlot(:core, :mem, "Available Memory", "% Free"))
5052

5153
# Show a graph rendering of compute tasks and data movement between them
5254
# Note: Profile events are ignored if absent from the log
53-
push!(d3r, GraphPlot(:core, :id, :timeline, :profile, "DAG"))
55+
push!(d3r, DaggerWebDash.GraphPlot(:core, :id, :timeline, :profile, "DAG"))
5456

5557
# TODO: Not yet functional
56-
#push!(d3r, ProfileViewer(:core, :profile, "Profile Viewer"))
58+
#push!(d3r, DaggerWebDash.ProfileViewer(:core, :profile, "Profile Viewer"))
5759

5860
# Add the D3Renderer as a consumer of special events generated by LogWindow
5961
push!(lw.creation_handlers, d3r)

lib/DaggerWebDash/Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ version = "0.1.2"
66
[deps]
77
Dagger = "d58978e5-989f-55fb-8d15-ea34adc7bf54"
88
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
9+
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
910
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
1011
MemPool = "f9f48841-c794-520a-933b-121f7ba6ed94"
1112
Mux = "a975b10e-0019-58db-a62f-e48ff68538c9"
@@ -17,6 +18,7 @@ TimespanLogging = "a526e669-04d3-4846-9525-c66122c55f63"
1718

1819
[compat]
1920
Dagger = "0.16"
21+
HTTP = "1.7"
2022
JSON3 = "1"
2123
MemPool = "0.3, 0.4"
2224
Mux = "0.7, 1"

lib/DaggerWebDash/src/d3.jl

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using Mux, MemPool, Distributed, Sockets
1+
using Mux, Sockets
2+
import HTTP
3+
import HTTP: WebSockets
4+
using MemPool, Distributed
25

36
struct LinePlot
47
core_key::Symbol
@@ -172,22 +175,22 @@ function client_handler(sock, id, port, port_range, config_updated, config, seek
172175
if id != myid()
173176
fsock_ready = Base.Event()
174177
worker_host, worker_port = worker_host_port(id, port, port_range)
175-
Mux.HTTP.WebSockets.open("ws://$worker_host:$worker_port/data_feed") do _fsock
178+
WebSockets.open("ws://$worker_host:$worker_port/data_feed") do _fsock
176179
fsock = _fsock
177180
@debug "D3R forwarder for $id ready"
178181
notify(fsock_ready)
179-
while !eof(fsock) && isopen(fsock)
182+
while true
180183
try
181-
bytes = readavailable(fsock)
184+
bytes = WebSockets.receive(fsock)
182185
if length(bytes) == 0
183186
sleep(0.1)
184187
continue
185188
end
186189
data = String(bytes)
187190
#@info "D3R forwarder for $id received data"
188-
write(sock, data)
191+
WebSockets.send(sock, data)
189192
catch err
190-
if err isa Mux.WebSockets.WebSocketClosedError || err isa Base.IOError
193+
if err isa WebSockets.WebSocketError && err.message isa WebSockets.CloseFrameBody
191194
# Force-close client and forwarder
192195
@async close(sock)
193196
@async close(fsock)
@@ -203,25 +206,25 @@ function client_handler(sock, id, port, port_range, config_updated, config, seek
203206
end
204207
if id == myid()
205208
@debug "D3R client for $id sending initial config"
206-
write(sock, JSON3.write((;cmd="data", payload=sanitize(D3R_LOGS[port]))))
209+
WebSockets.send(sock, JSON3.write((;cmd="data", payload=sanitize(D3R_LOGS[port]))))
207210
_workers = workers()
208211
if !(myid() in _workers)
209212
# FIXME: Get this from the Context
210213
_workers = vcat(myid(), _workers)
211214
end
212-
write(sock, JSON3.write((;cmd="config", payload=sanitize((;myid=myid(),workers=_workers,ctxs=config)))))
215+
WebSockets.send(sock, JSON3.write((;cmd="config", payload=sanitize((;myid=myid(),workers=_workers,ctxs=config)))))
213216
end
214217
push!(get!(()->[], D3R_CLIENT_SOCKETS[port], id), sock)
215218
@debug "D3R client for $id ready"
216-
while !eof(sock) && isopen(sock)
219+
while true
217220
try
218-
data = String(read(sock))
221+
data = String(WebSockets.receive(sock))
219222
@debug "D3R client for $id received: $data"
220223
if id == myid()
221224
#= FIXME
222225
if config_updated[]
223226
config_updated[] = false
224-
write(sock, JSON3.write((;cmd="config", payload=sanitize(config))))
227+
WebSockets.send(sock, JSON3.write((;cmd="config", payload=sanitize(config))))
225228
end
226229
=#
227230
if seek_store !== nothing
@@ -231,7 +234,7 @@ function client_handler(sock, id, port, port_range, config_updated, config, seek
231234
for (idx,key) in enumerate(Tables.columnnames(raw_logs))
232235
logs[key] = Tables.columns(raw_logs)[idx]
233236
end
234-
write(sock, JSON3.write((;cmd="data", payload=sanitize(logs))))
237+
WebSockets.send(sock, JSON3.write((;cmd="data", payload=sanitize(logs))))
235238
continue
236239
end
237240
m = match(r"seek\(([0-9]*),([0-9]*)\)", data)
@@ -242,19 +245,19 @@ function client_handler(sock, id, port, port_range, config_updated, config, seek
242245
for (idx,key) in enumerate(Tables.columnnames(raw_logs))
243246
logs[key] = Tables.columns(raw_logs)[idx]
244247
end
245-
write(sock, JSON3.write((;cmd="data", payload=sanitize(logs))))
248+
WebSockets.send(sock, JSON3.write((;cmd="data", payload=sanitize(logs))))
246249
continue
247250
end
248251
end
249252
if data == "data"
250-
write(sock, JSON3.write((;cmd="data", payload=sanitize(D3R_LOGS[port]))))
253+
WebSockets.send(sock, JSON3.write((;cmd="data", payload=sanitize(D3R_LOGS[port]))))
251254
end
252255
else
253256
@debug "D3R client sending to forwarder: $data"
254-
write(fsock, data)
257+
WebSockets.send(fsock, data)
255258
end
256259
catch err
257-
if err isa Mux.WebSockets.WebSocketClosedError || err isa Base.IOError
260+
if err isa WebSockets.WebSocketError && err.message isa WebSockets.CloseFrameBody
258261
idx = findfirst(x->x==sock, D3R_CLIENT_SOCKETS[port][id])
259262
if idx !== nothing
260263
deleteat!(D3R_CLIENT_SOCKETS[port][id], idx)
@@ -273,11 +276,9 @@ end
273276
function TimespanLogging.Events.creation_hook(d3r::D3Renderer, log)
274277
for sock in get!(()->[], get!(()->Dict{Int,Vector{Any}}(), D3R_CLIENT_SOCKETS, d3r.port), myid())
275278
try
276-
if isopen(sock)
277-
write(sock, JSON3.write((;cmd="add", payload=sanitize(log))))
278-
end
279+
WebSockets.send(sock, JSON3.write((;cmd="add", payload=sanitize(log))))
279280
catch err
280-
if err isa Mux.WebSockets.WebSocketClosedError
281+
if err isa WebSockets.WebSocketError && err.message isa WebSockets.CloseFrameBody
281282
continue
282283
end
283284
rethrow(err)
@@ -287,11 +288,9 @@ end
287288
function TimespanLogging.Events.deletion_hook(d3r::D3Renderer, idx)
288289
for sock in get!(()->[], get!(()->Dict{Int,Vector{Any}}(), D3R_CLIENT_SOCKETS, d3r.port), myid())
289290
try
290-
if isopen(sock)
291-
write(sock, JSON3.write((;cmd="delete", payload=idx)))
292-
end
291+
WebSockets.send(sock, JSON3.write((;cmd="delete", payload=idx)))
293292
catch err
294-
if err isa Mux.WebSockets.WebSocketClosedError
293+
if err isa WebSockets.WebSocketError && err.message isa WebSockets.CloseFrameBody
295294
continue
296295
end
297296
rethrow(err)

0 commit comments

Comments
 (0)