# @columenlabs/lumen-ops 中文文档

规范地址：https://npmcn.com/package/%40columenlabs/lumen-ops/

版本：0\.1\.219
npm 元数据更新时间：2026-11-09T05:44:03.770Z
中文译文更新时间：2026-11-10T11:33:50.648Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40columenlabs/lumen-ops
原文对照：https://npmcn.com/package/%40columenlabs/lumen-ops/?lang=original
项目主页：https://github.com/columenlabs/lumen
源码仓库：https://github.com/columenlabs/lumen

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：76.1 kB，26 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：2 个
- peer 依赖：hono \>=4\.8\.0
- 首次发布：2026-10-24T21:12:07.816Z
- 最新版本发布：2026-11-09T05:44:03.594Z
- 近 30 天下载量：42541（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：187（近 12 个月 187 个）

## 中文简介

Lumen的操作部分:每个请求,事件,数据查询和工具调用一个应用程序作为一个分析引擎点(只有模板,代码,形状和散列)运行,并签名出网.

## 安装

```sh
npm install @columenlabs/lumen-ops
```

也可以使用：`pnpm add @columenlabs/lumen-ops`、`yarn add @columenlabs/lumen-ops`、`bun add @columenlabs/lumen-ops`

## README

# @columenlabs/ lumen- ops

Lumen的"Cloudflare Workers"的操作部分:每个请求的应用程序回答,每个事件和每个数据查询都成为一个分析引擎点,这样你就可以发现出错,错配以及慢或重的查询并修正. 计数器将你的装订包了一次,所以新的代码是不选择加入的。 它只写每个查询的形状,从来不是值. 它也是仪表工具调用( I)`/tools`)并发送签名的webhoks(`/webhooks`) (中文(简体) ).

