可观测技术
更新时间:2025/7/7
在Gitcode上查看源码

可观测是基于openTelemetry规范构建的可视化能力,主要围绕系统中的可观测数据(包括指标、跟踪和日志),提供采集、上报以及与多种可视化工具集成的能力,帮助用户更好的监控系统状态、预测运行趋势、分析和定位系统故障。

背景介绍

跟踪(Traces)

跟踪是一组事件,这些事件是由单个逻辑操作触发的,并通过应用程序的各个组件处理后最终整合在一起。跟踪可能包含跨越进程、网络和安全边界的事件,因此也被称为分布式跟踪,当有人按下按钮在网站上启动一个操作时,就可能会启动分布式跟踪。 具体来说,跟踪可以被认为是跨度(Span)的有向无环图 (DAG),其中跨度之间的边定义为父子关系。例如,以下是一个由6个跨度组成的跟踪示例:

text
            [Span A]  ←←←(the root span)
               |
        +------+------+
        |             |
    [Span B]      [Span C] ←←←(Span C is a `child` of Span A)
        |             |
    [Span D]      +---+-------+
                  |           |
               [Span E]    [Span F]

使用时间轴来显示跟踪轨迹会更容易理解,如下图所示:

text
––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time

 [Span A···················································]
   [Span B··············································]
      [Span D··········································]
    [Span C········································]
         [Span E·······]        [Span F··]

指标(Metrics)

指标是是对系统行为、性能或状态的量化测量,可以是任何可测量的数值,例如CPU使用率、内存占用率、请求延迟、错误率等。记录测量值主要涉及计量仪(Meter)、仪表(Instrument)和测量值(Measurement):

  • 计量器(Meter):主要负责创建和管理仪表(Instrument)。
  • 仪表(Instrument):具有名称、类型、描述和单位等标识,主要用于捕捉和记录测量值。
  • 测量值(Measurement):单次记录的原始值,包含键值对属性标签,用于标记和区分不同场景下的测量值。
text
+------------------+
| MeterProvider    |                 +-----------------+             +--------------+
|   Meter A        | Measurements... |                 | Metrics...  |              |
|     Instrument X +-----------------> In-memory state +-------------> MetricReader |
|     Instrument Y |                 |                 |             |              |
|   Meter B        |                 +-----------------+             +--------------+
|     Instrument Z |
|     ...          |                 +-----------------+             +--------------+
|     ...          | Measurements... |                 | Metrics...  |              |
|     ...          +-----------------> In-memory state +-------------> MetricReader |
|     ...          |                 |                 |             |              |
|     ...          |                 +-----------------+             +--------------+
+------------------+

日志(Logs)

日志用于记录应用程序的事件和状态信息,方便调试和故障排查

  • OTel Logging API:原生日志接口(Logger/LoggerProvider)
  • 上下文注入:自动添加 TraceID/SpanID 实现日志-追踪关联 核心组件和数据流向如下
text
+----------------------------------------------------------------+
|                           Application                          |
|                                                                |
|          +----------------------+       +-------------------+  |
|          |   OTel Logging API   |       |   OTel Context    |  |
|          |   (Logger/Logger-   +------->   Propagator       |  |
|          |  Provider/LogRecord) |       | (TraceID/SpanID)  |  |
|          +----------+-----------+       +---------+---------+  |
|                     |                             |            |
|                     |        Inject Context       |            |
|                     +<----------------------------+            |
|                     |                                          |
|          +----------v-----------+                              |
|          |   OTel Logs SDK      |                              |
|          |  +-----------------+ |                              |
|          |  | LogRecord       | |       +-------------------+  |
|          |  | Processor       +--------->   Resource        |  |
|          |  | (Batch/Simple)  | |       | (service.name,    |  |
|          |  +--------+--------+ |       |  host.name, etc.) |  |
|          |           |          |       +---------+---------+  |
|          |  +--------v--------+ |                 |            |
|          |  | LogRecord       | |    Add Resource |            |
|          |  | Exporter        +<------------------+            |
|          |  | (OTLP/Console)  | |                              |
|          |  +-----------------+ |                              |
|          +----------+-----------+                              |
+----------------------------------------------------------------+

数据模型

跟踪

跟踪的数据模型

text
┌───────────────────────────────┐
│         TracerProvider        │
├───────────────────────────────┤
│ + getTracer(name, version)    │
└──────────────┬────────────────┘
               │ creates

