Posted in

Golang统计指标命名规范(Prometheus官方推荐+Uber内部标准双校验):违反这5条,你的指标将被SRE团队拉黑

第一章:Golang统计指标命名规范总览

在Go生态中,可观测性(Observability)高度依赖结构化、语义清晰的指标命名。Prometheus作为主流监控系统,其指标命名约定已成为事实标准,Golang项目(尤其是使用prometheus/client_golang库的项目)必须严格遵循这一规范,以确保指标可读、可聚合、可告警。

核心命名原则

指标名称应采用 namespace_subsystem_name 的三段式小写蛇形命名法:

  • namespace 表示应用或组织范围(如 http、grpc、redis);
  • subsystem 表示模块或组件(如 client、server、cache);
  • name 描述具体度量含义(如 requests_total、duration_seconds)。
    避免使用大写字母、空格、特殊符号(-、. 等),仅允许 _ 作为分隔符。

常见后缀语义约定

后缀 类型 含义 示例
_total Counter 单调递增计数器 http_requests_total
_seconds Histogram/Summary 观察值(单位为秒) http_request_duration_seconds
_bytes Gauge/Histogram 字节数量 memory_usage_bytes
_count / _sum Summary 分位数统计的组成部分 http_request_size_bytes_count

实际代码示例

import "github.com/prometheus/client_golang/prometheus"

// ✅ 正确:符合命名规范,明确区分维度与语义
httpRequestsTotal := prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Namespace: "http",       // 统一命名空间
        Subsystem: "server",     // 子系统标识
        Name:      "requests_total", // 核心指标名 + _total 后缀
        Help:      "Total number of HTTP requests.",
    },
    []string{"method", "status_code"}, // 标签维度,非嵌入名称中
)
prometheus.MustRegister(httpRequestsTotal)

// ❌ 错误示例(应避免):
// "HTTPRequests"(含大写)、"http-requests"(含连字符)、"http_server_reqs"(缩写模糊)

命名需兼顾机器解析与人工理解:标签(labels)承载动态维度(如 method="GET"),而指标名本身应稳定、无歧义,并支持跨服务统一查询(如 rate(http_requests_total[5m]))。

第二章:Prometheus官方推荐的五大命名铁律

2.1 指标名称必须以应用前缀开头并体现语义层级(理论解析+Go metrics包实操校验)

指标命名不是随意拼接,而是服务可观测性的第一道契约。app_http_request_duration_seconds 比 http_duration 更具可追溯性与上下文隔离能力。

为什么需要语义层级?

  • 前缀 app_ 标识业务归属,避免跨服务指标冲突
  • 层级结构 app_<domain>_<subsystem>_<metric>_<unit> 支持按维度聚合与过滤

Go metrics 实操校验

// 使用 prometheus/client_golang 注册规范指标
var httpRequestDur = prometheus.NewHistogramVec(
    prometheus.HistogramOpts{
        Namespace: "app",           // ← 强制前缀(非 subsystem)
        Subsystem: "http",          // ← 一级语义域
        Name:      "request_duration_seconds",
        Help:      "HTTP request latency in seconds",
        Buckets:   prometheus.ExponentialBuckets(0.01, 2, 10),
    },
    []string{"method", "code"},
)

Namespace: "app" 确保所有指标以 app_http_... 开头;Subsystem 补充领域粒度,最终完整名称为 app_http_request_duration_seconds。

组件 作用 示例值
Namespace 应用级隔离标识 app
Subsystem 功能模块划分 http, cache
Name 指标核心语义+单位后缀 request_duration_seconds
graph TD
    A[注册指标] --> B[namespace=app]
    B --> C[Subsystem=http]
    C --> D[Name=request_duration_seconds]
    D --> E[完整名称:app_http_request_duration_seconds]

2.2 使用下划线分隔单词,禁止驼峰与特殊字符(理论依据+go vet + promtool lint实战验证)

Prometheus 生态严格遵循 Metrics Naming Best Practices:指标名与标签名须采用 snake_case,禁用 camelCase、PascalCase 及 -、.、/ 等特殊字符。

为什么必须用下划线?

  • 语义清晰性:http_requests_total 比 httpRequestsTotal 更易被非 Go 开发者解析;
  • 工具链兼容性:promtool 和 go vet 的命名检查器均基于正则 ^[a-zA-Z_][a-zA-Z0-9_]*$ 验证。

