ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Quickwit 原生 OTLP 分布式追踪服务:gRPC 端点、Span 数据模型与配置实战

Quickwit 原生 OTLP 分布式追踪服务:gRPC 端点、Span 数据模型与配置实战 Quickwit 原生 OTLP 分布式追踪服务gRPC 端点、Span 数据模型与配置实战【免费下载链接】quickwitCloud-native OSS search engine for observability项目地址: https://gitcode.com/GitHub_Trending/qu/quickwitQuickwit 原生支持 OpenTelemetry ProtocolOTLP开箱即用地提供了一个 gRPC 端点用于接收来自 OpenTelemetry Collector 或应用内 exporter 上报的 Span 数据并自动完成索引创建与写入。本文将以 docs/distributed-tracing/otel-service.md 为主线结合仓库源码系统讲解 OTLP 端点的启用/禁用方式、自定义索引路由、otel-traces-v0_*索引的完整 Doc Mapping以及当前版本的已知限制帮助你快速把 Quickwit 接入现有可观测性链路构建云原生的分布式追踪后端。OTLP 服务概览Quickwit 如何接收 Span分布式追踪用于跟踪一个请求在多个服务前端、后端、数据库等之间的流转过程是排查性能瓶颈的利器。Quickwit 作为云原生的非结构化数据检索引擎天然适合充当 Trace 后端。它原生实现了 OpenTelemetry Protocol (OTLP) 的 gRPC 端点Span 可以来自一个独立的OpenTelemetry Collector通过 otlp exporter 转发应用代码中的OTLP exporter如 Python SDK 的OTLPSpanExporter直连 Quickwit。该端点默认启用。启用后Quickwit 会启动一个 gRPC 服务等待接收 Span并把数据索引到默认索引中如果该索引不存在Quickwit 会自动创建无需人工干预。从源码看OTLP 服务的注册发生在 quickwit-serve/src/grpc.rs 中服务启动时会根据services.otlp_traces_service_opt是否存在来决定是否挂载TraceServiceServer并为其开启Gzip 与 Zstd 两种压缩编码支持同时应用grpc_config.max_message_size限制消息大小。也就是说OTLP gRPC 端点与 Quickwit 自身的 gRPC 服务共用同一端口默认7281与同一套消息体量控制。需要注意的是OTLP 端点只在启用了indexer服务的节点上生效。核心判断逻辑位于 quickwit-serve/src/lib.rsif node_config.is_service_enabled(QuickwitService::Indexer) node_config.indexer_config.enable_otlp_endpoint { // ... 构建 OtlpGrpcLogsService / OtlpGrpcTracesService }即“indexer 服务开启”且“enable_otlp_endpoint为 true”两个条件同时满足时端点才会被创建。启用与禁用 OTLP 端点默认行为与禁用方式OTLP 端点默认开启其默认值来源于 quickwit-config/src/node_config/mod.rs 中的default_enable_otlp_endpoint()它读取环境变量QW_ENABLE_OTLP_ENDPOINT未设置时默认为true。如果出于安全、资源或其他原因需要关闭该端点官方文档提供了两种等价方式方式一环境变量QW_ENABLE_OTLP_ENDPOINTfalse ./quickwit run方式二节点配置node config# ... Indexer configuration ... indexer: enable_otlp_endpoint: false该配置项在 docs/configuration/node-config.md 的 Indexer 配置表中也有登记默认值标为false表示仅在显式开启或依赖环境变量默认值的情况下启用实际运行时默认行为以QW_ENABLE_OTLP_ENDPOINT为准。完整示例参见 config/quickwit.yaml其中indexer小节包含该参数及其它索引器参数indexer: enable_otlp_endpoint: true split_store_max_num_bytes: 100G split_store_max_num_splits: 1000 max_concurrent_split_uploads: 12提示在测试环境或 CI 中启用testsuitefeature 时源码将默认值强制为false避免测试进程意外监听 OTLP 端口。验证服务是否就绪启动后OpenTelemetry 生态的 exporter 将默认把 Span 上报到http://quickwit-host:7281gRPC。若希望 Quickwit 自产自销——把自己的内部追踪 Span 发送给自己——可以参考 docs/distributed-tracing/plug-quickwit-to-jaeger.md 的启动方式QW_ENABLE_OPENTELEMETRY_OTLP_EXPORTERtrue \ OTEL_EXPORTER_OTLP_ENDPOINThttp://127.0.0.1:7281 \ ./quickwit run这样 Quickwit 自身的 Span 也会进入 Trace 索引进而可以在 Jaeger UI 中观测 Quickwit 的完整搜索链路。将 Span 发送到自定义索引默认情况下Span 会被写入默认 Trace 索引。若希望把不同服务的 Trace 拆分到不同索引中只需在 gRPC 请求的 metadata 中设置自定义 headerqw-otel-traces-index: 目标索引 ID该 header 的解析逻辑位于 quickwit-opentelemetry/src/otlp/mod.rs 的extract_otel_index_id_from_metadata()从请求元数据中读取qw-otel-traces-index若缺失则回退到默认索引 ID同时会对索引 ID 做合法性校验非法值会直接返回错误。对于 HTTP 路径Quickwit 还额外提供了两种 REST 风格的上报入口实现在 quickwit-serve/src/otlp_api/rest_handler.rs路径说明POST /otlp/v1/traces默认 Trace 索引也可通过 headerqw-otel-traces-index指定目标索引POST /{index}/otlp/v1/traces直接在 URL 路径中指定目标索引 IDPOST /otlp/v1/logs默认 Logs 索引otel-logs-v0_*header 为qw-otel-logs-indexPOST /{index}/otlp/v1/logs在 URL 路径中指定 Logs 目标索引注意当前仓库源码中默认 Trace 索引常量为OTEL_TRACES_INDEX_ID otel-traces-v0_9定义于 quickwit-opentelemetry/src/otlp/traces.rs。文档早期版本写作otel-trace-v0_7属于版本演进过程中的命名差异由于 Jaeger 集成使用通配符模式otel-traces-v0_*见下文新旧版本索引均可被检索到无需担心向后兼容。通过 OpenTelemetry Collector 转发如果你已经有自己的 OpenTelemetry Collector只需在其配置中增加一个指向 Quickwit 的 OTLP gRPC exporter参考 docs/distributed-tracing/send-traces/using-otel-collector.mdreceivers: otlp: protocols: grpc: http: processors: batch: exporters: otlp/quickwit: endpoint: 127.0.0.1:7281 # macOS/Windows 上使用 host.docker.internal:7281 tls: insecure: true # 默认写入 otel-traces-v0_*如需指定索引取消注释 # headers: # qw-otel-traces-index: otel-traces-v0_9 service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlp/quickwit]启动 Collector 后可以用 cURL 向 Collector 的 HTTP 端口4318发送一条 JSON 格式的 Trace 做冒烟测试随后在 Quickwit 日志中会看到new-split之类的索引器日志表示 Span 已被接收并进入索引管线。此外Quickwit 的通用 source 也支持 OTLP 格式的输入input_format: otlp_traces_proto/otlp_traces_json例如可以从 Kafka 消费 OTLP Protobuf 编码的 Span参考 config/tutorials/otel-traces/kafka-source.yamlversion: 0.8 source_id: kafka-source source_type: kafka input_format: otlp_traces_proto params: topic: otlp_spans client_params: bootstrap.servers: localhost:9092Trace 与 Span 数据模型概念Trace 与 SpanTrace一组 Span 的集合代表一次完整的请求链路例如一次用户点击经过网关、服务 A、服务 B 与数据库。SpanTrace 中的单个操作单元描述一次具体的调用如一次 HTTP 处理、一次数据库查询。OpenTelemetry Collector 将 Span 批量上报给 QuickwitQuickwit 把 OTLP Span 模型映射为索引文档写入otel-traces-v0_*索引。该模型派生自 OpenTelemetry Trace API 规范。默认索引 Doc Mapping 详解下面是otel-traces-v0_*索引的 Doc Mapping基于 docs/distributed-tracing/otel-service.md并对照源码内嵌模板OTEL_TRACES_INDEX_CONFIG见 quickwit-opentelemetry/src/otlp/traces.rs 第 57–173 行version: 0.8 index_id: otel-traces-v0_9 doc_mapping: mode: strict field_mappings: - name: trace_id type: bytes input_format: hex output_format: hex fast: true - name: trace_state type: text indexed: false - name: service_name type: text tokenizer: raw fast: true - name: resource_attributes type: json tokenizer: raw - name: resource_dropped_attributes_count type: u64 indexed: false - name: scope_name type: text indexed: false - name: scope_version type: text indexed: false - name: scope_attributes type: json indexed: false - name: scope_dropped_attributes_count type: u64 indexed: false - name: span_id type: bytes input_format: hex output_format: hex - name: span_kind type: u64 - name: span_name type: text tokenizer: raw fast: true - name: span_fingerprint type: text tokenizer: raw - name: span_start_timestamp_nanos type: datetime input_formats: [unix_timestamp] output_format: unix_timestamp_nanos indexed: false fast: true fast_precision: milliseconds - name: span_end_timestamp_nanos type: datetime input_formats: [unix_timestamp] output_format: unix_timestamp_nanos indexed: false fast: false - name: span_duration_millis type: u64 indexed: false fast: true - name: span_attributes type: json tokenizer: raw fast: true - name: span_dropped_attributes_count type: u64 indexed: false - name: span_dropped_events_count type: u64 indexed: false - name: span_dropped_links_count type: u64 indexed: false - name: span_status type: json indexed: true - name: parent_span_id type: bytes input_format: hex output_format: hex indexed: false - name: is_root type: bool indexed: true stored: false - name: events type: arrayjson tokenizer: raw fast: true - name: event_names type: arraytext tokenizer: default record: position stored: false - name: links type: arrayjson tokenizer: raw timestamp_field: span_start_timestamp_nanos indexing_settings: commit_timeout_secs: 5 search_settings: default_search_fields: [service_name, span_name, event_names]说明is_root字段与commit_timeout_secs: 5、default_search_fields取自当前源码中的内嵌模板旧版文档中的 Mapping 未包含is_root且commit_timeout_secs为 10。如果你在自建索引时参考本文请以当前版本的实际模板为准。仓库中另有一份更早期的示例配置 config/tutorials/otel-traces/index-config.yaml使用span_start_timestamp_secs作时间戳字段、partition_key: service_name可作为自定义 Trace 索引的对照参考。关键字段解析标识与关联字段trace_id/span_id/parent_span_id以十六进制字节存储是链路追踪的核心关联键。trace_id开启了fast字段用于加速按 trace 聚合查询。span_kindSpan 类型u64编码。源码SpanKind支持 6 种取值0unspecified、1internal、2server、3client、4producer、5consumer。service_name服务名采用raw分词器并开启fast是 Jaeger UI 中“按服务过滤”的关键字段。它来源于 OTLP Resource 上的service.name属性缺失时默认取unknown_service见源码UNKNOWN_SERVICE常量。span_nameSpan 名称raw分词 fast。时间与耗时字段span_start_timestamp_nanosdatetime类型输入为unix_timestamp输出为纳秒同时是索引的timestamp_field所有按时间范围过滤的 Trace 查询都会命中该字段。开启fast且fast_precision: milliseconds在毫秒级精度上压缩存储以节省空间。span_end_timestamp_nanos结束时间只做存储不做索引。span_duration_millisSpan 耗时毫秒数由源码根据end_time_unix_nano - start_time_unix_nano换算得到span_duration_nanos / 1_000_000开启fast便于排序与耗时分析。属性与诊断字段resource_attributes/span_attributesResource 级与 Span 级属性均以json类型存储tokenizer: raw。源码通过extract_attributes()将 OTLP 的KeyValue列表转换为 JSON 对象支持字符串、布尔、整数、浮点、数组与嵌套 KV 结构OTLP 的 bytes 类型暂不支持会被忽略并告警。span_status状态对象含code与可选messageindexed: true可支持按状态码检索。span_fingerprint由“服务名 Span 类型 Span 名称”三段拼接而成的签名SpanFingerprint::newJaeger 的 service/operation 下拉列表与按操作聚合即依赖该字段。events/event_names/linksSpan 事件与链路链接。event_names单独抽取为arraytext并使用default分词器 record: position支持对事件名做全文检索。dropped_*系列字段记录 OTLP 上报时因超限被丢弃的属性/事件/链接数量便于评估数据完整性。is_root布尔字段由源码根据parent_span_id是否为空推导is_root: Some(parent_span_id.is_none())用于快速筛选根 Span。索引文档的生成链路从源码quickwit-opentelemetry/src/otlp/traces.rs可以还原一条 Span 从 gRPC 到索引的完整链路TraceService::export()接收ExportTraceServiceRequest先从 metadata 中解析目标索引 IDparse_otlp_spans()遍历resource_spans → scope_spans → spans为每个 Span 执行Span::from_otlp()把 OTLP 的Resource、InstrumentationScope、Span三种模型扁平化为一个 JSON 文档parse_spans()使用JsonDocBatchV2Builder将文档组装为DocBatchV2交给ingest_doc_batch_v2()路由到 Quickwit 的 ingest 管道INGEST_V2_SOURCE_ID请求处理中统计INGESTED_SPANS_TOTAL、INGESTED_BYTES_TOTAL、REQUESTS_TOTAL等指标并在响应中通过ExportTracePartialSuccess上报被拒绝的 Span 数量与错误信息。对应地仓库中的单元测试同文件的tests模块与 quickwit-serve/src/otlp_api/rest_handler.rs 的集成测试覆盖了默认端点、gzip 压缩、header 指定索引、路径指定索引等多种场景可作为自建 Trace 索引时的行为参考。结合 Jaeger UI 可视化 TraceQuickwit 实现了与 Jaeger gRPC API 兼容的 SpanReader 服务见 quickwit-jaeger/src/lib.rs因此可以直接用 Jaeger UI 查询 Quickwit 中存储的 Trace。Jaeger 的查询会作用于所有匹配otel-traces-v0_*模式的索引——这正是上文所说索引命名需要遵循该模式的原因。启动 Jaeger Query 时指定存储类型为grpcJaeger 1.58 之前为grpc-plugin# Linux 下使用 host 网络模式 docker run --rm --name jaeger-qw --networkhost \ -e SPAN_STORAGE_TYPEgrpc \ -e GRPC_STORAGE_SERVER127.0.0.1:7281 \ -p 16686:16686 \ jaegertracing/jaeger-query:1.60随后打开http://localhost:16686即可按服务、操作、时间范围检索 Trace。完整的分布式追踪概览如下图所示来自 docs/distributed-tracing/overview.md更多端到端细节包括在 Jaeger UI 中观察 Quickwit 自身find_traces、root_search、leaf_search等内部调用链可阅读 docs/distributed-tracing/plug-quickwit-to-jaeger.md应用侧的上报方式可参考 docs/distributed-tracing/send-traces/using-otel-collector.md 与 docs/distributed-tracing/send-traces/using-otel-sdk-python.md。已知限制与注意事项基于当前文档与源码在使用 Quickwit 作为分布式追踪后端时有以下限制需要提前评估OTLP gRPC 服务不提供高持久性High Durability文档明确指出该问题计划在后续版本修复。如果你的追踪数据要求严格的持久化保证需要结合其他数据通道如 Kafka source做灾备设计。OTLP HTTP 仅支持 Binary Protobuf 编码通过 REST 入口上报时Content-Type必须为application/x-protobuf见 quickwit-serve/src/otlp_api/rest_handler.rs 中warp::header::exact_ignore_case(content-type, application/x-protobuf)的强制校验OTLP HTTP 的 JSON 编码尚不支持若确有需求应关注上游 issue。索引版本命名随版本演进文档中的otel-trace-v0_7与当前源码的otel-traces-v0_9存在差异实际使用时应以当前版本常量为准并保持 Jaeger 查询模式otel-traces-v0_*的一致。总体而言Quickwit 的 OTLP 服务让“应用 → Collector / SDK → Quickwit 索引 → Jaeger UI 可视化”这条链路可以零成本打通默认索引自动创建、gRPC/HTTP 双入口、按 header 或路径路由自定义索引配合otel-traces-v0_*的 Jaeger 集成模式即可快速搭建一套云原生的分布式追踪后端。【免费下载链接】quickwitCloud-native OSS search engine for observability项目地址: https://gitcode.com/GitHub_Trending/qu/quickwit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表