-   文档 : [https://lumen.columenlabs.com/docs/ (中文(简体) )](https://lumen.columenlabs.com/docs/)
-   对于代理人: [https://lumen.columenlabs.com/llms.txt (中文(简体) )](https://lumen.columenlabs.com/llms.txt)
-   资料来源: [https://github.com/columenlabs/lumen (中文(简体) )](https://github.com/columenlabs/lumen) (单位:千美元)`packages/ops`麻省理工学院.

## 安装

```bash
bun add @columenlabs/lumen-ops
```

把它固定在与你其他的鲁门软件包相同的准确版本上. 用这个 `AsyncLocalStorage`,所以工人们需要 `nodejs_compat` 旗帜.

## 设置

将分析引擎数据集装入 `wrangler.jsonc`数字 :

```jsonc
"analytics_engine_datasets": [{ "binding": "QUERIES", "dataset": "myapp_queries" }]
```

将包好的装订件 交给您的应用程序:

```ts
import { foldRoute, meteredClickHouse, meteredD1, setQueryCallerOf, setQuerySink } from '@columenlabs/lumen-ops';

setQuerySink(env.QUERIES);
// Name the request in scope: the app (or part of it), the route, and the tool when an MCP call runs.
setQueryCallerOf(() => {
  const req = currentRequest(); // your own request scope
  return req && { app: 'myapp', kind: 'fetch', route: foldRoute(new URL(req.url).pathname) };
});
const db = meteredD1(env.DB);
const clickhouse = meteredClickHouse(env.CLICKHOUSE); // any ClickHouse HTTP service binding
```

在永久对象中,测量其SQLite:

```ts
import { meteredSql } from '@columenlabs/lumen-ops';

const sql = meteredSql(state.storage.sql, { app: 'myapp', kind: 'do', route: 'Person' });
```

运行、排队或提醒名本身

```ts
import { withQueryCaller } from '@columenlabs/lumen-ops';

await withQueryCaller({ app: 'myapp', kind: 'cron', route: 'nightly-rollup' }, () => rollup(env));
```

另一个引擎(R2 SQL,一个HTTP数据库)调用 `meterQuery({ engine, sql, method, ok, ms, ... })` 从它的一个客户端.

## 说得有道理

每回合发言一次1分:同一语句多次运行一次(插入圈)是总数的一分 `statements` 说多少跑。 以平分为正. 列单是读取数据集的合约:

| 栏 | 持有 |
| --- | --- |
| `index1` | 引擎 : `d1`, (中文(简体) ), `clickhouse`, (中文(简体) ), `do_sqlite`, (中文(简体) ), `r2_sql` 或属于自己的 |
| `blob1` . `blob5` | 发动机、应用程序、种类(`fetch`, (中文(简体) ), `cron`, (中文(简体) ), `queue`, (中文(简体) ), `alarm`, (中文(简体) ), `do`页:1 `:id`),工具 |
| `blob6` . `blob8` | 操作( O)`select`, (中文(简体) ), `insert`, (中文(简体) ), `update`, (中文(简体) ), `delete`, (中文(简体) ), `ddl`, (中文(简体) ), `pragma`, (中文(简体) ), `other`),指纹,查询的形状(最多 1 KB) |
| `blob9`, (中文(简体) ), `blob10` | `ok` 或者说 `error`方法(`all`, (中文(简体) ), `first`, (中文(简体) ), `run`, (中文(简体) ), `raw`, (中文(简体) ), `batch`, (中文(简体) ), `query`, (中文(简体) ), `insert`, (中文(简体) ), `exec`(中文(简体) ) |
| `double1` . `double10` | 壁 ms,引擎本身的 ms,行读取,字节读取,行回取,行写取,回取字节(每个共取),HTTP状态,语句,最慢 ms |

形状有每个字符串和数字字面 `?`, (中文(简体) ), `IN` 已折叠到 `(?...)`,评论和点击之家 `FORMAT` 掉下去,插入的一行被切断。 指纹是形状的散列, 一种查询.

以分析引擎SQL API为例

```sql
SELECT blob7 AS fingerprint, any(blob8) AS shape,
       sum(IF(double9 > 0, double9, 1) * _sample_interval) AS calls,
       sum(double1 * _sample_interval) / sum(IF(double9 > 0, double9, 1) * _sample_interval) AS mean_ms,
       max(double10) AS slowest_ms
FROM myapp_queries
WHERE timestamp > NOW() - INTERVAL '1' DAY
GROUP BY fingerprint ORDER BY mean_ms DESC LIMIT 20
```

## 出口

| 导出 | 它会做什么 |
| --- | --- |
| `setQuerySink(binding)` | 数据集每个点; 在设定之前什么都不是写入的 |
| `setQueryCallerOf(fn)` | 在没有任务时在范围中列出请求 |
| `withQueryCaller(caller, fn)` | 充电内部的每个查询 `fn` 改为 `caller` |
| `meteredD1(db)` | D1, 计量吸入器: `prepare` 财务报告和审定财务报表 `batch`,其中D1自己的行读取并写出并持续时间 |
| `meteredClickHouse(binding)` | 一个 ClickHouse HTTP 服务绑定, 当答案被读取后调制: 墙上时间到最后一个字节, ClickHouse 自己的统计 |
| `meteredSql(sql, caller?)` | 持久对象 `storage.sql`;其光标保持 `toArray`, (中文(简体) ), `one`, (中文(简体) ), `raw`, (中文(简体) ), `next`,重复和 `columnNames` |
| `meterQuery(point)` | 一分一分,对任何其他引擎 |
| `queryShape(sql)` | 查询的形状、指纹和操作 |
| `foldRoute(path)` | 有类似 id 的片段的路径 `:id` |
| `setQueryRowCap(n)` | 最多一行的语句应返回; 更多返回的语句应标记 `capped` 内 `blob11` |

## 请求

`@columenlabs/lumen-ops/hono` meth 每一个请求一个Hono应用程序的答案:先挂载一次,然后该应用程序的每一个路由在后面写出一个有其路由模板,状态,结果代码和时间的点. 它将请求命名为范围,所以里面的事件和询问都带有它的ID.

```ts
import { requestId } from 'hono/request-id';
import { requestMeter } from '@columenlabs/lumen-ops/hono';
import { setRequestSink } from '@columenlabs/lumen-ops/requests';

app.use('*', async (c, next) => {
  setRequestSink(c.env.REQUESTS, { log: true }); // also one JSON line per point in Workers Logs
  await next();
});
app.use('*', requestId());
app.use('*', requestMeter({
  app: 'myapp',
  env: (c) => c.env.DEPLOY_ENV,
  describe: (c) => ({ surface: 'api', subject: c.get('accountId'), callerKind: 'key' }),
}));
```

| 栏 | 持有 |
| --- | --- |
| `index1` | 主体:应用程序给谁打电话的不透明标识,或 `anon` |
| `blob1` . `blob7` | App,表面,方法,路由模板,结果(`ok`,一个 `error` jSON的密码, `exception`, (中文(简体) ), `http_<status>`),呼叫者种类,呼叫者编号 |
| `blob8` . `blob13` | 区域, env, 版本, colo, 国家, 请求 id |
| `double1` . `double6` | 状态, ms, 字节在, 字节在外, 上游 ms, 子请求 |

路径没有匹配的路由被写入为 `*`所以扫描仪的垃圾不会落地 没有贺野 就把处理器包起来 `withRequest(scope, route, fn)` 打电话 `meterRequest(point)` 你自己来.

## 约束和外出电话

在条目和补丁时包起嵌入器 `fetch` 一次,每个持久对象RPC方法,工人AI,矢量化,KV,R2,服务或VPC呼叫和每个出站 `fetch` 被定时并收费于请求的范围:

```ts
import { meterFetch, meteredBindings } from '@columenlabs/lumen-ops';
import { requestMeter } from '@columenlabs/lumen-ops/hono';

meterFetch();
app.use('*', requestMeter({ app: 'myapp', serverTiming: true }));
export default { fetch: (req, env, ctx) => app.fetch(req, meteredBindings(env, { kinds: { AI: 'ai', INDEX: 'vectorize' }, skip: ['METRICS'] }), ctx) };
```

呼叫按其约束性和方法命名(`DIRECTORY.seen`, (中文(简体) ), `AI.run`, (中文(简体) ), `fetch.api.example.com`),从不争论. 请求点 `upstream ms` 财务报告和审定财务报表 `subrequests` 添加; `serverTiming: true` 将拆分寄回 `Server-Timing` (单位:千美元)`do`, (中文(简体) ), `ai`, (中文(简体) ), `fetch`. . . . . . . , `app`, (中文(简体) ), `total`),当请求结束时,每个调用代码是一个 `call` 活动(`code` 电话, `ref` 同类的, `ms` 总计, 计数: 呼叫, 失败 。 在请求(警报)之外,每个电话都是自己的事件. `app` 可能是一种功能,而且 `route` 当一个工人通过路径向其他应用程序请求时,请指定路径.

## 活动

`@columenlabs/lumen-ops/events` 写一个应用程序所做的不是它回答的请求: 呼叫另一个服务, 网约车进出,同步的开始和结束, 登录。 以这些要求的要点,他们表明,是否已经采取行动.

```ts
import { meterEvent, setEventSink } from '@columenlabs/lumen-ops/events';

setEventSink(env.EVENTS);
meterEvent({ event: 'bank.call', code: '/accounts/get', ok: res.ok, ms, status: res.status, upstream: true });
meterEvent({ event: 'sync.done', ok: true, subject: accountId, ref: connectionId, counts: [added, modified, removed] });
```

| 栏 | 持有 |
| --- | --- |
| `index1` | 主题,或 `anon` |
| `blob1` . `blob10` | App,事件,代码,结果, ref,触发,请求id,上游id,env,版本 |
| `double1` . `double6` | ms,状态,数一,数二,数三,尝试 |

`upstream: true` 在请求中增加通话时间 `upstream ms`在永久对象中,没有请求范围: `setEventSink(binding, { app, env, version })` 默认,然后通过一个 `requestId` 如果你有电话就派来.

## 浏览器遥测

`useLumenTelemetry` 内 `@columenlabs/lumen-ui` 将打开的屏幕、 未发现的错误( 类和堆栈的散列, 永远不发送信件) 、 失败的请求和Web Vitals 分批发送到 `/api/t`工人检查并写道:

```ts
import { meterClientBatch, setClientSink } from '@columenlabs/lumen-ops/client';

setClientSink(env.CLIENT);
app.post('/api/t', async (c) => {
  meterClientBatch(await c.req.json().catch(() => null), { app: 'console', subject: c.get('accountId') });
  return c.body(null, 204);
});
```

| 栏 | 持有 |
| --- | --- |
| `index1` | 主题,或 `anon` |
| `blob1` . `blob9` | 类App(`view`, (中文(简体) ), `error`, (中文(简体) ), `fetch_fail`, (中文(简体) ), `vital`),路由模板,名称,堆栈指纹,请求代号,版本,设备,env |
| `double1`, (中文(简体) ), `double2` | 数值(毫分或分数),状态 |

一批失败的 schema 被全部删除; 只有代码,模板和数字通过 .

## 工具调用

`@columenlabs/lumen-ops/tools` mm每个调用助手或代理制作:每调用1分,随时间,结果和所运行代码的散列,如此缓慢或失败的工具出现,相同的脚本被分组到各跑.

```ts
import { meteredCall, meterToolCall, setToolSink } from '@columenlabs/lumen-ops/tools';

setToolSink(env.TOOL_CALLS); // an Analytics Engine dataset binding

// Wrap a call: latency and outcome are taken for you.
const rows = await meteredCall({ app: 'trade', tool: 'portfolio_list', kind: 'call' }, () => run(args));

// Or write one by hand, with the code a script ran.
meterToolCall({ app: 'trade', tool: 'script', kind: 'script', ok: true, ms: 840, code: source, rows: 120 });
```

| 栏 | 持有 |
| --- | --- |
| `index1` | 应用 |
| `blob1`.`blob9` | 应用、工具、种类、结果(`ok` 或者说 `error`),错误类型、代码散列、源、级、运行 id |
| `double1`.`double6` | 毫秒、行、字节、字节、符号、符号 |

争论和结果从不写;只写出其大小.

| 导出 | 它会做什么 |
| --- | --- |
| `setToolSink(binding)` | 数据集工具点进入; 在设定之前没有写入 |
| `meterToolCall(point)` | 一分一分的手头 |
| `meteredCall(point, fn, errorKind?)` | 运行 `fn`,定出时间并撰写结果 |
| `codeHash(code)` | 一个简短的散列脚本, 白空间折叠 |

## 网络呼出

`@columenlabs/lumen-ops/webhooks` 发送一份快递,按 [标准网络呼号](https://www.standardwebhooks.com/) 给定一个秘密时的 spec, 这样接收器就可以用任何标准的 Webhooks 库来验证它. 它从不扔出:结果说明它是如何走的,为的是应用自己的送货日志和回放.

```ts
import { newWebhookSecret, sendWebhook } from '@columenlabs/lumen-ops/webhooks';

const secret = newWebhookSecret(); // whsec_…, shown to its owner once, kept sealed
const r = await sendWebhook({
  url: endpoint.url,
  secret,
  id: event.id, // the same id on a retry
  body: JSON.stringify(event.payload),
  headers: { authorization: `Bearer ${endpoint.token}` },
  userAgent: 'MyApp-Webhooks/1',
});
if (!r.ok) scheduleRetry(event, r.status, r.error);
```

| 导出 | 它会做什么 |
| --- | --- |
| `sendWebhook(send)` | 一个POST: `{ ok, status, ms, id, error? }`; 当结束点从未回复时, 状态 0 |
| `newWebhookSecret()` | 一个新的 `whsec_` 秘密, 32 个随机字节 |

端点的自有头先行,所以永远无法替换签名头. 重定向算作失败, 除非 `redirect` 否则, 超时为 10 s .

## 版本数

0.x:任何未成年人可以断裂到1.0. 每次和鲁门合并 `main` 发布每个 Lumen 软件包的下一个补丁;参见 [释放](https://github.com/columenlabs/lumen/releases)。 。 。 .

## 常见问题

### @columenlabs/lumen-ops 是什么？

Lumen的操作部分:每个请求,事件,数据查询和工具调用一个应用程序作为一个分析引擎点\(只有模板,代码,形状和散列\)运行,并签名出网\.

### 如何安装 @columenlabs/lumen-ops？

在项目目录运行 npm install @columenlabs/lumen-ops，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：hono（\>=4\.8\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @columenlabs/lumen-ops 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @columenlabs/lumen-ops 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @columenlabs/lumen-ops 可以商用吗？

@columenlabs/lumen-ops 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @columenlabs/lumen-ops 的下载量有多少？

根据 npm 官方下载统计，@columenlabs/lumen-ops 在 2026/10/11 – 2026/11/09 这 30 天内被下载 42,541 次，日均约 1,418 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @columenlabs/lumen-ops 还在维护吗？

最新版本 0\.1\.219 发布于 2026/11/09（1 天前）；至今共发布 187 个版本，其中过去 12 个月发布了 187 个；首次发布于 2026/10/25。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