实战验证示例

# promtool lint 检测非法命名
echo 'httpRequestsTotal{method="GET"} 1' | promtool check metrics
# 输出:ERROR: httpRequestsTotal: invalid metric name (must match ^[a-zA-Z_][a-zA-Z0-9_]*$)

该命令触发 promtool 内置的 metricNameRE 正则校验,拒绝任何含大写字母或无下划线的标识符。

常见违规与合规对照表

违规名称 合规修正 原因
apiResponseTime api_response_time 驼峰违反 snake_case
disk-util% disk_util_percent % 是非法字符
// go vet -vettool=github.com/prometheus/client_golang/tools/cmd/pvet
var (
    // ❌ 错误:驼峰 + 特殊字符
    HTTPRequestsTotal = promauto.NewCounter(prometheus.CounterOpts{
        Name: "HTTPRequestsTotal", // 被 pvet 拒绝
    })
    // ✅ 正确:全小写 + 下划线
    http_requests_total = promauto.NewCounter(prometheus.CounterOpts{
        Name: "http_requests_total", // 通过所有 lint
    })
)

pvet 工具在编译期扫描 prometheus.CounterOpts.Name 字段,强制执行命名规范,避免运行时指标注入失败。

2.3 类型后缀严格遵循_counter、_gauge、_histogram、_summary约定(Prometheus类型系统原理+Go client_go代码生成示例)

Prometheus 客户端通过指标名称后缀隐式声明其类型,这是服务端解析与存储的契约基础。_counter 表示单调递增计数器,_gauge 表示可增可减的瞬时值,_histogram 和 _summary 则分别对应分位数统计的两种实现机制。

类型后缀语义对照表

后缀 类型 是否支持 observe() 是否支持 inc() 典型用途
_counter Counter ❌ ✅ 请求总数、错误累计
_gauge Gauge ✅ ✅ 内存使用、并发请求数
_histogram Histogram ✅ ❌ 请求延迟(bucket 分布)
_summary Summary ✅ ❌ 请求延迟(滑动分位数)

Go client_golang 代码生成示例

// 正确:后缀与类型严格匹配
httpRequestsTotal := promauto.NewCounter(prometheus.CounterOpts{
    Name: "http_requests_total",        // ✅ 合法:_total 是 _counter 的等价后缀
    Help: "Total HTTP Requests",
})
httpRequestDuration := promauto.NewHistogram(prometheus.HistogramOpts{
    Name: "http_request_duration_seconds", // ✅ 必须含 _seconds + _histogram 语义(实际由 client 自动补全)
    Help: "HTTP request duration in seconds",
})

逻辑分析:promauto.NewCounter 内部校验 Name 字段——若未以 _total/_counter/_count 结尾,会 panic;NewHistogram 则要求单位后缀(如 _seconds)并自动注册 xxx_bucket、xxx_sum、xxx_count 子指标。此机制确保指标元数据在注册阶段即符合 Prometheus 类型系统规范。

2.4 标签(label)命名需小写+下划线,且禁止动态高基数标签(SRE告警案例复盘+Go runtime/metrics中标签注入反模式演示)

🔍 SRE告警风暴溯源

某次凌晨告警激增 3700+/分钟,根源是 Prometheus 指标 http_request_duration_seconds{path="/api/v1/user/{uid}",status="200"} 中 uid 作为 label 值——单日生成超 200 万唯一值,触发 TSDB 内存爆炸与查询卡顿。

⚠️ Go metrics 反模式代码

// ❌ 危险:动态高基数 label 注入
promhttp.NewServeMux().With(
    prometheus.WrapRegistererWith(
        prometheus.Labels{"user_id": r.URL.Query().Get("uid")}, // 动态、不可控、高基数!
        prometheus.DefaultRegisterer,
    ),
)

逻辑分析:user_id 来自 HTTP 查询参数,无白名单校验;每次请求注册新 label 组合,导致 metric family 膨胀,Go runtime 的 runtime/metrics 采集器亦会因 label 泛滥拖慢 readMetrics 调用。