┌───────────────────────────────┐
│            Tracer             │
├───────────────────────────────┤
│ + startSpan(name, options)    │
└──────────────┬────────────────┘
               │ creates

┌───────────────────────────────┐ has  ┌──────────────┐
│             Span              │◆──▶ │ SpanContext  │
├───────────────────────────────┤      ├──────────────┤
│ - name: string                │      │ - traceId    │ 
│ - startTime: timestamp        │      │ - spanId     │
│ - endTime: timestamp          │      │ - traceFlags │
│ - parentSpanId: String        │      │ - isRemote   │
├───────────────────────────────┤      └──────────────┘ 
│ + setAttribute(k,v)           │ contains ┌─────────────┐
│ + addEvent(name, attributes)  │───────▶ │  Attribute  │
│ + recordException(exception)  │          ├─────────────┤
│ + end()                       │          │ - key       │
└──────────────┬────────────────┘          │ - value     │
               │ contains                  └─────────────┘
               ▼                                 ▲
        ┌─────────────┐       contains           │
        │    Event    │──────────────────────────┘
        ├─────────────┤
        │ - name      │
        │ - timestamp │
        └─────────────┘

跨度的组成

  • 操作名称。
  • 开始和结束时间戳。
  • 属性:键值对列表。
  • 事件:零个或多个事件的集合,每个事件本身都是一个元组(时间戳、名称、属性)。名称必须是字符串。
  • 父级跨度标识符。
  • 链接:指向零个或多个因果相关的跨度的链接(通过这些相关的跨度上下文)。
  • 上下文:引用跨度所需的跨度上下文(Span Context)信息。

跨度的名称

跨度的名称简洁地标识了跨度所代表的工作,例如RPC方法名称、函数名称或更大计算中的子任务或阶段的名称。

跨度的类型

  • SERVER 表示跨度涵盖了服务端处理的远程请求,而客户端等待响应。
  • CLIENT 表示跨度描述了一个远程服务的请求,客户端等待响应。当 CLIENT 跨度的上下文被传播时,CLIENT 跨度通常会成为远程 SERVER 跨度的父级。
  • PRODUCER 表示跨度描述了本地或远程操作的启动或调度。这个启动跨度通常在相关的 CONSUMER 跨度结束之前结束,甚至可能在 CONSUMER 跨度开始之前结束。 在具有批处理的消息传递场景中,跟踪单个消息需要为每条消息创建一个新的 PRODUCER 跨度。
  • CONSUMER 表示跨度代表由生产者启动的操作的处理,生产者不等待结果。
  • INTERNAL 默认值。表示跨度代表应用程序内的内部操作,而不是具有远程父级或子级的操作。

指标

指标的数据模型

text
  Metric
+------------+
|name        |
|description |
|unit        |     +------------------------------------+
|data        |---> |Gauge, Counter, Histogram, ...      |
+------------+     +------------------------------------+

  Data [One of Gauge, Counter, Histogram, ...]
+-----------+
|...        |  // Metadata about the Data.
|points     |--+
+-----------+  |
               |      +---------------------------+
               |      |DataPoint 1                |
               v      |+------+------+   +------+ |
            +-----+   ||label |label |...|label | |
            |  1  |-->||value1|value2|...|valueN| |
            +-----+   |+------+------+   +------+ |
            |  .  |   |+-----+                    |
            |  .  |   ||value|                    |
            |  .  |   |+-----+                    |
            |  .  |   +---------------------------+
            |  .  |                   .
            |  .  |                   .
            |  .  |                   .
            |  .  |   +---------------------------+
            |  .  |   |DataPoint M                |
            +-----+   |+------+------+   +------+ |
            |  M  |-->||label |label |...|label | |
            +-----+   ||value1|value2|...|valueN| |
                      |+------+------+   +------+ |
                      |+-----+                    |
                      ||value|                    |
                      |+-----+                    |
                      +---------------------------+

指标的组成

  • 指标由元数据和数据组成。
  • 元数据部分包含多个属性:
    • 指标名称。
    • 属性 (维度,也被称为标签)。
    • 值类型(整数、浮点等)。
    • 计量单位。
  • 数据是计数器、仪表、直方图等类型之一。
    • 数据点包含时间戳、属性和值。

指标的名称

  • 不能为空字符串。
  • 不区分大小写的ASCII字符串。
  • 第一个字符必须是字母。后续字符必须是字母数字字符、“_”、“.”、“-”和“/”。
  • 最大长度为 255 个字符。

