首页
/ Gitea 监控 Mixin 实战:从内置 Metrics 指标生成可配置的 Grafana 仪表盘

Gitea 监控 Mixin 实战:从内置 Metrics 指标生成可配置的 Grafana 仪表盘

2026-09-05 16:54:43作者:温玫谨Lighthearted

Gitea 仓库自带一套 Prometheus 指标端点,而 contrib/grafana-monitoring-mixin/README.md 讲解的正是如何基于这些指标,用 Jsonnet + Grafonnet 工具链生成一组可配置的 Grafana 仪表盘。读完本文,你将掌握:Gitea 端 [metrics] 配置项的开启方式、jb/jsonnet/mixtool 等工具的安装、make 构建流程的每一步在做什么,以及 config.libsonnet 中每个可定制参数(仪表盘命名、刷新频率、Issue 分仓/分标签图、标签配色)如何影响最终导入 Grafana 的 JSON 文件。

一、Mixin 的定位与目录结构

所谓 "mixin",是 Prometheus 社区监控生态中的一种约定:用代码(这里是 Jsonnet)声明式地描述一套仪表盘与告警规则,通过构建工具生成 Grafana 可直接导入的 JSON。Gitea 的 Mixin 位于 contrib/grafana-monitoring-mixin/ 目录,其定位是基于 Gitea 内置 metrics 端点导出的指标构建仪表盘,而不是自己采集。

目录职责如下:

文件/目录 作用
contrib/grafana-monitoring-mixin/Makefile 构建入口,定义 vendor、build、fmt、lint、dashboards_out、clean 等目标
contrib/grafana-monitoring-mixin/mixin.libsonnet Mixin 主入口,把仪表盘定义与用户配置两个 Jsonnet 对象合并
contrib/grafana-monitoring-mixin/config.libsonnet 用户可编辑的配置项(命名、标签、刷新周期、要展示的指标、标签配色等)
contrib/grafana-monitoring-mixin/dashboards/overview.libsonnet "Gitea Overview" 仪表盘的全部面板定义
contrib/grafana-monitoring-mixin/dashboards/dashboards.libsonnet 仪表盘聚合层,当前转发到 overview
contrib/grafana-monitoring-mixin/lib/dashboards.jsonnet 构建入口脚本,遍历 grafanaDashboards 对象生成多个 JSON 文件
contrib/grafana-monitoring-mixin/lib/alerts.jsonnetcontrib/grafana-monitoring-mixin/lib/rules.jsonnet Prometheus 告警与规则 YAML 的脚手架(见第六节说明)
contrib/grafana-monitoring-mixin/jsonnetfile.json jsonnet-bundler 依赖声明

jsonnetfile.json 可以看到唯一的依赖是 Grafana 官方维护的 grafonnet-lib(子目录 grafonnet),版本锁定在 master;具体的锁版本记录在 jsonnetfile.lock.json 中,由 jb install 拉取到 vendor/ 目录供 jsonnet 通过 -J vendor 查找导入。

mixin.libsonnet 本身只有一行逻辑:

(import 'dashboards/dashboards.libsonnet') +
(import 'config.libsonnet')

即把"仪表盘定义"与"用户配置"两个对象相加合并。仪表盘一侧通过 grafanaDashboards+:: 字段暴露面板,配置一侧通过 _config+:: 字段暴露参数,二者互不冲突,合并后供构建脚本按需取值。

二、前置条件:开启 Gitea 的 Metrics 端点

Mixin 消费的全部指标都来自 Gitea 自带的 /metrics 端点,因此部署侧必须先开启。参考 custom/conf/app.example.ini[metrics] 段的官方注释:

;[metrics]
;; Enables metrics endpoint. True or false; default is false.
;ENABLED = false
;; If you want to add authorization, specify a token here
;TOKEN =
;; Enable issue by label metrics; default is false
;ENABLED_ISSUE_BY_LABEL = false
;; Enable issue by repository metrics; default is false
;ENABLED_ISSUE_BY_REPOSITORY = false

这 4 个配置项与源码的对应关系可以在 modules/setting/metrics.go 中得到印证:

var Metrics = struct {
	Enabled                  bool
	Token                    string
	EnabledIssueByLabel      bool
	EnabledIssueByRepository bool
}{
	Enabled:                  false,
	Token:                    "",
	EnabledIssueByLabel:      false,
	EnabledIssueByRepository: false,
}

