Effect 里怎么记录指标?
「过去五分钟错误率是多少」「队列积压了多少」,这类问题你没法从日志里 grep 出来,因为它们是聚合后的数字。
在 Effect 里用 Metric:Metric.counter 记只增的计数,Metric.gauge 记当前值,Metric.histogram 记分布,统一用 Metric.update(metric, value) 更新。 counter 累加,gauge 覆盖,histogram 把值记入对应的桶。
指标回答的是「整体怎样」,跟日志和 span 分工不同,三种信号的区别见 Effect 里日志、span 和指标各自该观测什么。下面讲怎么写,以及用的时候该小心什么。
一个完整的例子长什么样?
下面记录两个数:失败了多少次,以及请求的耗时分布。
import { Duration, Effect, Metric } from "effect"
const ordersFailed = Metric.counter("orders.failed", {
description: "Orders that ended in failure"
})
const orderLatency = Metric.histogram("orders.latency_ms", {
description: "Order processing latency",
boundaries: Metric.exponentialBoundaries({ start: 10, factor: 2, count: 10 })
})
declare const run: (id: string) => Effect.Effect<void, Error>
export const instrumented = (id: string) =>
Effect.gen(function* () {
const [elapsed] = yield* Effect.timed(run(id))
yield* Metric.update(orderLatency, Duration.toMillis(elapsed))
}).pipe(Effect.tapError(() => Metric.update(ordersFailed, 1)))这是示意代码,重点不在细节而在选择:「失败了多少次」和「成功请求的耗时分布」这两个数字,能直接画成告警线。Effect.timed 返回的第一个元素是耗时,用 Duration.toMillis 转成毫秒后记入 histogram;失败时由 Effect.tapError 给 counter 加 1。
该记哪些数?
先问谁会看、看了要做什么决定。没有人据此做决定的指标,不要记。每个函数都记指标,只会让成本上去,信号被淹没。
标签为什么不能放用户 id?
指标要小心基数:attribute 的取值组合会各自成为一条时间序列。把用户 id、订单号、URL 全路径放进指标标签,序列数会爆炸。
指标的标签只放取值有限的维度,比如渠道、结果类型。需要追到具体某个订单,那是日志和 span 的事。
版本:Effect v4(教程章节没有标注具体的 effect 版本号)。代码是示意代码,用declare省略了业务函数,我没有在本文中逐段运行;关于Metric各 API 的描述来自教程章节本身,没有另行验证。