指标的名称约定

  • limit - 一种测量某种已知总量的恒定值的工具应称为entity.limit。例如,system.memory.limit 表示系统内存的总量。
  • usage - 一种测量已知总量(有限的)中已使用量的工具应称为 entity.usage。例如,system.memory.usage 带有属性 state = used | cached | free |… 表示每种状态下的内存量。在适当的情况下,所有属性值的总使用量应等于总量。
  • utilization - 一种测量使用量相对于其限制的比例工具应称为 entity.utilization。例如,system.memory.utilization 表示正在使用的内存比例。
  • time - 一种测量时间流逝的工具应称为 entity.time。例如,system.cpu.time 带有属性 state = idle | user | system |… 时间测量不一定是墙钟时间,可能小于或大于测量之间的实际墙钟时间。
  • io - 一种测量双向数据流的工具应称为 entity.io,并具有方向属性。例如,system.network.io。

日志

日志的数据模型

text
Logger
+------------------+
| name             |
| version          |     +------------------------------------+
| ...              |---> |LogRecord 1                         |
+------------------+     |+----------------+----------------+|
                         || Timestamp      |  timestamp     ||
                         |+----------------+----------------+|
                         || SeverityNumber |  severity_num  ||
                         |+----------------+----------------+|
                         || SeverityText   |  severity_text ||
                         |+----------------+----------------+|
                         || Body           |  body          ||
                         |+----------------+----------------+|
                         || Attributes     |  +-----------+ ||
                         ||                |  |key: value | ||
                         ||                |  |...        | ||
                         ||                |  +-----------+ ||
                         |+----------------+----------------+|
                         || TraceId        |  (optional)    ||
                         || SpanId         |  (optional)    ||
                         |+----------------+----------------+|
                         +------------------------------------+
                                        .
                                        .
                                        .
                         +------------------------------------+
                         |LogRecord N                         |
                         | ...                                |
                         +------------------------------------+

日志的组成

  • 定义了一个与供应商无关的日志数据模型(Log Record),包含核心字段如时间戳、严重级别、消息体、Trace ID、Span ID、资源属性(服务名、实例ID等)、属性(键值对)。

属性

属性在跟踪、指标和日志中都有使用。属性是一个键值对,必须具有以下要求:

  • 属性键必须是一个非空的字符串。键的大小写敏感,大小写不同的键被视为不同的键。
  • 属性值可以是:
    • 一个原始类型:字符串、布尔值、双精度浮点数(IEEE 754-1985)或带符号的 64 位整数。
    • 一个原始类型值的数组。数组必须是同质的,即它不能包含不同类型的值。
  • 属性的最大个数128。

属性的名称

以otel.开头的属性名称属于OpenTelemetry规范保留定义。 属性的名称应遵循以下规则:

  • 名称应为小写。
  • 使用命名空间,并使用点字符分隔命名空间。例如,service.version 表示服务版本,其中 service 是命名空间,version 是该命名空间中的一个属性。命名空间可以嵌套。例如,telemetry.sdk 是顶级 telemetry 命名空间中的一个命名空间,而 telemetry.sdk.name 是 telemetry.sdk 命名空间中的一个属性。在合适的情况下使用命名空间(和点分隔符)。
  • 对于名称中每个多词的点分隔组件,使用下划线分隔单词(即使用 snake_case)。例如,http.response.status_code 表示 http 命名空间中的状态码。仅在点(命名空间)的使用没有意义或改变名称的语义意义时使用下划线。例如,使用 rate_limiting 而不是 rate.limiting。
  • 属性、事件、指标和其他名称应具有描述性和明确性。在引入描述对象某个属性的名称时,包含属性名称。例如,使用 file.owner.name 而不是 file.owner,以及 system.network.packet.dropped 而不是 system.network.dropped。避免引入在不同约定或工具中使用时含义不同的名称和命名空间。例如,使用 security_rule 而不是 rule。
  • 在不影响清晰度的情况下使用更短的名称。在多词组件中删除不必要的命名空间组件或单词。例如,vcs.change.id 与 vcs.repository.change.id 一样精确地描述拉取请求 ID。

可观测架构

可观测数据流图

  1. 应用组件通过应用框架基于openTelemetry SDK封装的跟踪、指标、日志接口采集应用可观测数据;
  2. 应用框架通过可观测组件openTelemetry SDK采样器、处理器和导出器处理可观测数据,并上报到可观测组件fluent-bit服务端;
  3. 可观测组件fluent-bit服务的根据可观测配置,转发和上报可观测数据到openUBMC外收集器及可视化平台;

