Logo FSBarV1_Archived

HubLog Module

Canonical in-process log-emit surface for the Hub. Multi-subscriber bidi gRPC stream (`StreamHubLog`) is layered on top in `ScriptingHub`; local GUI diagnostics continue to flow through the `HubEventBus` via the per-call-site bridging documented in research.md §R8. Zero-overhead when no subscriber is attached: `emit` gates on a single `Volatile.Read` of the subscriber count before any `LogEntry` allocation, timestamp read, or message formatting (R1). Subscriber fan-out mirrors the `ScriptingHub` pattern: per- subscriber `BoundedChannel` with `BoundedChannelFullMode.DropOldest`, capacity 256 (R2). Dropped counts are carried on the *next* delivered entry's `DroppedSinceLast` field. Thread-safety: `emit` is fully lock-free on the hot path; `attach` / `detach` serialize on a single mutex that `emit` never takes.

Types

Type Description

AttachOutcome

Outcome of an `attach` call. `Rejected` when the subscriber cap (`HubSettings.MaxLogStreamSubscribers`) would be exceeded (FR-015a).

CorrelationId

Opaque correlation ID re-exported from `FSBar.Hub.CorrelationId`. Carried on every `LogEntry` whose emitter ran under a gRPC-interceptor-established scope.

LogCategory

Closed enumeration of Hub subsystems that emit on the log stream. Adding a case is an additive surface-area change (new baseline line + proto enum extension at position 10+).

LogEntry

One observation. Public shape — the fields map 1:1 onto `LogEntryMessage` on the wire, except `sequence` which is assigned per-subscriber by the wire mapper in `ScriptingHub`.

LogFilter

Effective per-subscriber filter. Immutable; mutated by replacing the subscriber's reference atomically (R4).

LogSeverity

Severity levels, orderable so a subscriber can specify a floor (`entry.Severity >= minSeverity`).

Subscription

Subscription handle. Disposing detaches the subscriber and completes the channel writer within 1 s (FR-013).

T

Opaque handle for the log bus. One per Hub process, created by `create` and disposed at shutdown. All subscribers share one bus. Implements `System.IDisposable`; dispose cancels every subscriber `CancellationTokenSource`, completes the per- subscriber channel writers, and guarantees resource release within 1 s (FR-013).

Functions and values

Function or value Description

attach arg1 clientLabel filter cancellationToken

Full Usage: attach arg1 clientLabel filter cancellationToken

Parameters:
Returns: AttachOutcome

Attach a new subscriber with the given filter and client label. Returns `Rejected` when the current subscriber count equals `HubSettings.MaxLogStreamSubscribers`.

arg0 : T
clientLabel : string
filter : LogFilter
cancellationToken : CancellationToken
Returns: AttachOutcome

availablePresets

Full Usage: availablePresets

Returns: Map<string, LogFilter>

Hub-shipped presets. Case-insensitive lookup; canonical keys are lowercase. Current set: `session-lifecycle`, `admin-channel`, `scripting-wire`.

Returns: Map<string, LogFilter>

create events settings

Full Usage: create events settings

Parameters:
Returns: T

Construct a fresh log bus. The supplied `HubSettings.HubSettings` thunk is invoked each time `attach` checks the cap so operator edits to `MaxLogStreamSubscribers` take effect on the next attach without requiring a bus rebuild. The supplied `IHubEventSink` is retained only for the `DiagnosticsLine` bridge (R8 — emitting overflow warnings etc. back into the existing GUI diagnostics pane). Log entries themselves do NOT fan out through the event bus.

events : IHubEventSink
settings : unit -> HubSettings
Returns: T

defaultFilter

Full Usage: defaultFilter

Returns: LogFilter

Default filter applied when a client sends an empty filter request: all categories, `Info` severity floor (FR-005a).

Returns: LogFilter

emit arg1 category severity sessionId scriptingClientId buildMessage

