Apache SkyWalking Meter Analysis Language实战:自定义指标计算

【免费下载链接】skywalking APM, Application Performance Monitoring System 【免费下载链接】skywalking 项目地址: https://gitcode.com/gh_mirrors/sky/skywalking

引言:MAL解决的核心痛点

你是否还在为分布式系统中复杂指标的计算与分析而烦恼?面对海量监控数据,如何快速提取关键性能指标、实现自定义告警阈值、构建业务专属监控视图?Apache SkyWalking的Meter Analysis Language(MAL,指标分析语言)为这些问题提供了一站式解决方案。本文将从实战角度,全面解析MAL的语法特性、使用场景和最佳实践,帮助你掌握自定义指标计算的核心技能。

读完本文后,你将能够:

  • 理解MAL在SkyWalking指标体系中的定位与价值
  • 熟练运用MAL进行标签过滤、转换与聚合操作
  • 掌握时间序列指标的高级计算方法(增长率、百分位数等)
  • 实现多维度指标下钻分析与业务关联
  • 构建从原始数据到存储的完整指标处理流水线

一、MAL核心概念与数据模型

1.1 MAL定位与架构

MAL是SkyWalking指标系统提供的函数式分析语言,运行于OAP服务器的流式处理引擎中。其核心价值在于将原始监控数据(如Prometheus指标、Agent采集数据)转换为业务可理解的聚合指标,并支撑SkyWalking的存储、查询与告警功能。

mermaid

关键特性

  • 流式处理:实时分析指标数据流
  • 函数式编程:支持链式操作与高阶函数
  • 多维度分析:基于标签的灵活维度管理
  • 与SkyWalking存储无缝集成:自动适配Elasticsearch、BanyanDB等存储后端

1.2 数据类型系统

MAL定义两种核心数据类型,构成指标计算的基础:

数据类型 描述 示例
Sample Family(样本族) 名称相同的一组指标样本集合,每个样本包含标签集和数值 http_requests_total{service="order",status="200"} 1560
Scalar(标量) 单个数值(整数或浮点数) 1003.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)

直方图转换原理mermaid

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
  )

服务依赖关系可视化mermaid

五、MAL配置与实战案例

5.1 MAL配置文件结构

MAL规则通过YAML配置文件定义,放置于$CLASSPATH/otel-rulesmeter-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性能优化技巧

  1. 过滤先行:在计算前先过滤不必要的样本

    # 优化前
    http_requests.sum(by=["service"]).tagEqual("env","prod")
    
    # 优化后
    http_requests.tagEqual("env","prod").sum(by=["service"])
    
  2. 减少标签基数:避免在高基数标签上聚合

    # 不推荐:user_id是高基数标签
    http_requests.sum(by=["user_id"])
    
  3. 合理设置时间窗口:根据指标特性选择合适窗口大小

    • 高频指标(如QPS):使用较小窗口(1-5分钟)
    • 低频指标(如订单量):使用较大窗口(10-30分钟)

6.2 常见问题与解决方案

问题 解决方案
指标计算结果为NaN 检查是否存在除以零的情况,使用tag()函数过滤无效值
K8s元数据关联失败 确认OAP服务器有K8s API Server访问权限
直方图转换异常 验证le标签是否符合Prometheus直方图规范
聚合结果与预期不符 确认聚合维度与指标基数匹配,避免跨批次聚合

七、总结与进阶学习

MAL作为SkyWalking指标体系的核心组件,提供了从原始数据到业务指标的完整处理能力。通过本文介绍的标签操作、聚合计算、时间窗口分析等功能,你可以构建灵活强大的自定义监控指标。

进阶学习资源

  1. SkyWalking官方文档:Meter Analysis Language
  2. OAP自监控配置:otel-rules/oap.yaml
  3. SkyWalking MQE文档:Metrics Query Expression

下期预告:《Apache SkyWalking MQE实战:多维度指标查询与可视化》

通过MAL与MQE的组合使用,你将能够构建从指标采集、计算到可视化的全链路监控解决方案,为分布式系统的可观测性提供强大支撑。立即动手实践,开启SkyWalking自定义指标之旅吧!

【免费下载链接】skywalking APM, Application Performance Monitoring System 【免费下载链接】skywalking 项目地址: https://gitcode.com/gh_mirrors/sky/skywalking

Logo

更多推荐