A traced run carries every Log.* line a script writes, every warning the runtime logs on the script's behalf, and the full exception a failing step threw. Each lands on its own node: a count badge on the node, a Log tab in the detail panel, and run-wide error and warning counts in the status strip. Live and Replay read the same rows.
at Submission#0.<<Initialize>>d__0.MoveNext() in ProcessRecipeDownload:line 41 at ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts.ScriptRunLauncher.RunScriptAsync(…) Inner exception: none
| Time (UTC) | Level | Source | Message |
|---|---|---|---|
| 14:02:11.204 | info | script | Recipe 42 requested for line L3 by flow-debugger |
| 14:02:11.206 | debug | script | Writing header attributes then DownloadRequest |
| 14:02:12.861 | info | script | Galaxy answered: RecipeProcessedFlag = true, ResultCode = 7 |
| 14:02:12.862 | warn | script | ResultCode 7 is outside the accepted set {0, 1} |
| 14:02:12.870 | error | script | Rejecting recipe 42 (code 7) — see exception above |
| 14:02:12.929 | warn | runtime | Log truncated inline: 0 lines dropped (shown only when the per-run cap is hit) |
Nothing moves on a node that has no log lines. A node with lines gains a count badge in the footer, highest severity first; a failed node swaps its subtitle for the exception's type and message.
One new global, Log, on every script surface (site scripts, shared scripts, inbound API methods, the Test Run editor). Always forwards to the node's logger; becomes a trace row only when the run is traced, so untraced production runs add no audit volume.
// ProcessRecipeDownload — site Call script (excerpt) var recipeId = Parameters.Get<int>("RecipeId"); Log.Info($"Recipe {recipeId} requested for line {Parameters.Get<string>("Line")} by {Parameters.Get<string>("Requester")}"); Log.Debug("Writing header attributes then DownloadRequest"); await Children["DelmiaReceiver"].SetAsync("RecipeId", recipeId); // … writes, wait … var code = await Children["DelmiaReceiver"].GetAsync<int>("ResultCode"); Log.Info($"Galaxy answered: RecipeProcessedFlag = true, ResultCode = {code}"); if (code is not (0 or 1)) { Log.Warn($"ResultCode {code} is outside the accepted set {{0, 1}}"); Log.Error($"Rejecting recipe {recipeId} (code {code})"); throw new InvalidOperationException($"Recipe {recipeId} rejected by Galaxy (code {code})"); } Log.Warn("Recoverable problem", caughtException); // an exception on a line renders as an expandable chip
| Produced by | Source | Lands on | How |
|---|---|---|---|
Log.* in a site script (incl. inline shared scripts) | script | That execution's Script run node | One ScriptTrace.ScriptLog row per line, keyed by the run's ExecutionId; no step id |
Log.* in an inbound API method script | script | The Inbound node (or the debugger's route-call root for a script entry) | Same row, written centrally with the inbound ExecutionId; inline on a Live run through the runner's collector |
| The runtime's own warnings while a helper step runs (write, wait, sync API call) | runtime | That step's node | The helper pre-mints its step's event id and holds it in an ambient scope; the context's logger copies Information + lines into a row stamped stepEventId |
| Runtime warnings outside any helper step | runtime | The Script run node | No scope active → falls back to the execution anchor |
| The exception that failed a script run | — | The Script run node's exception block | Not a log row: ScriptRun.errorDetail now carries ex.ToString() (type, message, stack, inner); the inbound row gets the same for a central method failure |
| Log lines from other actors on the node (instance actor, DCL) | — | Not captured in v1 | No execution-id enrichment exists on the node loggers; recorded as the follow-up, not attempted here |
ScriptLog kind in the existing ScriptTrace channel rides the collector for Live and the audit store for Replay, with redaction, retention and the site 7-day purge applying unchanged. The graph builder folds them into their owning step; they are never drawn as nodes.Log.* always writes to the node's ILogger at the given level (so it shows in Serilog and the site log as usual) and emits a row only when the run is traced. TraceAllCalls methods therefore gain lines in Replay at ~1 row per line.stepEventId or it belongs to the execution's anchor step. Steps whose row is written later by another actor (cached calls, notifications) keep the fallback.errorDetail costs one argument on the site and one internal field centrally; the HTTP caller still receives the safe SCRIPT_ERROR body.