应用接口

跟踪

本模块用于Trace相关能力接口的lua层隔离,以实现Lua层、封装层、开源引入层,Lua层与封装层、开源引入层隔离,Lua层与封装层之间通过弱引用隔离,在无法require到封装库时,Lua层提供空对象空接口保护业务不受影响。

tracer创建

tracer是Trace能力构建中最初一环,业务需要持有tracer用于创建span,利用span的记录存储上报能力构建跨服务跟踪链路,目前组件初始化过程中自动以组件名作为tracer name创建tracer并存储,组件后续调用get_tracer()将直接返回tracer,组件也可以通过传入参数name新建tracer

lua
-- 方法原型
local tracer = trace.get_tracer(name, version, url)

-- 使用示例
local trace = require 'telemetry.trace'
local name = ...
local trace_custom = trace.get_tracer(name, '1.0.0')
local trace_default = tracer.get_tracer()

req:

  • name: 必选参数,string类型,tracer名称,一般使用库名称. e.g. "hwdiscovery"
  • version: 可选参数,string类型,库版本. e.g. "1.0.0"
  • url: 可选参数,string类型,指向语义约定文档,用于属性命名规范. e.g. "https://xxx/"

rsp:

  • tracer: userdata类型,由业务持有并调用start_span进行span创建,然后进行后续操作;
  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

span创建

span是跟踪链路中的最小功能单元,生命周期一般为单个函数或代码块,业务在需要跟踪的位置创建span,并通过span提供的能力进行数据跟踪,在生命周期结束后进行上报,后台根据上报span间的关联将不同服务上报的span整合为一条完整的跟踪链路。

lua
-- 方法原型
local child_span = tracer:start_span(name, attribute, options)
local child_span_opt = trace.start_span(name, attribute, options)

-- 使用示例
function get_object()
    local root_span = tracer:start_span("get_object", {"level": "notice", "opcode": 1})
    local parent_span_context = root_span:get_context()
    local child_span = tracer:start_span("get_object", {"level": "notice", "opcode": 1}, {parent = parent_span_context})

    -- 支持不通过tracer直接创建span,trace会自动获取当前组件名与组件版本创建tracer
    local child_span_opt = trace.start_span("get_object", {"level": "notice", "opcode": 1}, {parent = parent_span_context})
end

req:

  • name: 必选参数,string类型,span的名称,无需唯一性,span创建时回分配span_id作为唯一性标识,业务不感知. e.g. "get_object";
  • attribute: 必选参数,字典类型,键必须为string,值只支持stringboolintdouble类型,span的属性,由用户根据需要使用,后续跟随span数据导出,可用于链路标记、数据筛选等. e.g. {"level": "notice", "opcode": 1};
  • options: 可选参数,字典类型,代表span创建时的可选配置项。可选项有:
    • parent: table类型,只能使用由span:get_context()导出的spancontext数据,传入时创建为child span,继承上级的trace_id, 不传入时创建为root span,作为整条跟踪链路的起始。
    • force_sample: bool类型,作为组件自定义采样标记,在业务需要强制跟踪采样时传入true

rsp:

  • span: userdata类型,由业务持有并调用相关方法完成跟踪链路的构建,Lua层未引用到封装层或创建失败会返回一个noop span,进行的任何操作都不会生效,数据也不会上报;
  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

span操作

set_attribute 设置span属性

span属性后续跟随span数据导出,可用于链路标记,数据筛选等。

lua
-- 方法原型
span:set_attribute(key, value)

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    span:set_attribute("level", "notice")

    local err_msg = span:set_attribute(key, value)
    local err_msg then
        log:error("%s", err_msg)
    end
end

req:

  • key: 必选参数,string类型,属性名称,若已存在该属性名,则该操作会修改原属性. e.g. "level";
  • value: 必选参数,支持stringboolintdouble类型,对应属性名的属性值。

rsp:

  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

span之间建立非父子关系的关联,一般为异步场景使用。

lua
-- 方法原型
span:add_link(span_context, attribute)

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    span:add_link(span_context, {"level": "notice", "opcode": 1})

    local err_msg = span:add_link(span_context, attribute)
    local err_msg then
        log:error("%s", err_msg)
    end
end

req:

  • span_context: 必选参数,字典类型,只能使用由span:get_context()导出的spancontext数据;
  • attribute: 可选参数,字典类型,键必须为string,值只支持stringboolintdouble类型,span的属性,添加links时的补充属性,由用户根据需要使用,后续跟随span数据作为links字段的额外字段导出. e.g. {"level": "notice", "opcode": 1}

