@crvouga/mockingbird-service-tempo

中文文档
0.10.0发布于 2026/11/11MITTypeScriptES Module构建来源已验证近 30 天下载 2381

Grafana Tempo的模拟器:OTLP/HTTP 追踪摄入(JSON和protobuf),追踪QL搜索,由ID进行追踪和在一个租户范围商店上发现标记名称.

中文使用文档
文档目录10 节
  1. 安装
  2. 使用量
  3. 路线
  4. 跟踪QL
  5. 认证和租户
  6. 管理员(超过标准合同)
  7. 命名空间
  8. 核实了什么
  9. 故意不模拟
  10. API 密码

@crvouga/mockingbird-service-tempo (英语)

本地模拟器。 真正的API合同. 部分 嘲笑鸟。 。 。 .

状态模拟器 格拉法纳·泰普 测试套房:OTLP/HTTP跟踪接收器 (单位:千美元)POST /v1/traces, JSON and protobuf) 和查询路径 跟踪阅读器呼叫( TraceQL search, 追踪身份,标记名称,超过一个商店。 测试出口跨越其应用方式和 读到它们后,它的制作读者发出请求, 没有多克和通波.

  • 行动范围: 支助
  • 状态 : 进行中的工作。Tempo没有发布 OpenAPI 文件,也没有实例 合同是写成的openapi.yaml跟着格拉法纳 HTTP API 参考文献 还有Tempo的消息来源 (原始内容存档于2017-03-10). v3.1.0. 核实了什么 列出每一个可以 未确认.

安装

npm install -D @crvouga/mockingbird-service-tempo

仅限无害环境管理。 节点 22或 Bun 1.2. 无土生属地. 给它服务 npx mockingbird-tempo serve, (中文(简体) ), createServer 从 ./server (节点),或 createRuntime 带有任意 获取服务器 .

使用量

Tempo在两个端口上收听(4318用于OTLP,3200用于查询);模拟器从一个端口同时服务 源代码。 指向出口商的终点和读者的Tempo URL:

npx mockingbird-tempo serve --port 8930
# OTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:8930   (the exporter posts /v1/traces)
# TEMPO_URL=http://127.0.0.1:8930                     (the reader calls /api/…)

# Grafana Cloud style credentials, and tenants:
npx mockingbird-tempo serve --basic-auth 123456:fixture-token --multitenancy
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
import { resourceFromAttributes } from "@opentelemetry/resources"
import { BasicTracerProvider, SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base"
import { createServer } from "@crvouga/mockingbird-service-tempo/server"

const server = await createServer()

// The OpenTelemetry SDK your application already uses. Only the exporter's URL changes
// (the protobuf exporter works the same way).
const provider = new BasicTracerProvider({
  resource: resourceFromAttributes({ "service.name": "checkout" }),
  spanProcessors: [new SimpleSpanProcessor(new OTLPTraceExporter({ url: `${server.url}/v1/traces` }))],
})
const span = provider.getTracer("checkout").startSpan("POST /checkout", {
  startTime: new Date(1_700_000_000_000),
  attributes: { "user.id": "user-1" },
})
span.end(new Date(1_700_000_001_500))
await provider.forceFlush()

// What the trace reader sends (Tempo's query API is plain HTTP).
const q = encodeURIComponent('{ .user.id = "user-1" }')
const search = await fetch(`${server.url}/api/search?q=${q}&start=1699999990&end=1700000010&limit=50`)
const { traces } = (await search.json()) as { traces: { traceID: string }[] }
const trace = await fetch(`${server.url}/api/traces/${traces[0]?.traceID}`)

await provider.shutdown()
await server.close()

路线

路线行为
POST /v1/traces一个 ExportTraceServiceRequest 作为 application/json 或者说 application/x-protobuf (gzip接受). 成功200个 {"partialSuccess":{}} 给JSON 和一个空的原生纸条给原生纸条 错误是 google.rpc.Status 在请求的编码中:400码3 一个不解码的有效载荷, trace ids must be 128 bit, received N bits 财务报告和审定财务报表 span ids must be 64 bit and not all zero, received N bits 为ids Tempo的经销商拒绝(整个出口被拒绝,没有存储)。 其他内容类型是415 415 unsupported media type, supported: [application/json, application/x-protobuf] 作为纯文本。 在任何其他检查之前,接受无跨度的出口。 已存储用于跟踪的横跨标识被替换 .
GET /api/searchq (跟踪QL,见下文), start编号 :end (时间秒), limit (违约20), spss (每套跨度分秒数,默认为3,最多为100). 答复 {traces: [...], metrics: {...}}; 每一个痕迹都有 traceID, (中文(简体) ), rootServiceName, (中文(简体) ), rootTraceName, (中文(简体) ), startTimeUnixNano (nanoseconds,一个小数字符串), durationMs (数目), spanSet编号 :spanSets (相匹配的跨度 : spanID, (中文(简体) ), startTimeUnixNano, (中文(简体) ), durationNanos,并属性比较的查询; matched )和 serviceStats。没有匹配 {"traces": []}最新的追踪第一。 两者 start 财务报告和审定财务报表 end (非零),当窗口重叠时返回一个跟踪:它始于或在此之前 end 结束时或之后 start,两者均包含纳米秒;其中之一缺失的窗口不适用,如Tempo。 没有 q 窗外的每一个痕迹都归了.
GET /api/traces/{traceId}作为Tempo的追踪器 {"batches": [{resource, scopeSpans: [{scope, spans}]}]}这是 没有 OTLP/JSON: (英语) traceId, (中文(简体) ), spanId 财务报告和审定财务报表 parentSpanId 是基础64, kind 财务报告和审定财务报表 status.code enum 名称 (SPAN_KIND_SERVER, (中文(简体) ), STATUS_CODE_ERROR),64位整数(时间, intValue)是十进制字符串,零值被省略,每个跨度有一个 status 对象。 短于32个十六进制字符的微量ID是左加法. 未知的痕迹:404 有一具空出的身体. 非六进制: 400 trace IDs can only contain hex characters: invalid character 'x' at position N。 。 。 .
GET /api/v2/search/tagsscope =: span, (中文(简体) ), resource, (中文(简体) ), event, (中文(简体) ), link, (中文(简体) ), instrumentation, (中文(简体) ), intrinsic,或缺席/none 为了他们所有人 答复 {scopes: [{name, tags}], metrics}: 任何存储跨度上看到的属性名称,每个列表排序,一个没有被忽略的名称的范围. 列出一个在单一范围内看到的名字. limit 每个列表都盖上。 未知范围: 400 invalid scope: <scope>。 。 。 .

每400个查询路线是Tempo's:错误文本作为整个正文, text/plain。 。 。 . 搜索以 Tempo 的顺序验证 : invalid start: strconv.ParseUint: parsing "abc": invalid syntax, (中文(简体) ), invalid limit: must be a positive number, (中文(简体) ), http parameter start must be before end. received start=10 end=5, (中文(简体) ), limit N exceeds max limit M,然后是 TraceQL 查询,168 h 最大范围 财务报告和审定财务报表 spans per span set exceeds 100. received N。 。 。 .

跟踪QL

评估一个相位过滤器:

  • { }, (中文(简体) ), { true }, (中文(简体) ), { false }
  • 属性平等 : .name, (中文(简体) ), span.name 或者说 resource.name (引文如下: span."user id" (列入) = 字符串、整数、浮点或布尔
  • && 二者之间;每个条件必须维持在相同的范围内

未扫描 .name 读取跨度的属性并返回资源。 类型比较 确切的说,除了这些整数和浮数比较数字。 任意时的数组属性匹配 元素确实如此.

其它的都是四百分之一 永远不是更松散的比赛

  • 输入 Tempo 的解析器以 Tempo 的措辞和位置拒绝答案, 例如 invalid TraceQL query: parse error at line 1, col 3: syntax error: unexpected IDENTIFIER 页:1 { user.id = "u" } (该点已缺失).
  • 子集外的有效 TrackQL (=~, (中文(简体) ), !=, (中文(简体) ), >, (中文(简体) ), ||,诸如 status 或者说 duration, (中文(简体) ), event.编号 :link.编号 :parent. 范围、管道、横幅操作器、提示) invalid TraceQL query: <construct> not yet supported (Mockingbird emulates a TraceQL subset)。 。 。 . 第一部分是Tempo对它缺乏的特性的验证器用途;一个真正的Tempo 评估这些查询.

认证和租户

Tempo本身认证了没有人;它前面的网关也认证了. 模拟器同时播放:

设置效果
无( 默认)本地的Tempo:不需要证明.
bearerTokens (单位:千美元)--bearer-token(中文(简体) )Authorization: Bearer <token> 在摄入和询问.
basicUsers (单位:千美元)--basic-auth user:password(中文(简体) )Authorization: Basic …,"格拉法纳云"风格(Intance id and access sord).
unauthorized遗失或错误证书的答复: {status, body, contentType} 与 status 401 或 403, 默认 401 Unauthorized 作为纯文本。 把它设定在你的网关答案.
multitenancy (单位:千美元)--multitenancy(中文(简体) )温柔的 multitenancy_enabled数字 : X-Scope-OrgID 租户只读写着什么。 没有标题的查询路由是 401 no org id; 没有它的导出为 503 {"code":14,"message":"no org id"}。 。 。 . a|b 在查询中看到两个房客。 关闭,标题被忽略.
leftPadTraceIds (单位:千美元)--left-pad-trace-ids(中文(简体) )温柔的 left_pad_trace_ids: 搜索回答 32-特征痕量标识. 关闭( Tempo 的默认值), 引导为 0 .
defaultLimit, (中文(简体) ), maxLimit搜索默认值(20)和最大值(262144)结果计数.

熊克令牌和 Basic 用户可以一起配置;一个请求需要匹配的.

管理员(超过标准合同)

路线效果
POST /__admin/traces{resourceSpans: [...], tenant?}:按给定的准确存储OTLP/JSON输出,没有证书,断层或租户头条。 跨度没有 startTimeUnixNano 以模拟时钟(POST /__admin/clock页:1 endTimeUnixNano 结束了。 答复 {accepted, tenant, traceIds}。 。 。 .
GET /__admin/traces{traces: [{tenant, traceID, spanCount, rootServiceName, rootTraceName, startTimeUnixNano, durationMs}]},最古老的第一. ?tenant= 缩小它.
GET /__admin/spans{spans: [...]}:所储存的跨度(电线外形旁的外形). ?traceId=, (中文(简体) ), ?tenant=。 。 。 .
GET /__admin/settings, (中文(简体) ), PUT /__admin/settings上面的设置, 用于调用命名空间 . POST /__admin/reset 返回它们的默认值.

即时快照( A)POST /__admin/snapshots, (中文(简体) ), POST /__admin/snapshots/:id/restore检查站, 重置,时钟,请求日记和度量衡是标准合同. 日记记录 一个出口发生, 以及它碰到的追踪编号, 从不横跨内容.

错误预设( E)POST /__admin/faults {"preset": "<name>", "count"?: n}· ; "count": 1 是一个 一发; GET /__admin/faults/presets: ingest_unavailable (503,出口商复试), ingest_rate_limited (429个) RATE_LIMITED: …重审, ingest_server_error (500个,已放弃), ingest_dropped (连接会死), query_unavailable (503个), query_server_error (500个) internal error, (中文(简体) ), query_rate_limited (429个) too many outstanding requests, (中文(简体) ), query_timeout (504个) context deadline exceeded, (中文(简体) ), query_dropped, (中文(简体) ), unauthorized (单位:千美元) 在每个路线上配置了401). 错误的答案 google.rpc.Status 在请求中 编码.

命名空间

平行的工人每人得到自己的商店 x-mockingbird-namespace时 /__admin/ns/<name> 前缀在基准 URL上,或者通过证书: PUT /__admin/credentials {"credentials": {"<bearer token or Basic username>": "<namespace>"}}。 。 。 . 租户(X-Scope-OrgID)是命名空间内相隔的一堵墙.

核实了什么

没有Tempo实例。 每一种行为都从Grafana的文档中读取,或者 Tempo出自(v3.1.0)和OpenTeleometry收集器的OTLP接收器(v.0.153.0,即Tempo) 内嵌:

  • 搜索参数、默认、验证顺序和信件: pkg/api/http.go (单位:千美元)ParseSearchRequest, (中文(简体) ), modules/frontend/search_handlers.go, (中文(简体) ), search_sharder.go。 。 。 .
  • 搜索和标记响应字段及 JSON 类型 : pkg/tempopb/tempo.proto 和gogo合唱 jsonpb 缺省数(modules/frontend/combiner/common.go),以及所记录的例子.
  • 最新的第一订单, 重叠窗口, 修剪的痕量标识, <root span not yet received>数字 : pkg/traceql/combine.go, (中文(简体) ), tempodb/encoding/vparquet5/block_traceql.go, (中文(简体) ), pkg/util/traceid.go, (中文(简体) ), modules/frontend/combiner/search.go。 。 。 .
  • batches,基数64的标识,enum名称并按标识进行跟踪排序;无身体的404: pkg/tempopb/trace_utils.go, (中文(简体) ), pkg/model/trace/sort.go, (中文(简体) ), modules/frontend/combiner/trace_by_id.go,以及"Push 横跨 HTTP"中的例子.
  • 标记范围、排序和内在列表 : pkg/api/search_tags.go, (中文(简体) ), modules/frontend/tag_handlers.go, (中文(简体) ), pkg/search/util.go, (中文(简体) ), pkg/collector。 。 。 .
  • TraceQL 令牌、 属性法和出错位置 : pkg/traceql/lexer.go, (中文(简体) ), parse.go,以及 预计错误 parse_test.go。 。 。 .
  • OTLP的答复和错误:收集器 receiver/otlpreceiver/otlphttp.go 财务报告和审定财务报表 internal/errors/errors.go; id 检查 modules/distributor/distributor.go。 。 。 .
  • no org id页:1 middleware.AuthenticateUser 用于查询的 Tempo 接收器中间软件 摄取;跨租户读作:"交叉租户查询联合会".

未核实 (来源,或选择来源于无)

  • 错误证书的默认为 401 。 它属于Tempo(格拉法纳)的门户 云体没有文件; 配置 unauthorized 来配合你的.
  • 在Tempo的解析测试中 解析-错误文本 。 模拟器从不附加goyacc的 , expecting … 列表,但测试确认的除外,以及一些位于外部的无效输入 子集作为“尚未支持”而不是作为语法错误报告.
  • 不可解码导出的 400 信件文本( 状态、 代码 3 和编码为 接收器的;其解码器的措辞没有复制),并且为错误长度的id 接收器在Tempo的经销商拒绝之前就拒绝.
  • 第503条 no org id 用于不包含 X-Scope-OrgID 多重租户: 接收者映射出纯错误到 UNAVAILABLE,没有观察到.
  • metrics 搜索和标记中的值(inspectedBytes, (中文(简体) ), inspectedTraces:合成.
  • serviceStats,并属性匹配的跨度列表:取自引擎源代码和 而不是现场回应.
  • 未瞄准标记响应中的范围顺序( Tempo's 是无命令的), 开始的痕迹顺序 在同一纳秒(模拟器使用微量id)上,它跟踪到一个 limit 保存 : Tempo"取出平行搜索的第一个N结果",模拟器总是保留最新的.
  • 404的路径Tempo不服务(404 page not found) (中文(简体) ).
  • 查询断层的正体预设 internal error, (中文(简体) ), too many outstanding requests 财务报告和审定财务报表 context deadline exceeded。 。 。 .

故意不模拟

  • Grafana UI、仪表板、PromQL和度量衡; TraceQL度量衡(/api/metrics/query_range(中文(简体) ) 和度量衡生成器.
  • Full TraceQL:只有上面的子集被评价,其他的都是400.
  • 标记搜索在 TraceQL 之前(tags=, (中文(简体) ), minDuration, (中文(简体) ), maxDuration),过滤后标签 名称 (q 标记路由中),标记值,以及 v1 标记路由:拒绝或缺席.
  • GET /api/v2/traces/{id} 财务报告和审定财务报表 Accept: application/protobuf 答案是JSON.
  • 块角时间范围 : start编号 :end 由 id 和 标记 进行验证,然后忽略 (模拟器是一个总是重叠的块).
  • 尾部取样、摄取限度、保留、收缩、分布式储存以及延迟 摄入和可搜索性之间:存储的跨度一并可见.
  • OTLP/gRPC、Jaeger和Zipkin接收器;OTLP记录和计量.
  • 管理、提供、推翻和云资源创造.
  • Span-id 为 Zipkin 风格的共享代号, 以及 Tempo 的根- span并服务 有关痕迹的统计数字分布在几个租户.

发送64位OTLP/JSON值(时间戳, intValue作为字符串,如出口商所做的:JSON号码 过去2^53在模拟者看到它之前失去精度. 不符合原生体的值 宽度、 长度和属性值误差的 id 值被拒于100 个深层 和一个400.

API 密码

导出仁爱说明
TempoAPI类进程模拟器 : fetch(request), (中文(简体) ), reset(), (中文(简体) ), inject(payload, tenant?), (中文(简体) ), spans(filter?), (中文(简体) ), traces(tenant?)选项: sqlite, (中文(简体) ), now, (中文(简体) ), namespace, (中文(简体) ), settings。 。 。 .
createRuntime函数全面服务合同(保健、行政管理、命名空间、证书、预设、钟表、检查站)的仿真者。 选项 : settings, (中文(简体) ), clock, (中文(简体) ), seed, (中文(简体) ), adminPrefix, (中文(简体) ), adminKey, (中文(简体) ), onLog, (中文(简体) ), sqlite。 。 。 .
TEMPO_PRESETS对象每个命名的断层预设.
TEMPO_NAMESPACE字符串服务名称, "tempo"。 。 。 .
DEFAULT_SETTINGS对象命名空间开始的设置 .
SINGLE_TENANT字符串Tempo的房客,当多租房关闭, "single-tenant"。 。 。 .
ORG_ID_HEADER字符串"x-scope-orgid"。 。 。 .
ROOT_SPAN_NOT_YET_RECEIVED字符串rootServiceName 一个没有根茎的痕迹.
INTRINSIC_TAGS数组名称 intrinsic 标记范围.
tempoCredential函数请求的无记名符号或基本用户名( 如何将证书映射到命名空间) .
parseTraceQL, (中文(简体) ), matchesSpan, (中文(简体) ), TraceQLError函数,类TraceQL子集:解析一个查询,测试一个跨度的属性对它,以及消息后面的错误 invalid TraceQL query: 。 。 。 .
decodeSpans, (中文(简体) ), validateIds, (中文(简体) ), OtlpError函数,类OTLP/JSON出口在Tempo的电线形状、Tempo的ID检查和拒绝出口引起的错误.
decodeTraceRequest, (中文(简体) ), encodeRpcStatus, (中文(简体) ), decodeRpcStatus, (中文(简体) ), ProtobufError函数,类原生植物 ExportTraceServiceRequest 解码器和 google.rpc.Status 密码.
hexToBase64, (中文(简体) ), base64ToHex函数在OTLP的六分法和Tempo的基数64之间转换ID.
document, (中文(简体) ), operationIds, (中文(简体) ), supportedOperationIds数值OpenAPI合同及其操作代号.
createServer, (中文(简体) ), serveTarget, (中文(简体) ), DEFAULT_PORT (单位:千美元)./server(中文(简体) )节点服务过来 node:http; 数据 serve CLI目标; 第8930口.

部分 嘲笑鸟。 。 。 .

版本与发布记录

@crvouga/mockingbird-service-tempo 共发布 16 个版本,首次发布于 2026/10/11;过去 12 个月发布了 16 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.10.0latest2026/11/11今天
0.9.52026/11/037 天前
0.9.42026/11/038 天前
0.9.32026/11/038 天前
0.9.22026/11/038 天前
0.9.12026/11/038 天前

关于 @crvouga/mockingbird-service-tempo 的常见问题

@crvouga/mockingbird-service-tempo 是什么?

Grafana Tempo的模拟器:OTLP/HTTP 追踪摄入(JSON和protobuf),追踪QL搜索,由ID进行追踪和在一个租户范围商店上发现标记名称.

如何安装 @crvouga/mockingbird-service-tempo?

在项目目录运行 npm install @crvouga/mockingbird-service-tempo,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 mockingbird-tempo,可以用 npx mockingbird-tempo 直接运行。

@crvouga/mockingbird-service-tempo 支持 TypeScript 吗?

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

@crvouga/mockingbird-service-tempo 支持 ESM 还是 CommonJS?

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

@crvouga/mockingbird-service-tempo 可以商用吗?

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

@crvouga/mockingbird-service-tempo 的下载量有多少?

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

@crvouga/mockingbird-service-tempo 还在维护吗?

最新版本 0.10.0 发布于 2026/11/11(今天);至今共发布 16 个版本,其中过去 12 个月发布了 16 个;首次发布于 2026/10/11。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。