✅ 正确实践清单

  • 标签名强制 snake_case:http_status_code ✅,HTTPStatusCode ❌
  • 高频维度降维:将 uid 移至 metric value 或 trace context,改用 user_type="premium" 等低基数 label
  • 静态 label 白名单校验(如正则 ^[a-z0-9_]+$)
维度 允许示例 禁止示例
标签名 request_method RequestMethod
标签值 post, v2_api POST, /user/123
graph TD
    A[HTTP 请求] --> B{提取 uid?}
    B -->|是| C[→ 高基数 label]
    B -->|否| D[→ 静态 label 如 api_version]
    C --> E[TSDB OOM / 查询超时]
    D --> F[稳定指标 cardinality < 100]

2.5 单一指标职责原则:禁止多语义聚合指标(Prometheus查询性能退化分析+Go自定义Collector拆分重构实践)

当 http_requests_total{method="GET",status="200",handler="/api/user"} 与 http_requests_total{method="POST",status="500",handler="/api/order"} 被强行聚合为同一指标名但混用业务维度时,Prometheus 查询引擎需遍历海量时间序列匹配 label 组合,导致 rate() 计算延迟飙升 300%+。

标签爆炸的根源

  • 单一指标承载 method × status × handler × region 四维正交组合 → 序列数呈指数增长
  • sum by (method) 查询被迫扫描数万 series,TSDB chunk 解压开销剧增

拆分后的 Collector 结构

// 拆分为语义清晰的独立指标
httpRequestsTotal := prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_requests_total", // 仅计数,无聚合语义
        Help: "Total HTTP requests",
    },
    []string{"method", "status"}, // 剥离 handler/region,交由关联指标或外部维度管理
)

逻辑分析:NewCounterVec 的 label 列表严格限定为业务行为核心语义(method/status),避免将部署拓扑(region)或路由路径(handler)混入指标名。参数 []string{"method","status"} 显式声明职责边界,使每个 series 具备可预测基数。

重构前 重构后
http_requests_total(7维 label) http_requests_total(2维) + http_route_requests_total(2维)
平均 series 数:12,480 各指标平均 series 数:
graph TD
    A[原始指标] -->|label 爆炸| B[Query OOM]
    C[拆分 Collector] -->|按语义解耦| D[series 基数↓72%]
    D --> E[rate() 延迟从 1.2s→380ms]

第三章:Uber内部标准对Go生态的增强约束

3.1 service_name与team标签强制注入机制(Uber Zanzibar架构映射+Go HTTP middleware自动打标实现)

在Zanzibar模型中,service_name与team是核心元数据维度,用于策略决策上下文隔离。我们通过Go HTTP middleware在请求入口统一注入,确保所有下游服务(如授权检查器、审计日志、指标采集)获得一致标签。

标签注入中间件实现

func TaggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        // 从服务注册中心或环境变量获取标识
        serviceName := os.Getenv("SERVICE_NAME")
        teamName := os.Getenv("TEAM_NAME")

        // 强制注入到context,不可被下游覆盖
        ctx := context.WithValue(r.Context(),
            keyServiceName{}, serviceName)
        ctx = context.WithValue(ctx,
            keyTeamName{}, teamName)

        // 同时写入OpenTelemetry span属性(兼容Zanzibar trace context)
        span := trace.SpanFromContext(r.Context())
        span.SetAttributes(
            attribute.String("service.name", serviceName),
            attribute.String("team", teamName),
        )

        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

逻辑分析:该中间件在请求生命周期早期执行,利用context.WithValue构造不可变标签链,并同步注入OpenTelemetry属性,使Zanzibar策略引擎可直接从trace context提取service_name和team作为关系元组(user:alice, service:payment, team:finance)的组成部分。

关键参数说明

参数 来源 用途
SERVICE_NAME Kubernetes Downward API / env 映射Zanzibar中的resource_type粒度
TEAM_NAME ConfigMap挂载 决定策略集归属与RBAC作用域

标签传播保障机制

  • ✅ 所有gRPC/HTTP客户端自动继承context标签
  • ✅ Prometheus指标自动添加service_name和team为label
  • ❌ 禁止业务代码调用context.WithValue覆盖原始标签(通过私有key类型keyServiceName{}实现类型安全)

3.2 指标生命周期管理:从初始化到注销的Go defer语义保障(Go sync.Once与runtime.SetFinalizer协同实践)

