SignalR Logging¶
All jobs — both GUI and GUI-less — report progress through
the IJobReporter interface. Signals are delivered to the frontend in real time via SignalR
and rendered in the log/progress area of the job page.
IJobReporter¶
EnergyAtlasCore/Job/Job.cs
1 2 3 4 | |
Every job receives an IJobReporter (either as a constructor argument for
GUI-less jobs, or as the second parameter of
Run(TInput input, IJobReporter reporter) for GUI jobs).
Implementations¶
| Class | Use |
|---|---|
SignalRJobReporter |
Production: sends signals via SignalR hub in-order |
NullJobReporter |
Unit testing, silent execution, console app |
JobSignal¶
EnergyAtlasCore/Job/Job.cs
A record with the following fields:
| Field | Type | Description |
|---|---|---|
Id |
string |
Unique signal ID (auto-generated with GUID suffix) |
Type |
JobSignalType |
Signal category (see below) |
Done |
bool? |
For Binary signals: false = working, true = done |
Percent |
double? |
For Progress signals: 0–100 |
Message |
string? |
Human-readable text |
Signal types (JobSignalType)¶
| Value | Name | Purpose |
|---|---|---|
| 0 | Binary |
Working/done indicator (spinner) |
| 1 | Progress |
Percentage-based progress bar |
| 2 | Log |
Free-form text message |
| 3 | Warning |
Warning message |
| 4 | Exception |
Error message |
Factory methods¶
| Method | Type | Notes |
|---|---|---|
JobSignal.Log(message) |
Log | General log line |
JobSignal.Start(message) |
Log | Prefixes message with "STARTING: " |
JobSignal.Complete(id) |
Log | Message = "JOB COMPLETED." |
JobSignal.Warning(message) |
Warning | Yellow warning |
JobSignal.Error(message) |
Exception | Red error |
JobSignal.Binary(id, message, done) |
Binary | Internal — use BinaryProgress instead |
JobSignal.Progress(id, percent, message) |
Progress | Internal — use TQDM instead |
BinaryProgress (working/done spinner)¶
EnergyAtlasCore/Job/Job.cs
A disposable wrapper that emits Binary signals. Shows a spinner while work is in progress,
then a "completed in Xs" message when done.
Usage¶
1 2 3 4 5 | |
Behaviour¶
- Constructor: Emits
Binary(id, label, done: false)→ frontend shows spinning indicator. - Dispose / Complete(): Emits
Binary(id, "label completed in Xs", done: true)→ spinner stops.
Frontend rendering¶
1 2 | |
The frontend maintains a Map<id, div> of binary lines. When done === false, the line
gets a spinning character appended. When done === true, the final message replaces it and
the spinner stops.
TQDM (percentage progress bar)¶
EnergyAtlasCore/Job/Job.cs
Named after Python's famous tqdm library. A disposable wrapper that emits Progress signals with percentage, elapsed time, and ETA.
tqdmmeans "progress" in Arabic (taqadum, تقدّم) and is an abbreviation for "I love you so much" in Spanish (te quiero demasiado).
Usage¶
1 2 3 4 5 6 7 8 9 | |
Behaviour¶
- Constructor: Emits
Binary(id, label, done: false)(initial spinner) +Progress(id, 0%, ...). - Increment(): Emits
Progress(id, percent, "label (done/total) | elapsed Xs | ETA Ys"). - Thread-safe (uses
Interlocked). - Throttled to avoid UI spam.
- Dispose: Forces progress to 100%, then emits
Binary(id, "label completed in Xs", done: true).
Frontend rendering¶
1 | |
The frontend maintains a Map<id, div> of progress lines. Each Progress signal updates
the same line with an ASCII bar [###---], percentage, and the message text.
Log, Warning, Error¶
These are simple text signals rendered as lines in the log container.
Usage¶
1 2 3 4 5 | |
Frontend rendering¶
| Type | CSS class | Prefix | Appearance |
|---|---|---|---|
| Log (type 2) | log-line |
(none) | Normal text |
| Warning (type 3) | log-line warning |
[WARNING] |
Yellow/amber text |
| Exception (type 4) | log-line error |
[ERROR] |
Red text |
Special log messages¶
"OUTPUT_JSON:{...}"— Not displayed as a log line. Parsed by the frontend to render the output section (text, charts, artefacts)."JOB COMPLETED."— Updates the status badge to "Completed".
SignalR delivery¶
SignalRJobReporter¶
The production reporter sends signals through SignalR in creation order:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
Key properties:
- Ordered: Signals are chained sequentially (even from parallel threads).
- Stored: All signals are persisted in JobRuntimeState.Signals for replay.
- Resilient: If a send fails, the signal is still in the store.
JobHub (client connection)¶
When a client calls JoinJob(jobId):
1. The client joins the SignalR group for that job.
2. All stored signals are replayed to the caller (so late-joining clients see full history).
Frontend connection¶
1 2 3 4 | |
Recommended patterns¶
Phase-based work with BinaryProgress¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Counted iteration with TQDM¶
1 2 3 4 5 6 7 8 9 | |
Mixed progress and logging¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | |
Summary¶
| What to use | When | Type emitted |
|---|---|---|
BinaryProgress |
Wrap a phase of work (no item count) | Binary (0) |
TQDM |
Iterate over counted items | Progress (1) + Binary (0) |
JobSignal.Log(...) |
Informational text | Log (2) |
JobSignal.Warning(...) |
Non-fatal issue | Warning (3) |
JobSignal.Error(...) |
Fatal failure | Exception (4) |
JobSignal.Start(...) |
Job start announcement | Log (2) |
JobSignal.Complete() |
Job completion marker | Log (2) |
See also¶
- GUI Job — auto-generated job pages with inputs, outputs, and logging examples
- GUI-less Job — one-click jobs with logging examples
- Working with Local Files — file picking and artifact sink
- Execution Modes — browser vs local mode