rsp:

  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

add_event 添加span事件

在span中记录事件,类似日志记录操作,是用于可视化的主要部分。

lua
-- 方法原型
span:add_event(name, attribute)

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    span:add_event(string.format("get object failed: %s", ret), {"level": "notice", "opcode": 1})

    local err_msg = span:add_event(name, attribute)
    local err_msg then
        log:error("%s", err_msg)
    end
end

req:

  • name: 必选参数,string类型,事件描述信息,即日志记录内容. e.g. "get object failed";
  • attribute: 可选参数,字典类型,键必须为string,值只支持stringboolintdouble类型,添加event时的补充属性,添加event时的补充属性,由用户根据需要使用,后续跟随span数据作为event字段的额外字段导出. e.g. {"level": "notice", "opcode": 1}

rsp:

  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

set_status 设置当前span状态

设置当前span状态,默认状态为unset,支持unsetokerror三种状态设置,span状态可用于尾部采样、可视化筛选等。

lua
-- 方法原型
span:set_status(status, description)

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    span:set_status("ok", "get object successed")

    local err_msg = span:set_status(status, description)
    local err_msg then
        log:error("%s", err_msg)
    end
end

req:

  • status: 必选参数,string类型,span状态,仅可设置description. e.g. "ok";
  • description: 必选参数,string类型,状态补充描述. e.g. "get object successed"

rsp:

  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

get_context 获取当前span的上下文信息

获取当前span的上下文信息,用于后续span进行linkchild span创建。

lua
-- 方法原型
local context = span:get_context()

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    local context = span:get_context()

    local context, err_msg = span:get_context()
    local err_msg then
        log:error("%s", err_msg)
    end
end

rsp:

  • context: span的上下文信息,字典类型,组成字段为trace_id, span_id, trace_state, is_remoting, trace_flags, 业务不感知具体信息,仅用来传递,禁止修改context内容,否则会导致下级span链接失败;
  • msg: string类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。

is_recording 检查当前span是否可操作

采样策略制定、发生错误等都会导致创建span失败而返回no operation span,当业务需要记录的内容需要通过耗时或资源占用等方式获取,可以通过该方法进行判断是否需要收集记录信息。

lua
-- 方法原型
local is_recording = span:is_recording()

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    if span:is_recording() then
        span:add_event()
        span:set_status()
    end
end

rsp:

  • is_recording: bool类型,反应当前span是否可操作,发生错误时则返回false

finish 结束当前span

结束当前span,自动触发存储或上报等操作。

lua
-- 方法原型
span:finish()

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)

    span:add_event()
    span:set_status()

    span:finish()
end

pcall 执行方法并捕获执行状态并记录到span中进行上报

类似lua的pcall方法,保护调用之外,同时捕获函数内部的执行结果,刷新span状态为"ok"或"error"并上报, 并且会自动结束此次跟踪

lua
-- 方法原型
span:pcall(cb, ...)

-- 使用示例
function get_object()
    local span = trace.start_span(name, attribute)
    local function record(time, msg)
        if type(msg) ~= "string" then
            error("msg must be string")
        end
        print(time, msg)
    end

    local ok, ret = span:pcall(record, time, msg)
end

req:

  • function: 必选参数,pcall进行保护调用的函数. e.g. function();
  • param: 可选不定参数,保护调用函数的参数

rsp:

  • status: bool类型,表示函数是否成功执行(true表示成功,false表示失败)。
  • result: 函数的返回值(如果成功)或错误信息(如果失败)

指标

本模块用于metrics相关能力接口的Lua层隔离,以实现Lua层、封装层、开源引入层隔离,Lua层与封装层之间通过弱引用隔离,在无法require到封装库时,Lua层提供空对象空接口保护业务不受影响

核心概念简述

  • MeterProvider:整个 Metrics API 的入口点,负责创建和管理所有 Meter 实例。
  • Meter:由 MeterProvider 创建,负责生成具体的指标工具Instrument。根据业务需要,通过CreateXxxInstrument()创建不同类型。
  • Instrument:由 Meter 创建,直接负责采集和上报具体的测量数据。

层级结构示例:

plaintext
+-- MeterProvider()
    |
    +-- Meter(name='test1', version='1.0.0', schema url='https://test//test')
    |   |
    |   +-- Instrument<Counter>(name='counter_test', description='test counter', unit='kb')
    |   |
    |   +-- instrument...
    |
    +-- Meter(name='test2', version='1.1.0', schema url='https://test//test')
        |
        +-- Instrument<ObservableCounter>(name='observable_counter_test', description='test observable counter', unit='kb')
        |
        +-- Instruments...