指标对象需严格遵循“创建→注册→使用→注销”闭环,避免内存泄漏与竞态访问。

初始化阶段:sync.Once 保证幂等安全

var initOnce sync.Once
func initMetric() *Metric {
    var m *Metric
    initOnce.Do(func() {
        m = &Metric{value: new(int64)}
        register(m) // 向监控系统注册
    })
    return m
}

sync.Once 确保 register() 仅执行一次;m 在首次调用后稳定返回,避免重复注册引发指标冲突。

注销阶段:defer + SetFinalizer 双保险

func NewTrackedMetric() *Metric {
    m := initMetric()
    runtime.SetFinalizer(m, func(obj interface{}) {
        if metric := obj.(*Metric); metric != nil {
            unregister(metric) // 异步兜底清理
        }
    })
    return m
}

defer 在函数退出时触发显式注销(主路径),SetFinalizer 作为 GC 前最后防线——二者协同覆盖正常退出与异常逃逸场景。

机制 触发时机 保障维度 局限性
defer 函数作用域结束 主动可控 依赖开发者显式编写
SetFinalizer GC 回收前 被动兜底 执行时机不确定、不可重入

graph TD A[NewTrackedMetric] –> B[initMetric via sync.Once] B –> C[register to collector] A –> D[SetFinalizer for GC cleanup] C –> E[Use in business logic] E –> F[defer unregister on exit] F –> G[Normal cleanup] D –> H[GC-triggered fallback]

3.3 错误指标统一采用_error_total后缀并绑定error_type标签(Uber Go error handling最佳实践+promauto.MustNewCounterVec集成方案)

统一错误指标命名规范

Prometheus 官方推荐将计数类错误指标统一以 _error_total 结尾,语义明确且与 *_total 命名惯例一致。结合 Uber 的 go.uber.org/zap + errors.Wrap 错误封装实践,可结构化提取错误类型。

Prometheus 指标定义与初始化

var (
    errCounter = promauto.MustNewCounterVec(
        prometheus.CounterOpts{
            Name: "service_request_error_total",
            Help: "Total number of service request errors, partitioned by error type",
        },
        []string{"error_type"},
    )
)
  • promauto.MustNewCounterVec 自动注册并返回线程安全的 CounterVec;
  • Name 必须含 _total 后缀,符合 Prometheus 约定;
  • error_type 标签用于区分 timeout, validation, not_found, internal 等错误分类。

错误上报逻辑示例

func handleRequest(ctx context.Context, req *Request) error {
    if err := validate(req); err != nil {
        errCounter.WithLabelValues("validation").Inc()
        return errors.Wrap(err, "validate request")
    }
    // ...
}
error_type 触发场景 是否可重试
validation 参数校验失败 是
timeout 下游调用超时 是
internal 服务内部 panic/panic 否
graph TD
    A[业务逻辑] --> B{发生错误?}
    B -->|是| C[提取 error_type]
    C --> D[errCounter.WithLabelValues\\(type\\).Inc\\(\\)]
    B -->|否| E[正常返回]

第四章:双标准交叉校验下的Go指标治理工程化落地

4.1 构建Go CI流水线:go generate + promlint + uber-metrics-validator三阶检查(GitHub Actions配置与Go build tag隔离策略)

三阶检查设计思想

