新闻详情

新闻详情

首页 / 资讯中心 / 详情

在 GoFr 中发布自定义 Prometheus 指标:Counter、UpDownCounter、Histogram 与 Gauge 的注册与使用指南

发布时间:2026/9/13 8:35:52来源:尧图网络
在 GoFr 中发布自定义 Prometheus 指标:Counter、UpDownCounter、Histogram 与 Gauge 的注册与使用指南
在 GoFr 中发布自定义 Prometheus 指标Counter、UpDownCounter、Histogram 与 Gauge 的注册与使用指南【免费下载链接】gofrAn opinionated GoLang framework for accelerated microservice development. Built in support for databases and observability.项目地址: https://gitcode.com/GitHub_Trending/go/gofrGoFr 框架内置了基于 OpenTelemetryOTel的指标采集能力并以 Prometheus 格式对外暴露。本文讲解如何在 GoFr 应用中以app.Metrics()注册四种同步指标Counter、UpDownCounter、Histogram、Gauge在 Handler 中通过ctx.Metrics()记录数据并为指标附加标签Labels以实现多维度聚合与查询最后介绍默认:2121/metrics拉取端点以及 OTLP 推送模式的配置方式。读完本文你将掌握在 GoFr 服务中发布业务级自定义指标并接入 Prometheus/Grafana 的完整实战方案。指标体系概览GoFr 的自定义指标从哪里来GoFr 在启动时已经默认发布一批框架级指标如 HTTP 请求量、延迟、内存与协程状态等系统指标相关内容可参考 快速开始 - 可观测性。但业务侧往往需要统计交易成功次数当日赊销总额交易耗时分布商品库存这类服务专属指标这正是自定义指标的用武之地。GoFr 可以同时管理多个不同的指标每个指标在初始化阶段通过其唯一的**名称Name**进行标识重复注册同名指标会被拒绝。框架支持以下四种 Prometheus 格式的指标类型定义于 pkg/gofr/metrics/register.go 的Manager接口指标类型注册方法数据记录方法适用场景CounterNewCounter(name, desc)IncrementCounter(ctx, name, labels...)只增不减的计数如请求总数、成功次数UpDownCounterNewUpDownCounter(name, desc)DeltaUpDownCounter(ctx, name, value, labels...)可增可减的计数如当前连接数、赊销余额HistogramNewHistogram(name, desc, buckets...)RecordHistogram(ctx, name, value, labels...)分布统计如响应延迟、请求体大小GaugeNewGauge(name, desc)SetGauge(name, value, labels...)直接设定当前值的快照如库存、温度这四种类型在 OTel 规范中都属于同步 Instrumentsynchronous instrument即在应用代码的调用点主动记录数值。其中Gauge略有特殊——OTel 原生只提供异步观测型 GaugeGoFr 为了支持同步设置值并携带标签在 pkg/gofr/metrics/register.go 中通过自定义float64Gauge类型 底层异步回调callbackFunc实现对外表现为可直接SetGauge的同步语义。两条访问入口需要区分app.Metrics()在main中注册创建指标定义在 pkg/gofr/gofr.go最终委托给container.Metrics()见 pkg/gofr/container/container.goctx.Metrics()在 Handler 中记录填充数据通过gofr.Context暴露与请求上下文绑定可随请求传递 trace/span 信息。Counter统计只增不减的业务事件Counter是同步 Instrument只支持非负递增。适合统计已发生且不会回退的事件例如成功的交易笔数。package main import ( gofr.dev/pkg/gofr ) func main() { // 初始化 gofr 对象 app : gofr.New() // 注册指标名称必须全局唯一描述用于 Prometheus HELP app.Metrics().NewCounter(transaction_success, used to track the count of successful transactions) app.POST(/transaction, func(ctx *gofr.Context) (any, error) { // 每次交易成功即 1 ctx.Metrics().IncrementCounter(ctx, transaction_success) return Transaction Successful, nil }) app.Run() }从源码实现看NewCounter底层调用meter.Int64Counter(name, metric.WithDescription(desc))创建 OTel 计数器并存入内部Storepkg/gofr/metrics/register.go。IncrementCounter从 Store 取出对应计数器并Add(ctx, 1, ...)pkg/gofr/metrics/register.go也就是说每次调用固定增加 1不能传增量值。提示如果计数器未注册就调用IncrementCounterGoFr 不会 panic而是记录一条Metrics xxx is not registered错误日志后静默返回详见 pkg/gofr/metrics/register_test.go 的Test_NewMetricsManagerMetricsNotRegistered。UpDownCounter可增可减的余额类指标UpDownCounter同样属于同步 Instrument支持递增和递减适合当前值随事件上下波动的指标。注意如果数值是单调递增的请改用Counter以免丢失语义。package main import ( gofr.dev/pkg/gofr ) func main() { // 初始化 gofr 对象 app : gofr.New() app.Metrics().NewUpDownCounter(total_credit_day_sale, used to track the total credit sales in a day) app.POST(/sale, func(ctx *gofr.Context) (any, error) { // 增加 1000 ctx.Metrics().DeltaUpDownCounter(ctx, total_credit_day_sale, 1000) return Sale Completed, nil }) app.Run() }与IncrementCounter固定 1 不同DeltaUpDownCounter的第二个参数是任意 float64 增量传正数即增加传负数即减少。源码中通过meter.Float64UpDownCounter创建记录时执行upDownCounter.Add(ctx, value, ...)pkg/gofr/metrics/register.go。例如退货场景可以调用DeltaUpDownCounter(ctx, total_credit_day_sale, -1000)冲减当日赊销额。Histogram统计数值的分布与百分位Histogram是同步 Instrument用于上报具有统计意义的任意数值适合做直方图、汇总与百分位分析最典型的场景是记录交易耗时。package main import ( time gofr.dev/pkg/gofr ) func main() { // 初始化 gofr 对象 app : gofr.New() // 注册直方图并显式指定桶边界单位与记录值保持一致此处为毫秒 app.Metrics().NewHistogram(transaction_time, used to track the time taken by a transaction, 5, 10, 15, 20, 25, 35) app.POST(/transaction, func(ctx *gofr.Context) (any, error) { transactionStartTime : time.Now() // transaction logic tranTime : time.Now().Sub(transactionStartTime).Milliseconds() ctx.Metrics().RecordHistogram(ctx, transaction_time, float64(tranTime)) return Transaction Completed, nil }) app.Run() }关于桶边界bucket boundaries源码注释给出了清晰解释pkg/gofr/metrics/register.goNewHistogram的可变参数会通过metric.WithExplicitBucketBoundaries传入 OTel每个记录值会落入对应的桶区间而最后一个桶自动覆盖所有超过最大边界值的样本等价于Inf。以上例的5, 10, 15, 20, 25, 35毫秒为例实际生成[0,5)、[5,10)、[10,15)、[15,20)、[20,25)、[25,35)、[35,Inf)共 7 个桶。Prometheus 暴露端会据此生成_bucket、_sum、_count系列可直接用于延迟的 P50/P95/P99 计算。桶边界应贴合你的业务数据量级避免样本集中堆积在首尾桶而失去分布意义。Gauge直接设定当前值的快照Gauge是同步 Instrument用于在值发生变化时记录不可累加的当前值例如商品库存、内存水位。package main import ( gofr.dev/pkg/gofr ) func main() { // 初始化 gofr 对象 app : gofr.New() app.Metrics().NewGauge(product_stock, used to track the number of products in stock) app.POST(/sale, func(ctx *gofr.Context) (any, error) { // 直接把库存设为 10覆盖上一次的值 ctx.Metrics().SetGauge(product_stock, 10) return Sale Completed, nil }) app.Run() }SetGauge的语义是覆盖而非累加每调用一次就把指标值设定为给定值pkg/gofr/metrics/register.go。底层float64Gauge内部维护observations map[attribute.Set]float64每次set都会覆盖对应标签组合的值再由 OTel 的异步回调在采集时统一上报。注意 Gauge 不保留历史轨迹Prometheus 侧通常配合rate()/delta()或直接看当前值使用。为自定义指标添加标签Labels标签是指标的键值对用于对同一指标按维度切分从而生成不同的时间序列实现更细粒度的分析与 Grafana 仪表盘筛选。常见标签示例environment如production、stagingservice如api-gateway、databasestatus如success、failure使用方式标签在填充指标数据时传入即作为 GoFr 记录方法IncrementCounter、DeltaUpDownCounter、RecordHistogram、SetGauge的可变参数以键、值、键、值逗号分隔的交替顺序排列c.Metrics().IncrementCounter(c, metric-name, metric-value, label-1, value-1, label-2, value-2)下面是一个同时注册指标、使用两个路由并携带不同标签的完整示例——同一指标total_credit_day_sale通过sale_type、product_type两个标签被拆分成多个时间序列package main import ( gofr.dev/pkg/gofr ) func main() { // 初始化 gofr 对象 a : gofr.New() // 注册自定义指标 a.Metrics().NewUpDownCounter(total_credit_day_sale, used to track the total credit sales in a day) // 注册所有路由 a.POST(/sale, SaleHandler) a.POST(/return, ReturnHandler) // 启动应用 a.Run() } func SaleHandler(c *gofr.Context) (any, error) { // 销售逻辑 // sale_type 与 product_type 是标签credit 与 beverage 是对应的值 c.Metrics().DeltaUpDownCounter(c, total_credit_day_sale, 10, sale_type, credit, product_type, beverage) return Sale Successful, nil } func ReturnHandler(c *gofr.Context) (any, error) { // 退货逻辑 c.Metrics().DeltaUpDownCounter(c, total_credit_day_sale, -5, sale_type, credit_return, product_type, dairy) return Return Successful, nil }标签使用建议尽量控制标签数量避免标签组合爆炸带来的复杂性选择能清晰描述数据点的有意义的标签名在应用内保持标签命名规范的一致性。标签组合的每一种键值排列permutation构成该指标的一个基数cardinality。从 pkg/gofr/metrics/register.go 的getAttributes实现可以看到 GoFr 的约束与校验标签数量为奇数键值不配对时记录一条metrics name label has invalid key-value pairs警告日志见 pkg/gofr/metrics/register_test.go 的Test_NewMetricsManagerInvalidLabelPairErrors单次调用携带超过 20 个标签时记录has high cardinality警告测试用例可见 pkg/gofr/metrics/register_test.go。基数越低查询性能越快、监控资源占用越低。因此在设计标签时应避免使用user_id、request_id这类高基数值作为标签值优先使用status、endpoint、region等低基数维度。组合四类指标完整电商交易示例仓库中的 examples/using-custom-metrics/main.go 将四种指标组合进一个模拟电商交易的场景并提供了配套的端到端测试 examples/using-custom-metrics/main_test.gopackage main import ( time gofr.dev/pkg/gofr ) const ( transactionSuccessful transaction_success transactionTime transaction_time totalCreditDaySales total_credit_day_sale productStock product_stock ) func main() { a : gofr.New() a.Metrics().NewCounter(transactionSuccessful, used to track the count of successful transactions) a.Metrics().NewUpDownCounter(totalCreditDaySales, used to track the total credit sales in a day) a.Metrics().NewGauge(productStock, used to track the number of products in stock) a.Metrics().NewHistogram(transactionTime, used to track the time taken by a transaction, 5, 10, 15, 20, 25, 35) a.POST(/transaction, TransactionHandler) a.POST(/return, ReturnHandler) a.Run() } func TransactionHandler(c *gofr.Context) (any, error) { transactionStartTime : time.Now() // transaction logic c.Metrics().IncrementCounter(c, transactionSuccessful) c.Metrics().RecordHistogram(c, transactionTime, float64(time.Now().Sub(transactionStartTime).Milliseconds())) c.Metrics().DeltaUpDownCounter(c, totalCreditDaySales, 1000, sale_type, credit) c.Metrics().SetGauge(productStock, 10) return Transaction Successful, nil } func ReturnHandler(c *gofr.Context) (any, error) { // logic to create a sales return c.Metrics().DeltaUpDownCounter(c, totalCreditDaySales, -1000, sale_type, credit_return) c.Metrics().SetGauge(productStock, 50) return Return Successful, nil }测试断言给出了标签在 Prometheus 文本格式中的实际呈现效果examples/using-custom-metrics/main_test.go例如total_credit_day_sale{otel_scope_nameusing-metrics,...,sale_typecredit} 1000 total_credit_day_sale{...,sale_typecredit_return} -1000 transaction_success{...} 1 product_stock{...} 50可以看到同一个指标名配合不同标签值会形成多条独立的时间序列otel_scope_name、otel_scope_version等是框架自动附加的 scope 标签。从app.Metrics()到/metrics一次记录的完整调用链从注册到被 Prometheus 抓取一次自定义指标的完整调用链如下注册阶段app.Metrics().NewXxx(...)pkg/gofr/gofr.go→container.Metrics()pkg/gofr/container/container.go→metricsManager.NewXxx创建 OTel Instrument 并写入内部Storepkg/gofr/metrics/register.go记录阶段Handler 内ctx.Metrics().IncrementCounter / DeltaUpDownCounter / RecordHistogram / SetGauge从Store取出对应 Instrument附加标签后调用 OTel API 记录暴露阶段metrics.GetHandlerpkg/gofr/metrics/handler.go注册GET /metrics路由将 OTel 指标通过promhttp.Handler()以 Prometheus 文本格式输出同时还挂载了runtime.ReadMemStats系统指标pkg/gofr/metrics/handler.go与pprof调试端点服务阶段metricServer在独立端口启动 HTTP 服务pkg/gofr/metrics_server.go默认端口为2121并支持优雅关闭。指标暴露与采集拉取Pull与推送Push两种模式默认拉取模式:2121/metricsGoFr 默认在2121端口提供 Prometheus 拉取端点。端口通过METRICS_PORT环境变量配置启动时initMetricsServer读取该值pkg/gofr/factory.go解析失败或非法时回退到默认端口METRICS_PORT0则完全禁用指标服务推送模式下可关闭拉取端口。go run main.go curl localhost:2121/metrics # 查看自定义指标与框架指标Prometheus 服务端配置一个 scrape job 指向该端点即可持续采集。推送模式OTLP Exporter纯环境变量配置如果希望把指标推送到 OTLP Collector 或云厂商后端Datadog、Grafana Cloud、New Relic 等无需改动任何 Go 代码只需修改configs/.env。GoFr 会在同一批 Instrument 上同时构建 Prometheus 拉取 reader 与 OTLP 推送 reader因此/metrics依然可被拉取、指标同时被推送且不会重复计数细节见 examples/using-custom-metrics/README.md。配置项含义默认值METRICS_EXPORTER设为otlp启用推送不设置或prometheus则仅拉取prometheusMETRICS_URLCollector/后端地址gRPC 用host:portHTTP 用 URL—METRICS_PROTOCOLgrpc默认或httpgrpcMETRICS_EXPORT_INTERVAL推送间隔秒30METRICS_TEMPORALITYcumulative默认、delta或lowmemorycumulativeMETRICS_HEADERSkeyvalue,keyvalue形式的请求头鉴权、路由—METRICS_AUTH_KEY快捷设置Authorization请求头—METRICS_INSECUREfalse默认保持 TLS本地明文 Collector 才设为truefalseMETRICS_PORT拉取端点端口0表示禁用纯推送2121本地起一个 OTLP Collector 调试docker compose up配置见 examples/using-custom-metrics/docker/otel-collector-config.yaml 与 examples/using-custom-metrics/docker/docker-compose.yaml并在configs/.env中配置METRICS_EXPORTERotlp METRICS_URLlocalhost:4317 METRICS_INSECUREtrueMETRICS_PORT与METRICS_EXPORTER相互独立纯推送的无服务器serverless模式即METRICS_EXPORTERotlpMETRICS_PORT0。关于注册信息的两个要点注册指标时必须提供两段信息Name名称指标的唯一标识Prometheus 中会转换为snake_case形式如transaction_successDescription描述出现在 PrometheusHELP输出中说明指标含义。而每次使用记录数据一个已注册指标时需要三段信息Name指标名Value本次记录的值Tags/Labels一组键值对用于维度切分。标签键值对的每种排列组合构成该指标的基数cardinality。基数越低查询性能越快监控资源消耗越低——这是设计标签时需要始终牢记的原则。生产实践衔接Kubernetes Prometheus在 K8s 中部署 GoFr 服务后可通过 ServiceMonitor 配置采集自定义指标并结合 recording rules 与 retention 策略进行生产级存储与查询参见 生产环境 Prometheus 部署指南基于自定义指标的水平伸缩发布的自定义指标可以驱动 Horizontal Pod Autoscaler 对 GoFr 服务进行自动扩缩容参见 Horizontal Pod Autoscaler 指南。结合本仓库的 使用自定义指标完整示例go run main.go后访问POST /transaction、POST /return再执行curl localhost:2121/metrics即可直观看到本文所述的四类指标与标签机制在实际服务中的表现。【免费下载链接】gofrAn opinionated GoLang framework for accelerated microservice development. Built in support for databases and observability.项目地址: https://gitcode.com/GitHub_Trending/go/gofr创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

