feat(site-runtime): ScriptLogger (Log global), TraceStepScope, TraceCapturingLogger (D4-D7)
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts;
|
||||
|
||||
/// <summary>
|
||||
/// Flow Debugger step logs (design 2026-09-09 D6): the ambient "which step is running right now"
|
||||
/// marker used to attribute runtime-sourced log lines to a step node.
|
||||
///
|
||||
/// <para>A <c>ScriptLog</c> row names its owning step explicitly (D2), but the runtime lines the
|
||||
/// node logs on the script's behalf are produced deep inside a helper — the helper knows its
|
||||
/// pre-minted step <c>EventId</c>, the logging call site does not. Rather than thread that id
|
||||
/// through every internal call, the helpers open a scope around their body and
|
||||
/// <see cref="ScriptLogger"/> reads <see cref="Current"/> when no explicit id is supplied.</para>
|
||||
///
|
||||
/// <para><see cref="AsyncLocal{T}"/> so the value flows through the helper's own awaits and
|
||||
/// nowhere else: it is captured by continuations started inside the scope and is invisible to
|
||||
/// concurrent runs on other threads of the script execution pool. Lines logged outside any scope
|
||||
/// see <see langword="null"/> and fall back to the execution's anchor row (D2).</para>
|
||||
/// </summary>
|
||||
public static class TraceStepScope
|
||||
{
|
||||
private static readonly AsyncLocal<Guid?> _current = new();
|
||||
|
||||
/// <summary>The step <c>EventId</c> owning the currently executing helper body, or <see langword="null"/> outside any scope.</summary>
|
||||
public static Guid? Current => _current.Value;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current step for the scope's lifetime; restores the previous value on dispose,
|
||||
/// so nested scopes (a helper calling another helper) unwind correctly.
|
||||
/// </summary>
|
||||
/// <param name="stepEventId">The pre-minted <c>EventId</c> of the step row this body belongs to.</param>
|
||||
/// <returns>A handle that restores the previous ambient value when disposed.</returns>
|
||||
public static IDisposable Enter(Guid stepEventId)
|
||||
{
|
||||
var prev = _current.Value;
|
||||
_current.Value = stepEventId;
|
||||
return new Restore(prev);
|
||||
}
|
||||
|
||||
/// <summary>Restores the ambient step id captured at <see cref="Enter"/> time.</summary>
|
||||
private sealed class Restore(Guid? prev) : IDisposable
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public void Dispose() => _current.Value = prev;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user