跳到内容
Lenso
简体中文
Esc
navigateopen⌘Jpreview
本页内容

Runtime Story

了解Lenso 的业务级运行时证据模型。

Runtime Story是 Lenso 对某个企业或运营商的持久记录 主机内部引起的动作。

不是要求用户将日志、队列行、代理调用、跟踪拼凑在一起, 并重试,Lenso 按 correlation_id 对相关运行时证据进行分组并显示 它作为一个Story:请求、模块操作、事件或功能工作、 Provider 调用、状态及其背后的技术操作。

这是Lenso的核心理念之一。Story不仅仅是一个踪迹查看器,而且不是 只是一个审核日志。这是模块化业务的操作员可读的叙述 系统。

Story给出了怎样的答案

当用户创建票证、同步联系人、添加组织成员身份时, 或运行模块操作,有用的问题是:

  • 发生了什么面向用户的事情?
  • 哪个模块拥有它?
  • 主机是否路由、授权并记录?
  • 它是否排队Outbox或运行时工作?
  • Service Provider 调用成功还是失败?
  • 哪种技术操作可以解释节点缓慢或失败的原因?

Runtime Story使这些答案在Runtime Console中可见。

Story是如何构建的

Lenso 不要求模块作者手动构建Story图。主人 当工作在平台拥有的接口中移动时,记录微小而持久的事实。

来源 Story角色
platform.story_events 规范化的Story节点,例如 HTTP 请求、管理操作和Provider调用
platform.outbox 已提交的模块事件和调度状态
runtime.function_runs 排队、正在运行、重试、已完成、失败或停止后台工作
platform.remote_http_proxy_calls 进程外模块流量的主机拥有的证据
遥测跨度 尽可能将技术操作链接回Story节点

Runtime Console通过 /admin/runtime/stories 读取这些记录并 呈现:

  • 包含标题、状态、持续时间、服务和模式的Story列表项;
  • 带有节点和边的详细图;
  • 运行时工作的时间线项目;
  • 用于诊断的热力图和技术操作视图。

分组键

主键是correlation_id

一个传入请求会获取一个请求 id 和相关 id。楼主什么都有 代表该请求的确实应该保留相同的相关ID。因果关系 ids 将子节点连接到导致它的节点。

POST /v1/support/tickets
  correlation_id = corr_ticket_123
  request_id     = req_create_ticket

story nodes:
  httpreq_req_create_ticket
  outbox_evt_ticket_created
  fnrun_support_ticket_escalate
  remoteproxy_rproxy_notify_crm

这就是为什么Lenso可以在不耦合每个模块的情况下展示业务级别的Story 到单个工作流引擎。

为Story命名

好的Story名称来自模块元数据。对于普通 HTTP 路由,设置 display_name 为节点,story_title 为Story。

use lenso::{ModuleHttpMethod, ModuleHttpRoute};

let route = ModuleHttpRoute {
    method: ModuleHttpMethod::Post,
    path: "/v1/support/tickets".to_owned(),
    capability: Some("support.tickets.write".to_owned()),
    display_name: Some("Create ticket".to_owned()),
    story_title: Some("Support ticket created".to_owned()),
};

对于运行时函数或其他执行名称,声明 story_display 元数据。

use lenso::{ModuleManifest, StoryDisplayDescriptor, StoryDisplaySource};

pub fn manifest() -> ModuleManifest {
    ModuleManifest::builder("identity")
        .story_display(vec![StoryDisplayDescriptor {
            source: StoryDisplaySource::ExecutionName {
                name: "identity.create_user".to_owned(),
            },
            display_name: "Create User".to_owned(),
            story_title: Some("User Registration".to_owned()),
        }])
        .build()
}

TypeScript Service 为其提供的 Module 声明相同的路由元数据。

import { defineModule, defineService, postRoute } from "@lenso/service-kit";

const accountProfile = defineModule({
  capabilities: ["account_profile.organizations.write"],
  httpRoutes: [
    postRoute("/organizations/{id}/memberships", {
      capability: "account_profile.organizations.write",
      displayName: "Add membership",
      storyTitle: "Organization membership added",
    }),
  ],
  name: "account-profile",
  version: "0.1.0",
});

export const manifest = defineService({
  modules: [accountProfile],
  name: "account-profile-service",
  version: "0.1.0",
});

如果元数据丢失,Story构建器就会退回到人性化执行 名称或事件名称。这使页面保持有用,但有意的Story元数据 对用户来说更好。

API 形态

Runtime Console调用主机拥有的运行时 API:

curl -sS \
  -H "Authorization: Bearer $LENSO_DEV_TOKEN" \
  "http://127.0.0.1:3000/admin/runtime/stories?limit=10" | jq .

curl -sS \
  -H "Authorization: Bearer $LENSO_DEV_TOKEN" \
  "http://127.0.0.1:3000/admin/runtime/stories/corr_ticket_123" | jq .

列表响应包括标题、correlation_id、状态、持续时间、 node_counterror_count、服务、模式和根错误。细节 响应包括摘要、节点、边和时间线项。

创作好Story

将Story质量视为模块质量的一部分:

  • 为面向用户的路由提供明确的 display_namestory_title
  • 保持功能名称稳定,以便Story可以与权限绑定;
  • 在排队工作时保留请求和相关上下文;
  • 使用Outbox事件和运行时函数进行后续工作而不是隐藏 副作用;
  • 避免Story元数据中的原始秘密、令牌、密码或敏感负载;
  • 添加一个冒烟检查来触发模块路径并断言Story出现。

冒烟检查可以很简单:

await waitFor("account-profile runtime story", async () => {
  const stories = await fetchJson(`${apiBaseUrl}/admin/runtime/stories?limit=5`);
  return stories.data?.some(
    (story) =>
      story.title === "Organization membership added" &&
      story.status === "completed" &&
      story.services?.includes("account-profile")
  );
});

什么Story不是

Runtime Story不会取代:

  • 用于进程级调试的结构化日志;
  • 用于低级延迟分析的分布式跟踪;
  • 合规性特定配置更改的审核历史记录;
  • 用于长期运行的业务编排的工作流定义。

它们位于这些层之上。Story是对“发生了什么”的简洁回答 业务系统,证据在哪里?”

最后更新于 2026年8月1日

这个页面有帮助吗?