LeetCode-Go 题解 1673:单调栈求最具竞争力子序列(Find the Most Competitive Subsequence) 2026/9/13 10:00:00

LeetCode-Go 题解 1673:单调栈求最具竞争力子序列(Find the Most Competitive Subsequence)

LeetCode-Go 题解 1673:单调栈求最具竞争力子序列(Find the Most Competitive Subsequence) 【免费下载链接】LeetCode-Go ✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解 项目地址: https://gi…

阅读更多 →
低功耗开发本质:嵌入式与安卓系统级功耗工程解析 2026/9/13 10:00:00

低功耗开发本质:嵌入式与安卓系统级功耗工程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Google Analytics Admin API .NET 客户端库安装与使用指南:基于 Google.Analytics.Admin.V1Beta 的 C 实战 2026/9/13 10:00:00

Google Analytics Admin API .NET 客户端库安装与使用指南:基于 Google.Analytics.Admin.V1Beta 的 C 实战

Google Analytics Admin API .NET 客户端库安装与使用指南:基于 Google.Analytics.Admin.V1Beta 的 C# 实战 【免费下载链接】skills Agent Skills for Google products and technologies 项目地址: https://gitcode.com/GitHub_Trending/skills29/skills 导…

阅读更多 →
类欧几里得算法与万能欧几里得算法:OI-wiki 中直线下整点计数与操作序列方法 2026/9/13 10:00:00