CI阶段按职责分层:

  • 第一阶:go generate 触发代码生成(如 //go:generate prometheus-go-metrics-gen ...)
  • 第二阶:promlint 校验 Prometheus 指标命名与类型合规性
  • 第三阶:uber-metrics-validator 验证指标注册语义(如重复注册、未使用标签等)

GitHub Actions 配置片段

- name: Run metrics validation
  run: |
    go generate ./...
    go install github.com/prometheus/promu/cmd/promlint@latest
    promlint ./metrics/... || exit 1
    go install go.uber.org/tools/metrics/validator@latest
    uber-metrics-validator --pkg ./metrics --build-tags ci-metrics

--build-tags ci-metrics 确保仅在 CI 中启用指标校验逻辑,避免污染主构建;go generate 依赖 //go:generate 注释,需提前在 metrics/ 包中声明生成规则。

构建标签隔离策略对比

场景 build tag 效果
本地开发 — 跳过指标生成与验证
CI 流水线 ci-metrics 启用 go generate + 全量校验
性能压测环境 no-metrics 编译期剔除所有指标注册逻辑
graph TD
  A[Push to main] --> B[Checkout + Setup Go]
  B --> C[go generate with //go:generate]
  C --> D[promlint: syntax & naming]
  D --> E[uber-metrics-validator: semantic rules]
  E --> F{All pass?}
  F -->|Yes| G[Proceed to unit test]
  F -->|No| H[Fail fast with line/column info]

4.2 使用go:generate自动生成符合双标准的指标声明模板(基于text/template的Go struct元编程实践)

为何需要双标准模板

Prometheus 指标需同时满足:

  • Go 运行时类型安全(*prometheus.CounterVec 字段)
  • OpenMetrics 兼容命名规范(snake_case 标签名 + metric_name_total 后缀)

模板驱动生成流程

// metrics_gen.go
//go:generate go run gen_metrics.go --output=metrics_decl.go
package main

type MetricDef struct {
    Name        string   // 如 "http_request_duration_seconds"
    Help        string   // 如 "HTTP request duration in seconds"
    Labels      []string // 如 ["method", "status"]
    Type        string   // "counter", "histogram"
}

此结构体作为 text/template 的数据源,定义了所有可生成指标的元信息。go:generate 触发时注入结构体实例,交由 gen_metrics.go 渲染模板。

生成逻辑核心(mermaid)

graph TD
A[go:generate] --> B[读取metrics.yaml]
B --> C[解析为[]MetricDef]
C --> D[渲染template/metrics.tmpl]
D --> E[输出metrics_decl.go]

生成结果节选(表格对比)

原始定义字段 生成 Go 字段名 生成 Prometheus 名
http_request_duration_seconds HTTPRequestDurationSeconds http_request_duration_seconds_sum

4.3 Prometheus exporter与Go pprof指标对齐:避免命名冲突的边界治理(Go net/http/pprof指标重映射与alias注册技巧)

数据同步机制

Go net/http/pprof 默认暴露的指标(如 http_request_duration_seconds)与 Prometheus 常用命名规范存在语义/粒度差异,直接抓取易引发命名冲突或语义歧义。

重映射核心策略

使用 promhttp.Handler() 配合自定义 Registry,通过 prometheus.WrapRegistererWith() 注入命名前缀与别名映射:

// 创建带 alias 的 registry,将 pprof 指标重映射为标准命名
reg := prometheus.WrapRegistererWith(
    prometheus.Labels{"source": "pprof"},
    prometheus.NewRegistry(),
)
// 手动注册重命名后的 pprof 指标(如 runtime_go_threads → go_threads_total)
reg.MustRegister(
    prometheus.NewGaugeVec(
        prometheus.GaugeOpts{
            Name: "go_threads_total", // 标准命名
            Help: "Number of OS threads created.",
        },
        nil,
    ).WithLabelValues(),
)

此代码显式覆盖默认 runtime.NumGoroutine() 等指标的原始名称,规避 go_goroutines 与 process_num_threads 的语义重叠。WrapRegistererWith 不修改指标值,仅控制注册时的元数据边界。

关键映射对照表

pprof 原名(非标准) 推荐 alias 语义说明
go_goroutines go_goroutines_total 符合 Prometheus 类型后缀规范
go_memstats_alloc_bytes go_memory_bytes 统一单位与维度语义

流程图:指标生命周期治理

graph TD
A[pprof HTTP handler] --> B[Raw metric scrape]
B --> C{Name normalization layer}
C --> D[Alias registry]
D --> E[Prometheus target]

4.4 SRE拉黑清单自动化检测:基于AST解析的Go源码指标合规性扫描(golang.org/x/tools/go/ast + ruleguard规则编写实战)

SRE团队需阻断高危指标上报路径,如 prometheus.MustRegister() 直接注册未加命名空间前缀的 CounterVec。

核心检测逻辑

使用 ruleguard 编写语义规则,匹配 AST 中 CallExpr 调用 MustRegister 且参数为 *prometheus.CounterVec 类型但缺失 WithLabelValues 链式调用:

// ruleguard: ignore
m.Match(`prometheus.MustRegister($_)`).
  Where(m["$_"].Type.Is("*prometheus.CounterVec") && !hasWithLabelValues(m["$_"])).
  Report("禁止直接注册裸 CounterVec:需通过 WithLabelValues 初始化")

逻辑分析:m["$_"] 捕获调用参数;Type.Is 做精确类型判定(非字符串匹配);hasWithLabelValues 是自定义 AST 遍历函数,检查是否含 CallExpr.Fun 为 WithLabelValues 的链式调用。

典型违规模式对比

场景 是否合规 原因
prometheus.MustRegister(cv.WithLabelValues("a")) ✅ 显式绑定标签
prometheus.MustRegister(cv) ❌ 裸指针注册,导致指标名冲突

扫描流程

graph TD
  A[Go源码文件] --> B[go/ast.ParseFile]
  B --> C[ruleguard.RunRules]
  C --> D{匹配MustRegister+CounterVec?}
  D -->|是| E[校验WithLabelValues链]
  D -->|否| F[跳过]
  E -->|缺失| G[输出告警位置]

第五章:指标命名规范失效的代价与演进展望

真实故障复盘:Prometheus 中的 http_request_duration_seconds 误用事件

2023年Q3,某电商中台团队因将 http_request_duration_seconds_count 错误地命名为 http_request_duration_seconds_total,导致 Grafana 告警面板持续显示“请求延迟突增”。运维人员耗时4.5小时排查,最终发现该指标实际是计数器(Counter)而非直方图分位数——其值每分钟增长超200万,而告警规则错误地将其当作 histogram_quantile(0.95, ...) 的输入源。根本原因在于命名未体现类型语义,违反了 OpenMetrics 类型后缀约定。

指标爆炸与可观测性债务的量化代价

某金融云平台在三年内指标总量从12万增长至87万,其中41%的指标存在命名歧义(如 cpu_usage 未注明单位/维度/采集方式)。SRE团队统计显示:每次新增监控看板平均需额外花费22分钟确认指标语义;CI/CD流水线中因指标名变更引发的告警误触发年均达67次,平均修复耗时19分钟/次。下表为典型命名冲突导致的运维成本对比:

命名问题类型 年均故障次数 平均MTTR(分钟) 关联告警误报率
缺少服务层级前缀 24 15 38%
单位未显式声明 31 28 62%
维度键值未标准化 19 41 79%

从人工约定到机器可读的演进路径

业界正加速推进指标元数据自动化注入。CNCF项目OpenTelemetry Collector v0.92起支持通过metricstransformprocessor自动补全缺失的unit、description和type字段。例如以下配置可将裸指标名request_latency_ms重写为符合OpenMetrics 1.0标准的完整标识:

processors:
  metricstransform:
    transforms:
      - include: request_latency_ms
        action: update
        new_name: http_server_request_duration_seconds
        operations:
          - action: add_label
            new_label: unit
            new_value: seconds
          - action: add_label
            new_label: type
            new_value: histogram

规范即代码:GitOps驱动的指标治理实践

某支付网关团队将指标命名策略嵌入CI流水线:所有新提交的Prometheus exporter代码必须通过promtool check metrics校验,且需匹配预定义的正则规则集。关键约束包括:

  • 所有Counter类指标强制以 _total 结尾(如 http_requests_total)
  • Duration类指标单位统一转换为seconds并标注_seconds
  • 业务维度标签必须来自白名单(service, endpoint, status_code, region)

该机制上线后,新指标命名违规率从34%降至0.7%,且首次实现指标注册与文档生成的自动同步。

flowchart LR
    A[开发者提交指标定义] --> B{CI流水线校验}
    B -->|通过| C[自动注入OpenMetrics元数据]
    B -->|失败| D[阻断PR并返回具体违规行号]
    C --> E[同步更新指标字典与Grafana模板变量]
    D --> F[开发者修正命名]

跨语言SDK的语义一致性挑战

Java Micrometer与Python Prometheus Client对Timer类型的默认命名不一致:前者生成http.server.requests.duration,后者输出http_server_requests_duration_seconds。某混合技术栈项目因此出现跨服务调用链路追踪断点——Zipkin无法关联Python服务的duration指标。团队最终通过定制NamingConvention适配器,在Micrometer中强制启用PrometheusNamingConvention,并在Python端禁用自动单位后缀,实现两端指标名完全对齐。

关注异构系统集成,打通服务之间的最后一公里。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注