即全部默认关闭:不配置时 /metrics 端点不启用,Prometheus 抓不到任何 gitea_ 前缀的指标,仪表盘自然一片空白。

指标本身的实现位于 modules/metrics/collector.gonamespace 常量定义为 "gitea_"Collector 结构体逐一定义了 gitea_organizationsgitea_usersgitea_teamsgitea_repositoriesgitea_milestonesgitea_starsgitea_releasesgitea_issuesgitea_issues_opengitea_issues_closedgitea_issues_by_labelgitea_issues_by_repository 等描述符。Mixin 中引用的每一个指标名都必须能在该 Collector(或标准 Go/进程指标如 process_*)中找到来源,这一点后文逐面板核对。

注意一个历史前提:README 中提到 gitea_issues_by_repository / gitea_issues_by_label 两个指标"Requires Gitea 1.16.0 with … set to true"。在当前仓库代码中,这两个描述符已直接内建于 Collector,且分别受 ENABLED_ISSUE_BY_LABELENABLED_ISSUE_BY_REPOSITORY 两个开关控制,标签维度形如 gitea_issues_by_label{label="bug"},仓库维度形如 gitea_issues_by_repository{repository="org/repo"}——这正与 config.libsonnet 中注释给出的指标样例一致。

三、安装构建工具

contrib/grafana-monitoring-mixin/README.md 的步骤,需要安装两类工具:

# 依赖拉取 + 渲染核心(必需)
go install github.com/jsonnet-bundler/jsonnet-bundler/cmd/jb@latest
go install github.com/google/go-jsonnet/cmd/jsonnet@latest
# 或用 Homebrew: brew install go-jsonnet

# 校验与格式化(可选,但有 Go 环境时装一下最方便)
go install github.com/monitoring-mixins/mixtool/cmd/mixtool@latest
go install github.com/google/go-jsonnet/cmd/jsonnetfmt@latest

各工具在构建流程中的分工:

  • jb:读取 jsonnetfile.json,把 grafonnet-lib 依赖下载到 vendor/(对应 Makefile 的 vendor 目标);
  • jsonnet:把 Jsonnet 源文件求值、manifest 成 Grafana JSON(对应 dashboards_out 目标);
  • mixtool:mixin 项目的官方校验器,用于检查 mixin 结构是否符合约定(make lint 中执行 mixtool lint mixin.libsonnet);
  • jsonnetfmt:Jsonnet 格式化器,保证源码风格统一(make fmt / make lint)。

四、构建流程:make 到底做了什么

构建命令只有一条:

make

对照 Makefile 逐目标拆解:

JSONNET_FMT := jsonnetfmt -n 2 --max-blank-lines 1 --string-style s --comment-style s

all: build dashboards_out

vendor: jsonnetfile.json
	jb install

build: vendor