类欧几里得算法与万能欧几里得算法:OI-wiki 中直线下整点计数与操作序列方法

类欧几里得算法与万能欧几里得算法:OI-wiki 中直线下整点计数与操作序列方法 【免费下载链接】OI-wiki :star2: Wiki of OI / ICPC for everyone. (某大型游戏线上攻略,内含炫酷算术魔法) 项目地址: https://gitcode.com/GitHub…

阅读更多 →
Apache Arrow 开发者脚本指南:PR 合并流程与 Docker 集成测试实战(dev/README.md 深度解读) 2026/9/13 10:00:00

Apache Arrow 开发者脚本指南:PR 合并流程与 Docker 集成测试实战(dev/README.md 深度解读)

Apache Arrow 开发者脚本指南:PR 合并流程与 Docker 集成测试实战(dev/README.md 深度解读) 【免费下载链接】arrow Apache Arrow is the universal columnar format and multi-language toolbox for fast data interchange and in-memory an…

阅读更多 →
大模型时代:零基础转行AI的职业路径与技能解析 2026/9/13 9:56:59

大模型时代:零基础转行AI的职业路径与技能解析

1. 大模型行业现状与职业前景2023年被称为AI大模型元年,ChatGPT的爆发让全球看到了通用人工智能的潜力。根据LinkedIn最新报告,大模型相关岗位增长率达到惊人的740%,而人才供给缺口超过85%。这个领域正在经历类似移动互联网早期的爆发式增长&…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