可观测是基于openTelemetry规范构建的可视化能力,主要围绕系统中的可观测数据(包括指标、跟踪和日志),提供采集、上报以及与多种可视化工具集成的能力,帮助用户更好的监控系统状态、预测运行趋势、分析和定位系统故障。
背景介绍
跟踪(Traces)
跟踪是一组事件,这些事件是由单个逻辑操作触发的,并通过应用程序的各个组件处理后最终整合在一起。跟踪可能包含跨越进程、网络和安全边界的事件,因此也被称为分布式跟踪,当有人按下按钮在网站上启动一个操作时,就可能会启动分布式跟踪。 具体来说,跟踪可以被认为是跨度(Span)的有向无环图 (DAG),其中跨度之间的边定义为父子关系。例如,以下是一个由6个跨度组成的跟踪示例:
[Span A] ←←←(the root span)
|
+------+------+
| |
[Span B] [Span C] ←←←(Span C is a `child` of Span A)
| |
[Span D] +---+-------+
| |
[Span E] [Span F]
使用时间轴来显示跟踪轨迹会更容易理解,如下图所示:
––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–––––––|–> time
[Span A···················································]
[Span B··············································]
[Span D··········································]
[Span C········································]
[Span E·······] [Span F··]
指标(Metrics)
指标是是对系统行为、性能或状态的量化测量,可以是任何可测量的数值,例如CPU使用率、内存占用率、请求延迟、错误率等。记录测量值主要涉及计量仪(Meter)、仪表(Instrument)和测量值(Measurement):
- 计量器(Meter):主要负责创建和管理仪表(Instrument)。
- 仪表(Instrument):具有名称、类型、描述和单位等标识,主要用于捕捉和记录测量值。
- 测量值(Measurement):单次记录的原始值,包含键值对属性标签,用于标记和区分不同场景下的测量值。
+------------------+
| 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 实现日志-追踪关联 核心组件和数据流向如下
+----------------------------------------------------------------+
| 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) | | |
| | +-----------------+ | |
| +----------+-----------+ |
+----------------------------------------------------------------+
数据模型
跟踪
跟踪的数据模型
┌───────────────────────────────┐
│ 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 默认值。表示跨度代表应用程序内的内部操作,而不是具有远程父级或子级的操作。
指标
指标的数据模型
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。
日志
日志的数据模型
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。
可观测架构
可观测数据流图
- 应用组件通过应用框架基于openTelemetry SDK封装的跟踪、指标、日志接口采集应用可观测数据;
- 应用框架通过可观测组件openTelemetry SDK采样器、处理器和导出器处理可观测数据,并上报到可观测组件fluent-bit服务端;
- 可观测组件fluent-bit服务的根据可观测配置,转发和上报可观测数据到openUBMC外收集器及可视化平台;
应用接口
跟踪
本模块用于Trace相关能力接口的lua层隔离,以实现Lua层、封装层、开源引入层,Lua层与封装层、开源引入层隔离,Lua层与封装层之间通过弱引用隔离,在无法require
到封装库时,Lua层提供空对象空接口保护业务不受影响。
tracer
创建
tracer
是Trace能力构建中最初一环,业务需要持有tracer
用于创建span
,利用span
的记录存储上报能力构建跨服务跟踪链路,目前组件初始化过程中自动以组件名作为tracer name
创建tracer
并存储,组件后续调用get_tracer()
将直接返回tracer
,组件也可以通过传入参数name
新建tracer
。
-- 方法原型
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
整合为一条完整的跟踪链路。
-- 方法原型
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
,值只支持string
、bool
、int
、double
类型,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
数据导出,可用于链路标记,数据筛选等。
-- 方法原型
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
: 必选参数,支持string
、bool
、int
、double
类型,对应属性名的属性值。
rsp
:
msg
:string
类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。
add_link
添加关联span
在span
之间建立非父子关系的关联,一般为异步场景使用。
-- 方法原型
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
,值只支持string
、bool
、int
、double
类型,span
的属性,添加links
时的补充属性,由用户根据需要使用,后续跟随span
数据作为links
字段的额外字段导出. e.g.{"level": "notice", "opcode": 1}
。
rsp
:
msg
:string
类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。
add_event
添加span事件
在span中记录事件,类似日志记录操作,是用于可视化的主要部分。
-- 方法原型
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
,值只支持string
、bool
、int
、double
类型,添加event
时的补充属性,添加event
时的补充属性,由用户根据需要使用,后续跟随span
数据作为event
字段的额外字段导出. e.g.{"level": "notice", "opcode": 1}
。
rsp
:
msg
:string
类型,错误信息,由业务选择是否接收,会返回失败的具体信息,若成功则不返回。
set_status
设置当前span
状态
设置当前span
状态,默认状态为unset
,支持unset
、ok
、error
三种状态设置,span
状态可用于尾部采样、可视化筛选等。
-- 方法原型
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
进行link
或child span
创建。
-- 方法原型
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
,当业务需要记录的内容需要通过耗时或资源占用等方式获取,可以通过该方法进行判断是否需要收集记录信息。
-- 方法原型
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
,自动触发存储或上报等操作。
-- 方法原型
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"并上报, 并且会自动结束此次跟踪
-- 方法原型
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
创建,直接负责采集和上报具体的测量数据。
层级结构示例:
+-- 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
创建
meter
是metrics
能力构建中最初的一环,业务需要持有meter
根据业务创建不同类型的instrument
来记录数据。组件通过调用get_meter()
来创建meter
。
-- 方法原型
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
仪器命名呈现在最终可视化系统中,直接体现了数据上报的易读性,需要着重审视命名合理性。
-- 方法原型
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
方法调用
同步仪器
同步仪器包括counter
和updowncounter
,通过显式调用直接记录指标。
-- 创建 Meter
local meter = metrics.get_meter()
-- 创建 Counter
local counter = meter:create_counter("my_counter")
-- 增加Counter计数器的值
counter:add(10)
-- 创建 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_counter
,observable_updowncounter
,observable_gauge
,也称为观察仪器,则是通过注册回调函数来采集数据。这些回调函数会在收集指标时被调用,这些数据需要定期轮询获取。
-- 创建 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级别日志 |
-- 记录debug日志
log:debug('my debug log')
-- 记录debug日志,和相关属性信息
log:debug('my debug log', {system_id=1, mc_name="xx"})
-- 其他级别日志使用方法同上