Apache SkyWalking Meter Analysis Language实战:自定义指标计算
你是否还在为分布式系统中复杂指标的计算与分析而烦恼?面对海量监控数据,如何快速提取关键性能指标、实现自定义告警阈值、构建业务专属监控视图?Apache SkyWalking的Meter Analysis Language(MAL,指标分析语言)为这些问题提供了一站式解决方案。本文将从实战角度,全面解析MAL的语法特性、使用场景和最佳实践,帮助你掌握自定义指标计算的核心技能。读完本文后,你将能够..
Apache SkyWalking Meter Analysis Language实战:自定义指标计算
引言:MAL解决的核心痛点
你是否还在为分布式系统中复杂指标的计算与分析而烦恼?面对海量监控数据,如何快速提取关键性能指标、实现自定义告警阈值、构建业务专属监控视图?Apache SkyWalking的Meter Analysis Language(MAL,指标分析语言)为这些问题提供了一站式解决方案。本文将从实战角度,全面解析MAL的语法特性、使用场景和最佳实践,帮助你掌握自定义指标计算的核心技能。
读完本文后,你将能够:
- 理解MAL在SkyWalking指标体系中的定位与价值
- 熟练运用MAL进行标签过滤、转换与聚合操作
- 掌握时间序列指标的高级计算方法(增长率、百分位数等)
- 实现多维度指标下钻分析与业务关联
- 构建从原始数据到存储的完整指标处理流水线
一、MAL核心概念与数据模型
1.1 MAL定位与架构
MAL是SkyWalking指标系统提供的函数式分析语言,运行于OAP服务器的流式处理引擎中。其核心价值在于将原始监控数据(如Prometheus指标、Agent采集数据)转换为业务可理解的聚合指标,并支撑SkyWalking的存储、查询与告警功能。
关键特性:
- 流式处理:实时分析指标数据流
- 函数式编程:支持链式操作与高阶函数
- 多维度分析:基于标签的灵活维度管理
- 与SkyWalking存储无缝集成:自动适配Elasticsearch、BanyanDB等存储后端
1.2 数据类型系统
MAL定义两种核心数据类型,构成指标计算的基础:
| 数据类型 | 描述 | 示例 |
|---|---|---|
| Sample Family(样本族) | 名称相同的一组指标样本集合,每个样本包含标签集和数值 | http_requests_total{service="order",status="200"} 1560 |
| Scalar(标量) | 单个数值(整数或浮点数) | 100、3.14 |
样本族结构解析:
instance_trace_count{region="us-west",az="az-1"} 100
- 指标名称:
instance_trace_count - 标签集:
region="us-west"、az="az-1" - 指标值:
100
二、MAL基础操作:标签处理与过滤
2.1 标签过滤操作
MAL提供四类标签过滤函数,用于从样本族中筛选符合条件的样本:
| 函数 | 作用 | 示例 |
|---|---|---|
| tagEqual(key, value) | 精确匹配标签值 | http_requests.tagEqual("status","200") |
| tagNotEqual(key, value) | 排除指定标签值 | http_requests.tagNotEqual("status","500") |
| tagMatch(key, regex) | 正则匹配标签值 | http_requests.tagMatch("service","order.*") |
| tagNotMatch(key, regex) | 排除正则匹配的标签值 | http_requests.tagNotMatch("service","test.*") |
组合过滤示例:
# 筛选us-west区域且非5xx状态码的请求
http_requests_total
.tagMatch("region","us-west|us-east")
.tagNotMatch("status","5..")
.tagEqual("protocol","http")
2.2 标签转换与增强
2.2.1 基础标签操作
MAL支持对标签进行添加、删除和重命名操作,核心函数为tag():
# 添加环境标签
http_requests_total.tag({tags -> tags + ["env":"production"]})
# 删除敏感标签
http_requests_total.tag({tags -> tags - "user_id"})
# 重命名标签
http_requests_total.tag({tags -> tags.rename("svc","service")})
2.2.2 K8s元数据集成
针对Kubernetes环境,MAL提供retagByK8sMeta()函数,实现基于K8s资源元数据的标签增强:
# 根据Pod名称自动关联Service标签
container_cpu_usage_seconds_total
.retagByK8sMeta(
"service",
K8sRetagType.Pod2Service,
"pod",
"namespace"
)
转换效果:
# 原始指标
container_cpu_usage_seconds_total{namespace="default", pod="order-service-5dc4865748-mbczh"} 2.5
# 转换后指标
container_cpu_usage_seconds_total{
namespace="default",
pod="order-service-5dc4865748-mbczh",
service="order-service.default"
} 2.5
三、指标计算核心操作
3.1 数值过滤与算术运算
3.1.1 数值过滤函数
MAL提供丰富的数值过滤函数,用于筛选特定范围内的指标样本:
| 函数 | 作用 | 示例 |
|---|---|---|
| valueGreater(n) | 筛选值大于n的样本 | latency.valueGreater(500) |
| valueLess(n) | 筛选值小于n的样本 | latency.valueLess(100) |
| valueGreaterEqual(n) | 筛选值大于等于n的样本 | errors.valueGreaterEqual(10) |
| valueLessEqual(n) | 筛选值小于等于n的样本 | queue_size.valueLessEqual(1000) |
3.1.2 算术运算符
MAL支持样本族与标量、样本族之间的算术运算:
| 运算符 | 作用 | 示例 |
|---|---|---|
| + | 加法 | request_count + 100 |
| - | 减法 | success_count - failure_count |
| * | 乘法 | request_count * 0.8 |
| / | 除法 | success_count / request_count |
实用示例:计算请求成功率
# 成功率 = 成功请求数 / 总请求数
success_count / request_count * 100
3.2 聚合操作
MAL提供多种聚合函数,支持基于标签维度的指标聚合:
| 函数 | 作用 | 示例 |
|---|---|---|
| sum(by=[tags]) | 求和聚合 | request_count.sum(by=["service","region"]) |
| avg(by=[tags]) | 平均值聚合 | latency.avg(by=["service"]) |
| min(by=[tags]) | 最小值聚合 | disk_free.min(by=["node"]) |
| max(by=[tags]) | 最大值聚合 | cpu_usage.max(by=["service"]) |
| count(by=[tags]) | 样本计数 | instance_count.count(by=["region"]) |
多层聚合示例:
# 先按服务聚合,再按区域聚合
request_count
.sum(by=["service","region"])
.avg(by=["region"])
注意:MAL聚合操作仅对单次批量样本生效。若需跨实例/节点聚合,应结合MQE(Metrics Query Expression)的
AggregateLabels操作使用。
三、时间序列指标高级计算
3.1 时间窗口函数
MAL提供三类核心时间窗口函数,用于计算指标在特定时间范围内的变化:
| 函数 | 作用 | 示例 |
|---|---|---|
| increase(duration) | 计算时间窗口内的增长总量 | http_requests.increase("PT5M") |
| rate(duration) | 计算每秒平均增长率 | http_requests.rate("PT5M") |
| irate() | 计算瞬时增长率 | http_requests.irate() |
实用场景:
# 5分钟请求增长率
http_requests_total.rate("PT5M")
# 10分钟错误增长总量
http_errors_total.increase("PT10M")
3.2 直方图计算
针对延迟、响应时间等分布型指标,MAL提供直方图专用处理函数:
# 将Prometheus直方图转换为SkyWalking直方图
prometheus_http_request_duration_seconds_bucket
.histogram("le")
# 计算P95延迟
prometheus_http_request_duration_seconds_bucket
.histogram("le")
.histogram_percentile(95)
直方图转换原理:
3.3 降采样策略
MAL通过downsampling()函数定义指标的降采样方式,控制不同时间粒度(分钟/小时/天)的数据聚合行为:
# 保留最新值
last_server_state_sync_time_in_seconds
.tagEqual("production", "catalog")
.downsampling(LATEST)
# 求和降采样
daily_transaction_amount
.downsampling(SUM)
支持的降采样类型包括:AVG(默认)、SUM、LATEST、SUM_PER_MIN、MIN、MAX等。
四、指标分层与业务关联
4.1 指标层级定义
MAL提供层级函数,将原始指标与SkyWalking的服务层级模型关联:
| 函数 | 作用 | 示例 |
|---|---|---|
| service(svc_labels, Layer) | 定义服务级指标 | .service(["service"], Layer.GENERAL) |
| instance(svc_labels, ins_labels, Layer) | 定义实例级指标 | .instance(["service"], ["instance"], Layer.JVM) |
| endpoint(svc_labels, ep_labels) | 定义端点级指标 | .endpoint(["service"], ["endpoint"]) |
服务层级指标定义示例:
# 定义订单服务的JVM实例级指标
jvm_memory_used
.tagMatch("service","order-service")
.instance(
["service"],
["instance"],
Layer.JVM,
{ tags -> ["pod": tags.pod, "namespace": tags.namespace] }
)
4.2 服务关系指标
对于分布式追踪场景,MAL提供serviceRelation()函数定义服务间调用指标:
# 定义服务调用关系指标
service_call_latency
.serviceRelation(
DetectPoint.SERVER,
["source_service"],
["dest_service"],
Layer.GRPC
)
服务依赖关系可视化:
五、MAL配置与实战案例
5.1 MAL配置文件结构
MAL规则通过YAML配置文件定义,放置于$CLASSPATH/otel-rules或meter-analyzer-config目录:
# 初始化表达式
initExp: "import static org.apache.skywalking.oap.server.core.analysis.Layer.*"
# 指标过滤条件
filter: '{ tags -> tags.job_name == "vm-monitoring" }'
# 表达式前缀
expPrefix: "metrics."
# 指标规则
metricsRules:
- name: "service_request_rate"
exp: "http_requests_total.rate('PT5M').service(['service'], GENERAL)"
- name: "instance_cpu_usage"
exp: "container_cpu_usage_seconds_total.sum(by=['instance']).instance(['service'], ['instance'], CONTAINER)"
5.2 实用案例:电商订单系统监控
案例1:订单成功率监控
metricsRules:
- name: "order_success_rate"
exp: |
# 订单成功率 = 成功订单数 / 总订单数
(order_success_count / order_total_count * 100)
.tagMatch("status","completed")
.service(["service"], Layer.SPRING_CLOUD)
.downsampling(AVG)
案例2:支付延迟P99监控
metricsRules:
- name: "payment_latency_p99"
exp: |
# 支付延迟P99计算
payment_latency_bucket
.histogram("le")
.histogram_percentile(99)
.instance(["service"], ["instance"], Layer.SPRING_CLOUD)
.downsampling(LATEST)
案例3:异常订单告警指标
metricsRules:
- name: "abnormal_order_rate"
exp: |
# 异常订单率 = (取消订单 + 超时订单) / 总订单数
(order_canceled_count + order_timeout_count) / order_total_count
.tagMatch("service","order-service")
.service(["service"], Layer.SPRING_CLOUD)
.downsampling(MAX)
六、最佳实践与性能优化
6.1 MAL性能优化技巧
-
过滤先行:在计算前先过滤不必要的样本
# 优化前 http_requests.sum(by=["service"]).tagEqual("env","prod") # 优化后 http_requests.tagEqual("env","prod").sum(by=["service"]) -
减少标签基数:避免在高基数标签上聚合
# 不推荐:user_id是高基数标签 http_requests.sum(by=["user_id"]) -
合理设置时间窗口:根据指标特性选择合适窗口大小
- 高频指标(如QPS):使用较小窗口(1-5分钟)
- 低频指标(如订单量):使用较大窗口(10-30分钟)
6.2 常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 指标计算结果为NaN | 检查是否存在除以零的情况,使用tag()函数过滤无效值 |
| K8s元数据关联失败 | 确认OAP服务器有K8s API Server访问权限 |
| 直方图转换异常 | 验证le标签是否符合Prometheus直方图规范 |
| 聚合结果与预期不符 | 确认聚合维度与指标基数匹配,避免跨批次聚合 |
七、总结与进阶学习
MAL作为SkyWalking指标体系的核心组件,提供了从原始数据到业务指标的完整处理能力。通过本文介绍的标签操作、聚合计算、时间窗口分析等功能,你可以构建灵活强大的自定义监控指标。
进阶学习资源:
- SkyWalking官方文档:Meter Analysis Language
- OAP自监控配置:otel-rules/oap.yaml
- SkyWalking MQE文档:Metrics Query Expression
下期预告:《Apache SkyWalking MQE实战:多维度指标查询与可视化》
通过MAL与MQE的组合使用,你将能够构建从指标采集、计算到可视化的全链路监控解决方案,为分布式系统的可观测性提供强大支撑。立即动手实践,开启SkyWalking自定义指标之旅吧!
更多推荐

所有评论(0)