Metric Lua API
模块:
local mc = require("mc")→mc.metric
概述
mc.metric 把 mc::engine 的同步度量句柄暴露给 Lua:按 catalog 创建 Counter / UpDownCounter / Gauge / Histogram,add/record 写入进程 SHM。不提供独立 collect;诊断用 debug_dump。
主要特性
- 与 C++
mc::engine::create_*/apply_metric_config同一套单例与 catalog - 无效句柄仍是 userdata,
is_valid()为 false,打点返回 false Enabled=false或未激活时add/record返回 true(空操作)- 属性可用 Lua table 或
mc.dict
基本用法
local mc = require("mc")
mc.metric.apply_config("Enabled", true)
mc.metric.apply_config("ServiceName", "bmc.app")
local c = mc.metric.create_counter("bmc.app.requests", "http requests", "1")
assert(c:is_valid())
assert(c:add(1, { method = "GET" }))
assert(not c:add(-1, { method = "GET" }))
local g = mc.metric.create_gauge("bmc.app.temp", "temp", "C")
assert(g:record(36.5))
local snap = mc.metric.debug_dump()
assert(type(snap) == "table")
assert(snap.magic == 0x4D434D53)
local mc = require("mc")
mc.metric.apply_config("Enabled", true)
mc.metric.apply_config("ActivatedMetrics", { "bmc.app.temp" })
local c = mc.metric.create_counter("bmc.app.requests")
-- 句柄仍 valid,但未激活:add 为 true 且不改槽
assert(c:add(1, { method = "GET" }))
API 详细说明
create_counter / create_updown_counter / create_gauge / create_histogram
h = mc.metric.create_counter(name[, description[, unit]])
h = mc.metric.create_updown_counter(name[, description[, unit]])
h = mc.metric.create_gauge(name[, description[, unit]])
h = mc.metric.create_histogram(name[, description[, unit]])
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| name | string | catalog 中的仪器名 |
| description | string | 可选;非空时须与 catalog 一致 |
| unit | string | 可选;非空时须与 catalog 一致 |
返回值: userdata 句柄(永不 nil)
异常: name 非 string 时 Lua 参数错误
创建走 mc::engine::create_*:lazy 加载默认 catalog。未登记、kind 不符、Observable 已跳过 → is_valid()==false。
apply_config
ok = mc.metric.apply_config(key, value)
参数:
| 参数 | 类型 | 说明 |
|---|---|---|
| key | string | Enabled / ServiceName / ActivatedMetrics / ExportIntervalSeconds |
| value | bool / string / number / string 数组 | 与 C++ apply_metric_config 相同 |
返回值: 参数形态合法为 true,否则 false(不抛)
异常: 无(类型不对返回 false)
mc.metric.apply_config("Enabled", true)
mc.metric.apply_config("ExportIntervalSeconds", 40)
mc.metric.apply_config("ActivatedMetrics", { "bmc.app.temp" })
debug_dump
snap = mc.metric.debug_dump()
返回值: SHM 已 map 且 magic 已发布时为 table,否则 nil
异常: 不抛异常
table 结构:
| 字段 | 说明 |
|---|---|
magic |
0x4D434D53 |
meters |
数组 |
meters[i].name |
meter 名 |
meters[i].overflow_drops |
溢出丢弃 |
meters[i].series |
序列数组 |
series.name / kind / attrs |
仪器名、种类、属性表 |
series.value |
Counter / UpDown |
series.gauge |
Gauge |
series.count / sum / min / max / buckets |
Histogram;buckets 为 1-based 数组 |
同名同属性可能有多条(段未 unlink 时旧槽仍在)。断言当前进程写入值时取 最后一条。
POSIX 文件:/dev/shm/mc_metrics。
句柄方法
counter / updown_counter :add
ok = handle:add(value[, attrs])
| 参数 | 类型 | 说明 |
|---|---|---|
| value | number | Counter 须 ≥0 的整数语义;UpDown 可为负 |
| attrs | table 或 dict | 可选 |
返回值: boolean。无效句柄或校验失败 false;开关关闭或未激活 true。
gauge / histogram :record
ok = handle:record(value[, attrs])
NaN / Inf → false。Histogram 桶只来自 catalog。
:is_valid
ok = handle:is_valid()
最佳实践
✅ 正例
local c = mc.metric.create_counter("bmc.app.requests")
if c:is_valid() then
c:add(1, mc.dict({ method = "GET" }))
end
-- 关 Enabled 后仍 add,不崩溃
mc.metric.apply_config("Enabled", false)
assert(c:add(1, { method = "GET" }))
❌ 反例
-- 不要假设 io.open("/dev/shm/mc.metrics")
local f = io.open("/dev/shm/mc.metrics", "rb")
-- dump 取第一条可能是上次进程留下的槽
local snap = mc.metric.debug_dump()
local first = snap.meters[1].series[1]
assert(first.gauge == 36.5) -- 可能是旧值 40