Full Usage: emit arg1 category severity sessionId scriptingClientId buildMessage

Parameters:

Emit one log entry. Non-blocking; O(1) work when no subscriber is attached (R1). The `buildMessage` thunk is invoked only after the filter-pass gate has confirmed at least one subscriber wants the entry, so string formatting cost is paid lazily. `sessionId` and `scriptingClientId` are passed explicitly by the emitter — `CorrelationId` is read implicitly from `CorrelationId.current ()` at emit time.

arg0 : T
category : LogCategory
severity : LogSeverity
sessionId : Guid option
scriptingClientId : Guid option
buildMessage : unit -> string

emitFromDiagnosticsLine arg1 category severity sessionId scriptingClientId message

Full Usage: emitFromDiagnosticsLine arg1 category severity sessionId scriptingClientId message

Parameters:

Bridge helper: `HubEvent.DiagnosticsLine` call sites invoke this in addition to the existing event-bus publish, passing the caller's owning category. Maps `HubEvents.Severity.Info/Warning/Error` onto `LogSeverity.Info/Warning/Error` and delegates to `emit`.

arg0 : T
category : LogCategory
severity : Severity
sessionId : Guid option
scriptingClientId : Guid option
message : string

emitSimple arg1 category severity buildMessage

Full Usage: emitSimple arg1 category severity buildMessage

Parameters:

Convenience wrapper with no session or client context. Equivalent to `emit bus category severity None None buildMessage`.

arg0 : T
category : LogCategory
severity : LogSeverity
buildMessage : unit -> string

exchangeDroppedSinceLast arg1 subscriberId

Full Usage: exchangeDroppedSinceLast arg1 subscriberId

Parameters:
    arg0 : T
    subscriberId : Guid

Returns: int

Atomically read and reset the per-subscriber drop counter to 0. Returns 0 if the subscriber is no longer attached. Used by the wire mapper to stamp `LogEntryMessage.dropped_since_last`.

arg0 : T
subscriberId : Guid
Returns: int

nextSequenceFor arg1 subscriberId

Full Usage: nextSequenceFor arg1 subscriberId

Parameters:
    arg0 : T
    subscriberId : Guid

Returns: uint64

Increment the per-subscriber wire sequence counter and return the new value (starts at 1). Returns 0 if the subscriber is no longer attached. Used by the `ScriptingHub.StreamHubLog` mapper to stamp `LogEntryMessage.sequence` per subscriber.

arg0 : T
subscriberId : Guid
Returns: uint64

resolveFilter categories minSeverity presetName

Full Usage: resolveFilter categories minSeverity presetName

Parameters:
Returns: Result<LogFilter, string>

Resolve a wire-level filter request to a `LogFilter`. Returns `Error msg` when the preset is unknown or a category is `Unspecified` / a string name is unknown (FR-007).

categories : LogCategory list
minSeverity : LogSeverity option
presetName : string option
Returns: Result<LogFilter, string>

subscriberCount arg1

Full Usage: subscriberCount arg1

Parameters:
    arg0 : T

Returns: int

Current subscriber count. Exposed for tests + Settings-tab diagnostics.

arg0 : T
Returns: int

truncateUtf8 message

Full Usage: truncateUtf8 message

Parameters:
    message : string

Returns: string

Byte-safe UTF-8 truncation at 8 KiB per FR-012a / R6. Public for tests; emit callers should not invoke directly (emit calls this internally post-filter-gate).

message : string
Returns: string

updateFilter arg1 subscriberId newFilter

Full Usage: updateFilter arg1 subscriberId newFilter

Parameters:
Returns: Result<unit, string>

Atomically replace the filter for an existing subscriber. Returns `Ok ()` when the subscriber is found; `Error msg` when it has already been detached.

arg0 : T
subscriberId : Guid
newFilter : LogFilter
Returns: Result<unit, string>

Type something to start searching.