ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Elsa.Diagnostics.StructuredLogs 数据模型深度解析:结构化日志事件的字段契约与实时链路设计

Elsa.Diagnostics.StructuredLogs 数据模型深度解析:结构化日志事件的字段契约与实时链路设计 后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载本指南以 specs/004-diagnostics-structured-logs/data-model.md 为核心系统讲解 Elsa 诊断模块Elsa.Diagnostics.StructuredLogs的六大核心数据实体及其在采集、脱敏、缓冲、订阅链路中的实际作用。读完本文你将掌握每个实体的完整字段语义、它们与源码中 C# 类型的一一对应关系以及如何通过配置项控制数据模型的容量与脱敏行为。一、数据模型总览六个实体如何构成完整链路Elsa.Diagnostics.StructuredLogs是 Elsa 诊断体系中的结构化日志模块它不采集 raw stdout/stderr只面向ILogger产生的语义化日志记录参见 spec.md 的 FR-009 与边界说明。其数据模型由六个实体协作完成采集 → 脱敏 → 缓冲 → 查询 → 实时推送的闭环实体角色生命周期StructuredLogEvent一条语义化日志记录核心载体短生命周期事件产生时被创建StructuredLogSource产生事件的进程/容器/Pod/机器身份长生命周期随进程存活而登记StructuredLogFilter最近查询与实时订阅的过滤条件每次查询/订阅创建StructuredLogProvider可插拔的事件来源抽象随应用生命周期注册StructuredLogRedactor事件离开后端前的脱敏处理器贯穿每次发布StructuredLogSubscription单条 SignalR 实时订阅状态随订阅连接创建/销毁从源码目录结构看这些实体分别落在 Models/、Contracts/、Providers/InMemory/、Services/ 与 RealTime/ 中与契约文档一一对应。二、StructuredLogEvent语义化日志事件的完整字段契约StructuredLogEvent是整条数据模型链路的核心实体对应源码 StructuredLogEvent.cs 中的 C# record 类型。原文档定义的全部字段如下结合源码补充了类型与默认值字段语义源码类型/默认值Id唯一事件标识符string默认Guid.NewGuid().ToString(N)Sequence由 provider/logger 路径分配的单调递增序号longTimestamp事件发生时间DateTimeOffsetReceivedAt后端接收时间与产生时间分离便于观测传输延迟DateTimeOffsetLevel结构化日志级别StructuredLogLevel枚举Categorylogger 类别通常是类型全名string非空EventIdMicrosoft 日志框架的数字事件 IDintEventName可选的 Microsoft 事件名称string?Message已渲染的消息文本string默认空串MessageTemplate原始消息模板来自{OriginalFormat}string?Exception已脱敏的异常摘要/详情StructuredLogException?Scopes活动 logging scope 中经脱敏的键值IDictionarystring, string?Properties结构化属性已剔除{OriginalFormat}IDictionarystring, string?TraceId/SpanId活动Activity的追踪标识为未来 OpenTelemetry 链路预留string?CorrelationId关联 ID可用时string?TenantId/WorkflowDefinitionId/WorkflowInstanceIdElsa 工作流上下文值可用时string?SourceId产生该事件的来源标识string非空2.1 消息模板与{OriginalFormat}的采集策略MessageTemplate是事件保持语义化的关键。设计决策记录在 research.md 中Microsoft 日志提供程序会通过名为{OriginalFormat}的结构化状态项暴露原始模板。模块把它单独提取为MessageTemplate字段并从Properties中剔除避免重复数据污染结构化属性同时不采用从渲染消息反推模板的方案因为渲染后的消息已经丢失占位符名称。对应功能需求 FR-011logger provider 必须在存在{OriginalFormat}时填充消息模板值。2.2 Trace/Span 字段为 OpenTelemetry 预留的稳定链接TraceId与SpanId直接取自活动Activity。spec 的 FR-020 明确要求这两个字段必须足够稳定以支持未来 Elsa.Diagnostics.OpenTelemetry 模块 的深链deep link能力。也就是说本模块只负责暴露关联字段trace waterfall、指标图表与 span 探索归未来的 OpenTelemetry 模块所有当前不越界。2.3 事件在 REST 契约中的完整形态结合 contracts/rest-api.md一个完整的StructuredLogEvent在最近日志查询响应中呈现如下注意字段名与数据模型一一对应{ items: [ { id: 01h..., sequence: 42, timestamp: 2026-05-10T12:00:00Z, receivedAt: 2026-05-10T12:00:00Z, level: Information, category: Elsa.Workflows.Runtime, eventId: 1001, eventName: WorkflowStarted, message: Workflow order-123 started, messageTemplate: Workflow {WorkflowInstanceId} started, exception: null, scopes: { TenantId: tenant-a }, properties: { WorkflowInstanceId: order-123 }, traceId: 4bf92f3577b34da6a3ce929d0e0e4736, spanId: 00f067aa0ba902b7, correlationId: corr-123, tenantId: tenant-a, workflowDefinitionId: orders, workflowInstanceId: order-123, sourceId: local } ], droppedCount: 0 }三、StructuredLogSource日志来源的进程级身份StructuredLogSource描述产生事件的后端进程、容器、Pod 或机器。字段集如下身份字段Id运行进程的稳定来源标识、Name显示名、MachineName、ProcessId、ProcessNameKubernetes/容器字段可用时PodName、Namespace、ContainerName、NodeName生命周期字段StartedAt来源启动时间、LastSeen最近活跃时间健康状态字段Status取值为unknown、healthy、stale、disconnected。在 REST 契约中来源列表接口GET /diagnostics/structured-logs/sources返回形如 rest-api.md 中的响应其中status为Healthy。READMEREADME.md指出即使使用默认的内存 provider只捕获当前进程的日志来源对象仍携带 Kubernetes/容器元数据使 Studio 能按来源过滤与展示来源状态由SourceHeartbeatTimeout控制——超过心跳超时未更新LastSeen即判定为Stale对应 README.md 中SourceHeartbeatTimeout→Stale的共享存储契约约定。四、StructuredLogFilter查询与订阅的统一过滤条件StructuredLogFilter同时服务于最近日志查询REST与实时订阅SignalR字段覆盖三大维度日志内容维度MinimumLevel包含式的最低级别含该级别及以上Levels精确级别集合与MinimumLevel二选一或组合使用CategoryPrefixlogger 类别前缀过滤Query跨消息、模板、类别、异常、scopes 与 properties 的自由文本过滤。上下文/关联维度TenantId、WorkflowDefinitionId、WorkflowInstanceId工作流上下文过滤TraceId、SpanId、CorrelationId追踪关联过滤SourceId来源过滤。时间与数量维度From/To时间范围Limit最近查询的条数上限由 options 钳制不能超过配置的MaxRecentLogQuerySize。关于Limit的钳制实现源码 StructuredLogsOptions.cs 提供了直接证据ClampRecentLogQueryTake(int? take)将take钳制在[0, MaxRecentLogQuerySize]区间负数视为 0从而保证查询构造不会因非法参数抛异常。这印证了数据模型中Limitrecent query limit clamped by options的行为定义。五、StructuredLogProvider可插拔的事件来源抽象StructuredLogProvider定义了模块与底层事件来源的边界完整接口契约见 contracts/provider-contract.mdpublic interface IStructuredLogProvider { ValueTask PublishAsync(StructuredLogEvent logEvent, CancellationToken cancellationToken default); ValueTaskRecentStructuredLogsResult GetRecentAsync(StructuredLogFilter filter, CancellationToken cancellationToken default); IAsyncEnumerableStructuredLogEvent SubscribeAsync(StructuredLogFilter filter, CancellationToken cancellationToken default); ValueTaskIReadOnlyCollectionStructuredLogSource ListSourcesAsync(CancellationToken cancellationToken default); }四个方法分别对应数据模型中的四项职责发布脱敏后的事件、返回最近事件及丢弃缓冲计数、流式输出实时事件及丢弃摘要、列出已知来源。扩展接口IStructuredLogStreamProvider进一步把丢弃摘要显式化public interface IStructuredLogStreamProvider : IStructuredLogProvider { IAsyncEnumerableStructuredLogStreamItem SubscribeWithDroppedEventsAsync(StructuredLogFilter filter, CancellationToken cancellationToken default); }默认实现是InMemoryStructuredLogProvider源码位于 Providers/InMemory/用有界环形缓冲保存脱敏事件用有界订阅者队列广播实时事件是开发环境与单节点宿主的默认 provider。契约文档同时强调外部 provider 可以通过实现该接口边界接入例如未来由插件提供分布式或持久化实现模块本身保持存储中立。六、StructuredLogRedactor在捕获路径出口执行的脱敏StructuredLogRedactor是安全边界的关键实体必须在缓冲与流式之前执行对应 spec 的 FR-023。其职责遮蔽 properties 与 scopes 中的敏感名称遮蔽消息与异常详情中的敏感文本模式在任何事件离开后端捕获路径前完成。接口定义同样在 provider-contract.md 中public interface IStructuredLogRedactor { StructuredLogEvent Redact(StructuredLogEvent logEvent); }默认脱敏规则由 StructuredLogsOptions.cs 配置分为两类默认敏感名称属性/scope 键名匹配不区分大小写匹配语义见 README 存储契约说明authorization, token, password, secret, api-key, apikey, cookie, connection-string, connectionstring默认敏感文本模式对消息、异常详情做正则遮蔽(?i)bearer\s[A-Za-z0-9._~/-] # Bearer token (?i)(password|secret|token|api[-_]?key)\s*[:]\s*[^\s,;] # keyvalue / key: value (?i)(AccountKey|SharedAccessKey)([^;\s]) # Azure 存储账号密钥这两组集合均可通过StructuredLogsOptions.SensitiveNames与SensitiveTextPatterns扩展。边缘场景见 spec提示脱敏可能移除原本用于过滤或追踪链接的字段配置时需权衡可观测性与安全性。七、StructuredLogSubscription实时订阅的运行时状态StructuredLogSubscription描述一条活的 SignalR 订阅包含连接标识connection ID当前过滤器StructuredLogFilter取消令牌用于终止订阅背压状态记录订阅者队列溢出与丢弃事件。关键能力是过滤器可热更新订阅建立后调用UpdateFilterAsync无需重连即可替换过滤条件。对应的 SignalR 契约见 contracts/signalr-hub.md客户端→服务端方法SubscribeAsync(StructuredLogFilter filter)创建或替换调用者的实时订阅UpdateFilterAsync(StructuredLogFilter filter)不重连地替换活跃过滤器UnsubscribeAsync()停止订阅并释放资源。服务端→客户端方法ReceiveLogEventAsync(StructuredLogEvent logEvent)推送事件ReceiveDroppedEventsAsync(StructuredLogDroppedEventSummary summary)推送丢弃摘要ReceiveSourceChangedAsync(StructuredLogSource source)来源变更通知。背压策略订阅者队列保持有界当订阅者消费跟不上时provider 对该订阅者丢弃事件并在稍后发送丢弃事件摘要保证慢消费者不会拖垮整个发布链路。这与数据模型中Reports dropped events when subscriber queues overflow及 spec 的 FR-014有界近期缓冲 有界订阅者行为 可见的丢弃计数完全一致。八、端到端链路从 ILogger 到 Studio 的一次事件旅程将六个实体串联起来一次日志事件的完整旅程如下应用代码调用ILogger.LogStructuredLogLoggerProviderLogging/捕获事件提取{OriginalFormat}作为MessageTemplate通过IExternalScopeProvider抓取活跃 scopes设计依据见 research.md并携带活动Activity的TraceId/SpanIdStructuredLogRedactor对事件执行脱敏在缓冲/流式之前FR-023IStructuredLogProvider.PublishAsync将脱敏后的StructuredLogEvent写入有界环形缓冲InMemoryStructuredLogStore并广播给各订阅者队列同时登记StructuredLogSource的来源心跳Studio 打开日志页时先通过 REST 接口POST /diagnostics/structured-logs/recent以StructuredLogFilter拉取最近事件Limit受MaxRecentLogQuerySize钳制再通过 SignalR 建立StructuredLogSubscription接收实时事件订阅者消费过慢时队列溢出事件被丢弃并以StructuredLogDroppedEventSummary形式告知客户端。此链路中 REST 端点与 SignalR Hub 的路由分别为/diagnostics/structured-logs/recent含sources与/elsa/hubs/diagnostics/structured-logs见 quickstart.md 与 rest-api.md。九、配置选项控制容量、心跳与脱敏数据模型的容量与安全行为均由 StructuredLogsOptions.cs 控制完整选项如下含默认值选项默认值作用RecentLogCapacity5_000有界近期事件缓冲容量SubscriberChannelCapacity1_000单个订阅者的有界队列容量背压阈值MaxRecentLogQuerySize1_000最近查询的默认Take与上限钳制值负值按 0 处理SourceHeartbeatTimeout30 秒来源心跳超时超时后来源状态置为StaleIncludeStructuredLogsInternalLogsfalse是否允许捕获模块自身的内部诊断日志递归防护开关对应 FR-015SensitiveNames8 个默认敏感名称遮蔽 properties/scopes 中的敏感键名SensitiveTextPatterns3 条默认正则遮蔽消息/异常中的敏感文本代码方式配置来自 quickstart.mdservices.AddElsa(elsa { elsa.UseStructuredLogs(options { options.RecentLogCapacity 5_000; options.SubscriberChannelCapacity 1_000; options.MaxRecentLogQuerySize 1_000; }); }); app.UseStructuredLogs(); // 映射 /elsa/hubs/diagnostics/structured-logs 与 REST 端点Shell 特性方式配置appsettings.json特性全名Elsa.Diagnostics.StructuredLogs.ShellFeatures.StructuredLogsFeature字段与代码方式一一对应{ ShellFeatures: { Elsa.Diagnostics.StructuredLogs.ShellFeatures.StructuredLogsFeature: { RecentLogCapacity: 5000, SubscriberChannelCapacity: 1000, MaxRecentLogQuerySize: 1000, IncludeStructuredLogsInternalLogs: false } } }授权REST 端点与 SignalR Hub 均要求read:diagnostics:structured-logs权限spec 的 FR-017仅授予允许查看后端日志的运维与开发人员。十、边界约定与验证数据模型明确划定了模块边界spec 的 FR-025 与 Assumptions不采集直接写入 stdout/stderr 的内容——那是未来Elsa.Diagnostics.ConsoleLogs模块的职责不提供trace waterfall、指标图表、span 探索——那是未来Elsa.Diagnostics.OpenTelemetry模块的职责本模块只稳定暴露TraceId/SpanId关联字段不负责长期持久化——StructuredLogProvider是可插拔边界未来可由持久化 provider 提供如 README 提到的Elsa.Diagnostics.StructuredLogs.Persistence.Sqlite存储包。验证命令与基线结果见 quickstart.mddotnet build src/modules/Elsa.Diagnostics.StructuredLogs/Elsa.Diagnostics.StructuredLogs.csproj dotnet test test/unit/Elsa.Diagnostics.StructuredLogs.UnitTests/Elsa.Diagnostics.StructuredLogs.UnitTests.csproj dotnet test test/integration/Elsa.Diagnostics.StructuredLogs.IntegrationTests/Elsa.Diagnostics.StructuredLogs.IntegrationTests.csprojquickstart 记录的 2026-05-10 验证结果为构建通过单元测试 28 个通过集成测试 6 个通过测试重点覆盖{OriginalFormat}模板采集、scope 捕获与脱敏、最近查询/来源列表/过滤/实时流/丢弃事件等行为spec 的 SC-004SC-006。如需继续深入可依次阅读 spec.md功能需求 FR-001FR-025、provider-contract.md、rest-api.md 与 signalr-hub.md并在源码目录 src/modules/Elsa.Diagnostics.StructuredLogs 中对照实现细节。赞分享后端工作流自动化流程编排低代码【免费下载链接】elsa-coreThe Workflow Engine for .NET项目地址https://gitcode.com/gh_mirrors/el/elsa-core点击查看免费下载相关推荐Gatsby 与 Jamstack 架构实战指南用 JavaScript、API 与 Markup 构建无数据库的现代网站Gatsby 与 Jamstack 架构实战指南用 JavaScript、API 与 Markup 构建无数据库的现代网站 Jamstack 是一种现代网站与后端工作流自动化流程编排低代码QuickRecorder macOS 录屏教程6 种录制模式与进阶配置一次讲清QuickRecorder macOS 录屏教程6 种录制模式与进阶配置一次讲清 QuickRecorder 是一款基于 ScreenCaptureKitA后端工作流自动化流程编排低代码Mastra ClickHouse vNext 日志事件log_events设计解析逻辑模型、物理表结构与查询契约Mastra ClickHouse vNext 日志事件log_events设计解析逻辑模型、物理表结构与查询契约 本文围绕 Mastra 可观测性 v人工智能Agent 框架AI AgentRAG后端上一篇终极冒险岛游戏编辑器指南Harepacker-resurrected三大神器打造专属游戏世界下一篇如何将任何图片转换为3D打印模型免费图片转STL工具完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进