meter创建

metermetrics能力构建中最初的一环,业务需要持有meter根据业务创建不同类型的instrument来记录数据。组件通过调用get_meter()来创建meter

lua
-- 方法原型
local meter = metrics.get_tracer(name, version, schema_url)
 
-- 使用示例
local metrics = require 'telemetry.metrics'
local meter_custom = metrics.get_meter(name)

req:

  • name: 必选参数, string类型, meter名称;
  • version: 可选参数, 版本号;
  • schema_url: 可选参数, 关联的语义约定的URL。

instrument创建

instrument是负责采集和上报具体的测量数据的载体,业务根据需要选择创建不同类型的instrument

NOTE

仪器命名呈现在最终可视化系统中,直接体现了数据上报的易读性,需要着重审视命名合理性。

lua
-- 方法原型
meter:create_counter(name, description, unit)
meter:create_updowncounter(name, description, unit)
meter:create_observable_counter(name, description, unit)
meter:create_observable_updowncounter(name, description, unit)
meter:create_observable_gauge(name, description, unit)
 
-- 使用示例
local counter = meter:create_counter("counter_data", "count some data for test", "kb")
  • create_counter:创建一个单调递增的计数器counter;
  • create_updowncounter:创建一个可递增递减的计数器counter;
  • create_observable_counter:创建一个异步的单调递增的计数器observable_counter;
  • create_observable_updowncounter:创建一个异步的可递增递减的计数器observable_updowncounter;
  • create_observable_gauge:创建一个异步的瞬时仪表observable_gauge。

req:

  • name: 必选参数, string类型, instrument名称;
  • description: 可选参数, instrument的相关描述信息;
  • unit: 可选参数, 采集数据的单位,e.g. "kb"

instrument方法调用

同步仪器

同步仪器包括counterupdowncounter,通过显式调用直接记录指标。

lua
-- 创建 Meter
local meter = metrics.get_meter()

-- 创建 Counter
local counter = meter:create_counter("my_counter")

-- 增加Counter计数器的值
counter:add(10)
lua
-- 创建 Meter
local meter = metrics.get_meter()

-- 创建 UpDownCounter
local updowncounter = meter:create_updowncounter("my_updowncounter")

-- 增加或减少UpDownCounter的值
updowncounter:add(5)    -- 增加
updowncounter:add(-3)   -- 减少

-- 使用 Attribute 给指标添加维度示例
flash_io_counter:add(data_size, {file_type="log", mc_name="xx"})
flash_io_counter:add(data_size, {file_type="persisitence", mc_name="xx"})

在实际业务的度量采样中,添加标签可以从多个维度去分析同一个指标,可视化系统支持通过标签筛选和聚合指标。例如:

  • otelcol_flash_io_total{file_type = "log"}可查看指标在写入类型为日志的flash写入量数值变化;
  • sum(otelcol_flash_io_total{file_type = "persisitence"})可查看指标在写入类型为持久化的flash写入总量的数值变化。

异步仪器

异步仪器包括observable_counterobservable_updowncounterobservable_gauge,也称为观察仪器,则是通过注册回调函数来采集数据。这些回调函数会在收集指标时被调用,这些数据需要定期轮询获取。

lua
-- 创建 Meter
local meter = metrics.get_meter()

-- 创建ObservableCounter
local observable_counter = meter:create_observable_counter("my_observable_counter")

-- 注册回调函数
observable_counter:add_callback(function()
    return 30
end)

日志

本模块用于logs相关能力接口的Lua层隔离,以实现Lua层、封装层、开源引入层隔离,Lua层与封装层之间通过弱引用隔离,在无法require到封装库时,Lua层提供空对象空接口保护业务不受影响

日志接口与调试日志接口已归一,内部通过键值对列表和参数列表方式区分上报日志和调试日志

日志记录

接口功能
log:debug(body, attrs)上报debug级别日志
log:info(body, attrs)上报info级别日志
log:notice(body, attrs)上报notice级别日志
log:warn(body, attrs)上报warn级别日志
log:error(body, attrs)上报error级别日志
lua
-- 记录debug日志
log:debug('my debug log')

-- 记录debug日志,和相关属性信息
log:debug('my debug log', {system_id=1, mc_name="xx"})

-- 其他级别日志使用方法同上