@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/search | q (跟踪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/tags | scope =: 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页:1middleware.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口. |
部分 嘲笑鸟。 。 。 .