dashboards_out: mixin.libsonnet config.libsonnet $(wildcard dashboards/*)
	@mkdir -p dashboards_out
	jsonnet -J vendor -m dashboards_out lib/dashboards.jsonnet

clean:
	rm -rf dashboards_out
  1. vendor:执行 jb install,依据 jsonnetfile.json 拉取 grafonnet-libvendor/。注意该目标依赖 jsonnetfile.json 这一文件,只有它变动才会重新执行——锁文件 jsonnetfile.lock.json 保证依赖版本可复现。

  2. dashboards_out(默认目标 all 的实质工作):

    jsonnet -J vendor -m dashboards_out lib/dashboards.jsonnet
    
    • -J vendor:把 vendor/ 加入导入搜索路径,这样 overview.libsonnet 第一行的 import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet' 才能解析;
    • -m dashboards_out:把顶层对象的每个字段分别输出为 dashboards_out/<字段名> 文件。
  3. fmt / lint:前者用 jsonnetfmt -i 原地格式化全部 *.libsonnet/*.jsonnet(跳过 vendor);后者用 diff 方式检查格式化差异,并额外跑 mixtool lint mixin.libsonnet 校验 mixin 规范。

  4. clean:删除 dashboards_out 目录。

构建入口 lib/dashboards.jsonnet 只有 5 行:

local dashboards = (import '../mixin.libsonnet').grafanaDashboards;

{
  [name]: dashboards[name]
  for name in std.objectFields(dashboards)
}

它从合并对象中取出 grafanaDashboards,再对每个仪表盘名(当前是 gitea-overview.json)逐个输出。因此最终产物是 dashboards_out/gitea-overview.json,需要导入 Grafana。README 提醒:导入方式取决于你的环境(Grafana 界面导入、provisioning 目录、API 等),Mixin 本身只负责生成 JSON。

五、config.libsonnet:可配置项逐项解析

mixin.libsonnet 合并的配置一侧就是 config.libsonnet_config 字段,它是唯一需要用户编辑的文件。逐项说明:

字段 默认值 作用
dashboardNamePrefix 'Gitea' 仪表盘标题前缀,最终标题为 '%s Overview' % prefix(即 "Gitea Overview")
dashboardTags ['gitea'] 写入仪表盘 tags,便于在 Grafana 中按标签检索
dashboardPeriod 'now-1h' 仪表盘 time_from,即打开时的默认时间窗口
dashboardTimezone 'default' 时区设置
dashboardRefresh '1m' 自动刷新间隔
showIssuesByRepository true 是否渲染 "Issues by repository" 面板;依赖 ENABLED_ISSUE_BY_REPOSITORY = true
showIssuesByLabel true 是否渲染 "Issues by label" 面板;依赖 ENABLED_ISSUE_BY_LABEL = true
showIssuesOpenClose true true 时 Gitea stats 展示 gitea_issues_open/gitea_issues_closed 两个指标;false 时退化为单个 gitea_issues
giteaStatMetrics 见下文 Gitea stats 统计面板与 Changes 变化图使用的指标列表,可按需增删
issueLabels 见下文 Issue 标签 → 颜色的映射,用于图上按标签着色

giteaStatMetrics 的默认列表为:

[
  { name: 'gitea_organizations', description: 'Organizations' },
  { name: 'gitea_teams',         description: 'Teams' },
  { name: 'gitea_users',        description: 'Users' },
  { name: 'gitea_repositories', description: 'Repositories' },
  { name: 'gitea_milestones',   description: 'Milestones' },
  { name: 'gitea_stars',        description: 'Stars' },
  { name: 'gitea_releases',     description: 'Releases' },
]
+ if c.showIssuesOpenClose then
  [
    { name: 'gitea_issues_open',  description: 'Issues opened' },
    { name: 'gitea_issues_closed', description: 'Issues closed' },
  ] else
  [
    { name: 'gitea_issues', description: 'Issues' },
  ]

注意两个机制:name 即 Prometheus 指标名(description 只用于面板图例/文案);列表通过 Jsonnet 的对象字段拼接 +动态组合——showIssuesOpenClosetrue 时追加开/关 Issue 两条曲线,否则回落到总数曲线。列表中每个 name 都对应 collector.go 中的描述符(OrganizationsTeamsUsersRepositoriesMilestonesStarsReleasesIssuesOpenIssuesClosedIssues)。如果你的 Gitea 版本不导出某个指标,把对应项从列表删掉即可,这正是 README 所说"Edit config.libsonnet if required"的含义。

issueLabels 默认提供 6 个常用标签的配色(bugduplicateinvalidenhancementhelp wantedquestion)。这些颜色在仪表盘里不是简单图例,而是通过 overview.libsonnet 顶部的 addIssueLabelsOverrides 函数,为每个标签生成一条 byRegexp matcher 的 field override,把对应序列固定为该颜色——因此你只需在 issueLabels 里增删 {label, color} 条目,图上分标签曲线就会自动换色。

六、生成的仪表盘长什么样:Gitea Overview 面板解析

overview.libsonnet 用 Grafonnet 的 grafana.dashboard.new(...) 构建 uidgitea-overview 的仪表盘,全部查询统一带 job=~"$job", instance=~"$instance" 两个模板变量选择器,数据源也统一走 $datasource

模板变量(4 个):

  • datasource:类型 datasource、查询 prometheus,默认文本 "Prometheus"——让导入后的仪表盘自动匹配任意 Prometheus 数据源;
  • joblabel_values(gitea_organizations, job),多选,allValue.+——job 下拉框直接枚举抓到了哪些 Gitea 实例;
  • instancelabel_values(gitea_organizations{job="$job"}, instance),随 job 联动过滤;
  • agg_interval:interval 型变量,query: '1m,10m,1h,1d,7d'auto_min: '1m',供变化类面板做聚合区间。

面板与对应 PromQL(均带 {job=~"$job", instance=~"$instance"} 选择器):

面板 类型 查询
Gitea stats stat(lastNotNull,蓝色数值模式) giteaStatMetrics 列表中的每个指标名,图例取 description
Uptime stat(area 图,单位秒) time() - process_start_time_seconds{...}
Memory usage timeseries(字节,绿色平滑) process_resident_memory_bytes{...}
CPU usage timeseries(百分比,绿→红渐变) rate(process_cpu_seconds_total{...}[$__rate_interval]) * 100
File descriptors usage timeseries(双序列) process_open_fds{...}process_max_fds{...},上限序列被 override 成红色虚线
Changes stat(-- Dashboard -- 数据源,sum 聚合) 引用下方"全量变化"面板的 refId A 求和
Changes(图) 堆叠柱状图(drawStyle: 'bars' changes(process_start_time_seconds{...}[$__interval]) > 0(重启计数,图例 "Restarts")+ 各 stat 指标 floor(delta(m{...}[$__interval])) > 0
Issues by repository 柱状图 + 汇总 stat floor(increase(gitea_issues_by_repository{...}[$__interval])) > 0,图例 {{ repository }}
Issues by labels 柱状图 + 汇总 stat,按 issueLabels 着色 floor(increase(gitea_issues_by_label{...}[$__interval])) > 0,图例 {{ label }}

两个值得注意的实现细节:

  1. "Changes" 汇总面板用 Grafana 的 -- Dashboard -- 数据源引用兄弟面板(panelId 指向变化图面板的静态 id 200refId: 'A'),把图里所有序列按 sum 汇成一个大数字,实现"本期共多少变化"的总览。
  2. 面板静态 id 刻意保留:变化图面板、分仓图(id 210)、分标签图(id 220)及其汇总面板(211221)是通过 panels+: 补丁方式而非 .addPanel() 写入的(源码注释写明 "use patching instead of .addPanel() to keep static ids"),因为 -- Dashboard -- 引用依赖固定 id;而分仓/分标签两块又受 showIssuesByRepository / showIssuesByLabel 开关控制,用 if ... else [] 条件拼接进面板数组。

进程级指标(process_*time())来自 Prometheus 默认对 Go 应用采集的 standard library 指标,仓库级指标则全部落在 gitea_ 命名空间,与 collector.go 一一对应。

七、导入 Grafana,以及 alerts / rules 脚手架

构建完成后,把 dashboards_out/ 下的 JSON 文件导入你的 Grafana 服务器即可。README 强调导入方式与环境相关(UI 导入、provisioning、API 皆可)。由于仪表盘声明了 datasource 模板变量且默认查询 prometheus,导入后只需确认有一个可用的 Prometheus 数据源,且该数据源已配置抓取 Gitea 的 /metrics 端点(建议保留 job 标签以便多实例区分)。

此外,lib/ 目录下还有 alerts.jsonnetrules.jsonnet 两个脚手架文件,分别通过 std.manifestYamlDoc 把 mixin 的 prometheusAlerts / prometheusRules 字段输出为 Prometheus 告警与规则 YAML。但就当前仓库代码结构看,mixin.libsonnet 只合并了 grafanaDashboards(仪表盘)与 _config(配置)两块,并未导出 prometheusAlerts/prometheusRules 字段,因此这两个入口目前属于为将来定义告警预留的骨架,Makefile 的默认构建也不会执行它们;如果你要落地告警,需要先在 mixin 侧补齐对应字段。

更高级的 mixin 用法(告警规则写法、与其他 mixin 组合等)可参考 monitoring-mixins 项目的官方文档(README 末尾给出的指引,此处不附外链)。

八、小结:一条命令的完整链路

把 README 的极简流程与源码对应起来,整条链路是:

[metrics] 配置开启 /metrics 端点(modules/setting/metrics.go)
        → Prometheus 抓取 gitea_* 指标(modules/metrics/collector.go)
        → jb install 拉取 grafonnet-lib(jsonnetfile.json)
        → jsonnet 求值 mixin.libsonnet(dashboards + config.libsonnet)
        → 输出 dashboards_out/gitea-overview.json(Makefile: dashboards_out)
        → 导入 Grafana,job/instance 变量自动枚举实例(overview.libsonnet)

关键文件速查:构建入口 Makefilelib/dashboards.jsonnet、用户配置 config.libsonnet、面板实现 dashboards/overview.libsonnet、服务端指标开关 custom/conf/app.example.ini[metrics] 段)与 modules/setting/metrics.go、指标定义 modules/metrics/collector.go

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384