
iii 引擎可观测性实战用 iii-observability 统一分布式追踪、结构化日志与指标【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii本文是一份围绕 iii 项目内建可观测性方案的技术指南核心讲解iii-observability工作线程如何基于 OpenTelemetry 为整个系统提供分布式追踪、结构化日志和指标并给出从 CLI 到控制台、再到源码级配置的完整实战路径。读完本文你将掌握 iii 系统的观测模型、Logger三语言接入方式、engine::*查询函数的用法以及采样、导出、告警等配置的底层原理。为什么 iii 的可观测性可以零埋点覆盖全系统iii 的架构决定了可观测性的天然优势系统中的每一次调用都要经过引擎——函数调用function invocations、触发器触发trigger firings、通道消息channel messages都流过引擎。由于所有 worker 都通过引擎通信引擎可以随着调用在 worker 之间流转而追踪工作无需每个 worker 自己埋点。负责把这些信息变成 OpenTelemetry 追踪、指标和日志的就是iii-observability工作线程。它由引擎自动注入其声明见 engine/src/workers/observability/iii.worker.yaml类型为type: engine官方文档明确提示不要在config.yaml或worker-compose.yaml中声明它也不需要把它写进engine.workers或项目containers:。安装它非常简单iii worker add iii-observability本文是快速上手导览。完整的配置项与全部查询函数清单见仓库内的工作线程文档 engine/src/workers/observability/README.md。OpenTelemetry 支持一次接入任意后端iii-observability完全基于 OpenTelemetry它产生跨 worker 跳转的分布式追踪distributed traces、指标metrics和结构化日志structured logs并且可以导出到任意兼容 OTel 的后端OTLP/gRPC、OTLP/HTTP protobuf 等或保留在内存中用于本地开发exporter: memory通过engine::*查询函数直接检索。采样sampling、留存retention和导出目标exporter targets都在工作线程配置上完成。这些配置项在引擎内置configuration工作线程中以iii-observability为 id 注册可以通过configuration::set或控制台动态修改持久化条目默认落盘于./config/iii-observability.yaml会在每次引擎启动时、日志/追踪初始化之前被重新读取因此即便需要重启才生效的字段编辑后也会在下次启动时自动应用。${VAR:default}占位符在字符串字段中可用读取时展开。核心配置字段字段类型说明enabledboolean是否启用 OpenTelemetry 追踪导出默认false环境变量OTEL_ENABLEDservice_namestring追踪与指标中的服务名默认iii环境变量OTEL_SERVICE_NAMEservice_versionstring服务版本service.versionOTel 属性环境变量SERVICE_VERSIONservice_namespacestring服务命名空间service.namespace属性环境变量SERVICE_NAMESPACEexporterstring追踪导出器memory、otlp或both。both表示既保留在 iii 内可查询、又导出到外部默认otlp环境变量OTEL_EXPORTER_TYPEendpointstringOTLP collector 基础端点默认http://localhost:4317环境变量OTEL_EXPORTER_OTLP_ENDPOINTsampling_rationumber全局追踪采样率0.0–1.0默认1.0环境变量OTEL_TRACES_SAMPLER_ARGmemory_max_spansnumber内存中保留的最大 span 数默认1000环境变量OTEL_MEMORY_MAX_SPANSmetrics_enabledboolean是否启用指标采集默认false环境变量OTEL_METRICS_ENABLEDmetrics_exporterstring指标导出器memory或otlp默认memorymetrics_retention_secondsnumber指标内存留存秒数默认3600logs_enabledboolean是否启用结构化日志存储logs_exporterstring日志导出器memory、otlp或both默认memory环境变量OTEL_LOGS_EXPORTERlogs_max_countnumber内存中最大日志条数默认1000logs_retention_secondsnumber日志内存留存秒数默认3600logs_sampling_rationumber日志留存采样比例0.0–1.0默认1.0logs_console_outputboolean是否将摄入日志打印到控制台默认truelevelstring最低日志级别trace、debug、info、warn、error默认infoformatstring日志输出格式default或json默认defaultalertsAlertRule[]基于指标求值的告警规则OTLP 传输细节默认情况下追踪与指标通过OTLP/gRPC导出https://端点使用系统根证书的 TLShttp://端点使用明文传输。若想改用 OTLP/HTTP protobuf在启动引擎前设置标准协议环境变量即可export OTEL_EXPORTER_OTLP_PROTOCOLhttp/protobuf也可以按信号细分覆盖export OTEL_EXPORTER_OTLP_TRACES_PROTOCOLgrpc export OTEL_EXPORTER_OTLP_METRICS_PROTOCOLhttp/protobuf选择 HTTP/protobuf 后iii 会把endpoint当作 collector 基础 URL 并自动追加信号路径追踪/v1/traces、指标/v1/metrics日志导出器通过 HTTP 发送 OTLP 日志到/v1/logs。需要鉴权或路由头的 collector可使用标准 OTLP 头环境变量例如OTEL_EXPORTER_OTLP_HEADERSAuthorizationBearer $OTLP_TOKEN日志优先读OTEL_EXPORTER_OTLP_LOGS_HEADERS再回退到全局头。想让 iii 控制台在导出到外部 collector 的同时保持可用请为追踪设置exporter: both、为日志设置logs_exporter: both。结构化日志Logger 直通 OpenTelemetry 管线Worker 代码通过观测性 SDK 提供的Logger输出结构化日志这些日志进入同一条 OpenTelemetry 管线因此日志行会与它们发生时的 trace 关联起来而不是写到原始 stdout。这正是日志与追踪天然关联的关键设计日志携带 trace 上下文排查问题时可以从一条日志直接跳到所属调用链。以下是官方文档给出的三种语言写法// Node / TypeScript import { Logger } from iii-dev/helpers/observability; const logger new Logger(); // each level takes a message and optional structured data logger.debug(cache lookup, { key }); logger.info(processing link, { slug }); logger.warn(retrying upstream, { attempt }); logger.error(failed to persist, { slug, err });# Python from iii_helpers.observability import Logger logger Logger() # each level takes a message and optional structured data logger.debug(cache lookup, {key: key}) logger.info(processing link, {slug: slug}) logger.warn(retrying upstream, {attempt: attempt}) logger.error(failed to persist, {slug: slug, err: str(err)})// Rust use iii_helpers::observability::Logger; use serde_json::json; let logger Logger::new(); // each level takes a message and optional structured data logger.debug(cache lookup, Some(json!({ key: key }))); logger.info(processing link, Some(json!({ slug: slug }))); logger.warn(retrying upstream, Some(json!({ attempt: attempt }))); logger.error(failed to persist, Some(json!({ slug: slug, err: err.to_string() })));每个级别方法都接受消息 可选结构化数据。以 Node SDK 为例Logger采用懒初始化首次使用时才获取底层 OTel logger见 sdk/packages/node/helpers/src/observability/logger.tstrace 上下文由 SDK 自动注入你无需手动传递trace_id。除了在代码里打日志你还可以通过观测性工作线程的触发器从 CLI 直接产出日志行、并检索已存储的日志# emit a log line from the CLI iii trigger engine::log::info --json {message:hello from the CLI} # find it in the stored logs iii trigger engine::logs::list | grep -C 10 hello从源码看日志查询函数engine::logs::list支持start_time、end_time、trace_id、span_id、severity_min1–24数值越大越严重、severity_text、offset、limit等过滤器输入结构见 engine/src/workers/observability/mod.rs 中的LogsListInput返回包含logs、total、query、timestamp的响应。分布式追踪跨 worker 的 span 树一条 trace 捕获一次调用跨 worker 流转的全部 span是端到端调试请求的头条视图。trace 来源于 worker 函数调用worker 每次处理一次调用就记录一个 span。需要注意的默认行为内建engine::*函数默认不被追踪需要设置III_OTEL_TRACE_BUILTINStrue才会纳入。该开关在源码 engine/src/workers/telemetry/mod.rs 的trace_builtins_enabled()中解析接受1或true默认关闭是因为无上下文的引擎内建调用是高频管道控制台 RPC 轮询、启动期读取、引擎自身机制每个都会成为新单 span trace 的根淹没 trace 列表。而本身就携带调用方traceparent的内建调用始终会被追踪。此外观测性管线自身的查询/摄入函数engine::logs::*、engine::traces::*等永远不会被追踪——连III_OTEL_TRACE_BUILTINS也不能开启否则观察观察者会让 span 循环回流span → 实时推送 → 投递 span → 再推送……。所以要产生一条 trace先调用一个 worker 函数。官方文档推荐用 sandboxes 工作线程 的sandbox::run快速起步# add the sandbox worker if you dont have it yet iii worker add iii-sandbox # run something to produce a trace iii trigger sandbox::run imagepython langpython codeprint(1) # count the recorded spans (workers export them a moment after the call, # so re-run this until it reports a non-zero count) iii trigger engine::traces::list | jq .total # grab the most recent trace id and print its span tree TID$(iii trigger engine::traces::list | jq -r .traces[-1].trace_id) iii trigger engine::traces::tree trace_id$TID如果你使用 worker-compose 编排则可以把iii-sandbox声明为引擎自有例外放在顶层engine.workers下而不是containers下engine: workers: iii-sandbox: {}然后用iii compose --up启动该文件再调用 sandbox 函数。注意engine::traces::tree需要真实的trace_id而 trace 导出存在短暂延迟。如果engine::traces::list仍报告0或上面取trace_id的调用解析为null而失败请等几秒再重试。追踪查询函数函数说明engine::traces::list每个 trace 一条紧凑摘要子 span 贡献聚合状态与计数可用search_all_spans跨全部 span 搜索attribute_projection只返回请求的属性engine::traces::spans列出完整存储的 span 记录含属性、事件、链接面向需要完整 span 载荷的详情/时间线消费方engine::traces::tree以层级 span 树形式取回一条 trace参数trace_id必填engine::traces::clear清空内存中的全部存储 spanengine::traces::list支持丰富的过滤trace_id/trace_ids、service_name、name、statuserror/pending/ok/unset、min_duration_ms/max_duration_ms、start_time/end_timeUnix 毫秒、sort_bystart_time/duration/service_name/name、sort_order、属性精确匹配attributes、排除exclude_attributes、include_internal等全部定义在 engine/src/workers/observability/mod.rs 的TracesListInput中。Live进行中span从源码看还有一个很实用的设计——live spans使用memory导出器时本地开发默认span 在开始的瞬间就会被镜像进内存存储标记为pending: trueend_time_unix_nano: 0状态读作unsetspan 关闭时最终 span原地替换快照同一存储位置每个 span id 一条记录。这就是实时 trace 视图能展示进行中工作的原因引擎侧父 spantrigger fn、enqueue、内建call fn在子工作仍在运行时即可见trace 一开始出现就能出现在列表视图。该行为仅存在于内存存储与查询视图OTLP 导出路径永远只发送完整的 spanend_time_unix_nano在 OTLP 线上是语义必需的。exporter: both的生产形态可用live_spans: true或OTEL_LIVE_SPANStrue显式开启。健康检查与数据清理开发过程中可以用以下内建函数检查引擎健康状态、清理已存储的遥测数据# overall health status iii trigger engine::health::check | jq -r .status # clear stored logs iii trigger engine::logs::clear # the logs are now empty iii trigger engine::logs::list # clear stored traces iii trigger engine::traces::clear # the span count is now zero iii trigger engine::traces::list | jq .totalengine::health::check返回status、componentsotel、metrics、logs、spans 四组件的healthy/disabled状态、timestamp、version。注意日志填充非常快。engine::logs::clear之后紧跟engine::logs::list仍可能看到两次调用间隙新产生的日志——这是预期行为。在控制台中可视化控制台 会把这份遥测数据可视化渲染出来——运行中系统的 trace、日志和指标一目了然。因此日常开发中你通常不需要手写上面的查询函数这些engine::*查询接口更多服务于 CLI 脚本、自动化排查和 Agent 场景。配置深度热更新分层与告警采样iii-observability的完整配置面注册在内置configuration工作线程下见 engine/src/workers/observability/configuration.rs 的register_config存储条目是运行时的事实来源。configuration::updated事件会按字段分层热应用分层字段生效方式Live即时logs_console_output、logs_sampling_ratio、logs_enabled摄入闸门、enabled摄入闸门即时每次使用读取Limits限制memory_max_spans、logs_max_count、metrics_max_count、metrics_retention_seconds即时下次插入 / 60 秒清扫时强制Swap换装sampling_ratio、sampling.*、alerts、collapse_spans、level即时重建编译产物并换装存活的告警规则保持冷却/触发连续性Task rebuild任务重建logs_exporter、logs_batch_size、logs_flush_interval_ms、logs_retention_seconds等后台任务以新配置重启logs_enabled从 false→true 会复活日志存储、log 触发器订阅、OTLP 日志导出器与留存任务Restart-only仅重启exporter、endpoint、service_name/service_version/service_namespace、format、metrics_enabled、metrics_exporter等记录警告下次引擎启动时经持久化条目应用告警规则在 engine/src/workers/observability/config.rs 中定义字段包括name必填、唯一、metric必填如iii.invocations.error、threshold必填、operatorgreaterthan、greaterthanorequal、lessthan、lessthanorequal、equal、notequal默认greaterthanconfig.yaml中可用、等符号别名但通过configuration::set远程编辑必须使用规范小写名、window_seconds默认 60、cooldown_seconds默认 60、enabled默认 true、action{type:log}、{type:webhook,url:...}或{type:function,path:...}。高级采样支持按操作/按服务的规则与速率限制示例配置如下sampling: default: 1.0 parent_based: true rules: - operation: api.* rate: 0.1 rate_limit: max_traces_per_second: 100这些配置与configuration工作线程的集成行为首次启动播种、不覆盖已存值、${VAR:default}展开、schema 拒绝非法值有专门的端到端测试验证见 engine/tests/observability_configuration_e2e.rs。参考查询函数一览除了本文用到的日志与追踪函数iii-observability还提供以下查询面完整说明见 engine/src/workers/observability/README.md日志engine::log::info/warn/error/debug/trace均可接受message、data、trace_id、span_id、service_nameengine::logs::list、engine::logs::clear指标engine::metrics::list引擎计数器调用量、worker 数、性能分位数 p50/p95/p99 等、engine::rollups::list1/5/60 分钟聚合窗口其他engine::baggage::get/set/get_alltrace 上下文 baggage、engine::sampling::rules、engine::health::check、engine::alerts::list/evaluate此外观测性工作线程还提供log与trace两种触发器类型让任意 worker 或 Web 控制台能响应式刷新而不是轮询log触发器可按level订阅如error级别触发告警函数trace触发器是约 300ms 合并的traces 已变化节拍处理函数收到窗口内受影响的 trace id 列表后再通过engine::traces::*重读详情引擎内部 span 与触发器自身投递产生的 span 会被排除避免无限反馈循环。至此你已经掌握了从引擎中心化观测的架构原理到Logger接入、CLI 查询、trace 树查看、健康检查清理、控制台可视化再到采样、告警与热更新分层的完整闭环——足以在实际的 iii 系统中高效定位与排查问题。【免费下载链接】iiiEffortlessly compose, extend, and observe every service in real-time for the first time ever.项目地址: https://gitcode.com/GitHub_Trending/mo/iii创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考