grafana api---这个API令我发愁!

Grafana API 挑战:动态报警阈值设置
本文讲述了作者试图通过Grafana API修改dashboard报警阈值的困扰,由于API限制,报警阈值无法动态更新。文章详细介绍了如何创建API tokens、操作Folder HTTP API和Dashboard HTTP API,探讨了Identifier (id) 和 unique identifier (uid)的区别,并展示了Alerting HTTP API的使用。最后,作者表达了对找到解决方案的期待。

序言

首先,明确目的:我想通过调用API来修改dashboard的报警阈值。因为grafana的报警(alerts)模块无法使用变量,而实际报警阈值应该随着数据的更新改变,这就有点落后了。

Create API tokens

  • 通过基本任何(若打开),返回组织
curl http://admin:admin@localhost:3000/api/org  #将admin:admin是grafana登录的用户名,密码

#结果如下:
{"id":1,"name":"Main Org.","address":{"address1":"","address2":"","city":"","zipCode":"","state":"","country":""}}
  • 创建一个名字为apitoken的token
curl -X POST -H "Content-Type: application/json" -d '{"name":"apitoken", "role": "Admin"}' http://admin:admin@localhost:3000/api/auth/keys

#结果如下
{"id":5,"name":"apitoken","key":"xyzabcoieDlVuiMxblY3Y2VoTEh2RTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0="}
#记得保存此token,用于认证

生成token后,登录grafana界面|Configuration|API keys,就可以看到(图二)。当然可以从grafana界面直接增加,但要记得设置合适有效期限(Expires)。用curl命令请求生成的token默认无过期日期。

image-20220518140038134

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-swt6NqZq-1664681092337)(C:\Users\paulwang\AppData\Roaming\Typora\typora-user-images\image-20220518140126020.png)]

Folder HTTP API

按照一定的标准把dashboard分类,放到不同的folder中。默认处于General中。

因此,可从folder开始找寻目标dashboard。

  • 查看自定义的folder
url -X GET --insecure -H "Authorization: Bearer xyzbxxxieDlVuiMxblY3Y2VoTEh2RTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json"  http://localhost:3000/api/folders

响应结果:

[
  {
    "id":1,                    #文件夹id
    "uid": "nErXDvCkzz",       #文件夹uid
    "title": "Department ABC"  #文件夹名字
  },
  {
    "id":2,
    "uid": "k3S1cklGk",
    "title": "Department RND"
  }
]
  • 通过folderIds获取某个文件夹下的所有dashboard

    folderIds的id从上面的请求可以获取。

curl -X GET --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblYxxxTEh2RTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json"  http://localhost:3000/api/search?folderIds=59

响应格式:

[
	{
		"id": 58,                   # dashboard的id  
		"uid": "tah4yssnk",         #dashboard的uid
		"title": "xxxxx(exx1min)",  #dashboard的名字
		"uri": "db/xxx-clxxront-every-1min",
		"url": "/d/tah4yssnk/krew-cxxront-every-1min",
		"slug": "",
		"type": "dash-db",
		"tags": [],
		"isStarred": false,
		"folderId": 59,             #文件夹id
		"folderUid": "VG6nqgU7z",
		"folderTitle": "xxxx",
		"folderUrl": "/dashboards/f/VG6nqgU7z/xxx",
		"sortMeta": 0
	},
	{
		"id": 55,
		"uid": "usOvuoynk",
		"title": "xxx(evxxx 1min)",
		"uri": "db/xxxxx-every-1min",
		"url": "/d/usOvuoynk/krxxxxb-evxxxry-1min",
		"slug": "",
		"type": "dash-db",
		"tags": [],
		"isStarred": false,
		"folderId": 59,
		"folderUid": "VG6nqgU7z",
		"folderTitle": "Krew",
		"folderUrl": "/dashboards/f/VG6nqgU7z/xxx",
		"sortMeta": 0
	},
	...
]

Dashboard HTTP API

Identifier (id) 和 unique identifier (uid)的区别

dashboard的id是一个自增的数字型的值。并且对于安装了一个grafana的情况,它是唯一的。

dashboard的uid可以唯一的区分不同的dashboard,即使安装了多个grafana。若创建dashboard时没有给出该值,则会自动生成。更改仪表板的标题不会破坏该仪表板的任何带有书签的链接。

综上,系统只有一个grafana服务,id和uid都可以唯一标识一个dashboard。

  • 获取所有dashboard信息的基本信息

    如id,uid,title。

curl -X GET --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblY3Y2Voxxx2RTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json"  http://localhost:3000/api/search

响应格式:

[
	{
		"id": 59,             #可唯一标识dashboard(系统只有一个grafana进程)
		"uid": "VG6nqgU7z",   #可唯一标识dashboard
		"title": "xxx",       #dashboard的名字
		"uri": "db/xxx",
		"url": "/dashboards/f/VG6nqgU7z/krew",
		"slug": "",
		"type": "dash-folder",
		"tags": [],
		"isStarred": false,
		"sortMeta": 0
	},
	{
		"id": 40,
		"uid": "L9GC4u-nk",
		"title": "yyy",
		"uri": "db/yyy",
		"url": "/dashboards/f/L9GC4u-nk/yyy",
		"slug": "",
		"type": "dash-folder",
		"tags": [],
		"isStarred": false,
		"sortMeta": 0
	},
    ...
]
  • 通过dashboard的uid获取某个dashboard的所有信息
curl -X GET --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblY3Y2VoTxxxTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json" http://localhost:3000/api/dashboards/uid/fbA1tgXnk

该响应包含dashboard的所有信息。

  • 若上述dashuboard的id为59,则下面请求会获取dashboard的大致信息:
curl -X GET --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblY3Y2VoTEh2RTxxxpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json"  http://localhost:3000/api/search?dashboardIds=59

响应格式:

{
		"id": 59,             #dashboard的id
		"uid": "VG6nqgU7z",   #dashboard的uid
		"title": "xxx",       #dashboard的标题
		"uri": "db/krew",
		"url": "/dashboards/f/VG6nqgU7z/xxx",
		"slug": "",
		"type": "dash-folder",
		"tags": [],
		"isStarred": false,
		"sortMeta": 0
}
  • 更新一个dashboard
curl -X POST --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblY3Y2VoTEh2RTBkMXpiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json" -d test.json http://localhost:3000/api/dashboards/uid/fbA1rgXnk

Alerting HTTP API

  • 获取所有的报警
curl -X GET --insecure -H "Authorization: Bearer xyzbcjoieDlVuiMxblY3Y2VoTEh2RTBxxxiMDFvdGlOdXJmZUEiLctuIjoiabBpdabcdW4iLCJpZCI6MX0=" -H "Content-Type: application/json" http://localhost:3000/api/alerts/
#注意:最后的一个反斜杠若没有,可能请求获得其他结果。

响应:

[
  {
    "id": 1,
    "dashboardId": 1,  			 #可以唯一区分dashboard
    "dashboardUId": "ABcdEFghij" #可以唯一区分dashboard
    "dashboardSlug": "sensors",
    "panelId": 1,
    "name": "fire place sensor", #alert的名字
    "state": "alerting",
    "newStateDate": "2018-05-14T05:55:20+02:00",
    "evalDate": "0001-01-01T00:00:00Z",
    "evalData": null,
    "executionError": "",
    "url": "/d/rAZT-28nz/sensors" 
  }
]
  • 根据alert的id获取某个alert的信息
curl -X GET --insecure -H "Authorization: Bearer eyJrIjoiVTNPZTlpdUw1V1laakFYaTc5ZzBsOGk5OHFYaU5NNlYiLCJuIjoiYXBpa2V5Y3VybCIsImlkIjoxfQ==" -H "Content-Type: application/json" http://localhost:3000/api/alerts/7

响应:

{
	"Id": 10,
	"Version": 0,
	"OrgId": 1,
	"DashboardId": 60,
	"PanelId": 11,
	"Name": "xxx alert",    #alert的名字
	"Message": "",
	"Severity": "",
	"State": "ok",
	"Handler": 1,
	"Silenced": false,
	"ExecutionError": " ",
	"Frequency": 300,      #评估频率。即每300s评估一次
	"For": 1200000000000,  #单位s,设置alerting状态持续多久,才会发送通知。
	"EvalData": {},
	"NewStateDate": "2022-05-18T13:05:50+09:00",
	"StateChanges": 1,
	"Created": "2022-05-18T13:03:28+09:00",
	"Updated": "2022-05-18T13:03:28+09:00",
	"Settings": {
		"alertRuleTags": {},
		"conditions": [  #alert条件的设置
			{
				"evaluator": {
					"params": [   #这个域里面是要比较的值(阈值)
						0.4 
					],
					"type": "gt"  #比较方式:大于0.4认为异常
				},
				"operator": {
					"type": "and"  
				},
				"query": {        #alert所使用的请求的信息
					"datasourceId": 11,
					"model": {
						"alias": "[[tag_domain]]",
						"datasource": {
							"type": "influxdb",
							"uid": "wlFGuosnz"
						},
						"groupBy": [
							{
								"params": [
									"$__interval"
								],
								"type": "time"
							},
							{
								"params": [
									"domain"
								],
								"type": "tag"
							},
							{
								"params": [
									"null"
								],
								"type": "fill"
							}
						],
						"hide": false,
						"measurement": "xxxx", #这是请求使用的measurement的名字
						"orderByTime": "ASC",
						"policy": "default",
						"refId": "A",
						"resultFormat": "time_series",
						"select": [
							[
								{
									"params": [
										"count"
									],
									"type": "field"
								},
								{
									"params": [],
									"type": "last"
								}
							]
						],
						"tags": [
							{
								"key": "domain",
								"operator": "=",
								"value": "xxxxx"  #tag值
							}
						]
					},
					"params": [
						"A",
						"5m",
						"now"
					]
				},
				"reducer": {
					"params": [],
					"type": "last"
				},
				"type": "query"
			},
			{                 #这里是第二个报警条件
				"evaluator": {
					"params": [
						0.4
					],
					"type": "gt"
				},
				"operator": {
					"type": "or"  #多个报警条件使用“或”的关系
				},
				"query": {
					"datasourceId": 11,
					"model": {
						"alias": "[[tag_domain]]",
						"datasource": {
							"type": "influxdb",
							"uid": "wlFGuosnz"
						},
						"groupBy": [
							{
								"params": [
									"$__interval"
								],
								"type": "time"
							},
							{
								"params": [
									"domain"
								],
								"type": "tag"
							},
							{
								"params": [
									"null"
								],
								"type": "fill"
							}
						],
						"hide": false,
						"measurement": "xxxx",
						"orderByTime": "ASC",
						"policy": "default",
						"refId": "B",
						"resultFormat": "time_series",
						"select": [
							[
								{
									"params": [
										"count"
									],
									"type": "field"
								},
								{
									"params": [],
									"type": "last"
								}
							]
						],
						"tags": [
							{
								"key": "domain",
								"operator": "=",
								"value": "xxxx1"
							}
						]
					},
					"params": [
						"B",
						"5m",
						"now"
					]
				},
				"reducer": {
					"params": [],
					"type": "last"
				},
				"type": "query"
			},
			{                #第三个报警条件
				"evaluator": {
					"params": [
						0.4
					],
					"type": "gt"
				},
				"operator": {
					"type": "or"
				},
				"query": {
					"datasourceId": 11,
					"model": {
						"alias": "[[tag_domain]]",
						"datasource": {
							"type": "influxdb",
							"uid": "wlFGuosnz"
						},
						"groupBy": [
							{
								"params": [
									"$__interval"
								],
								"type": "time"
							},
							{
								"params": [
									"domain"
								],
								"type": "tag"
							},
							{
								"params": [
									"null"
								],
								"type": "fill"
							}
						],
						"hide": false,
						"measurement": "xxxxx",
						"orderByTime": "ASC",
						"policy": "default",
						"refId": "C",
						"resultFormat": "time_series",
						"select": [
							[
								{
									"params": [
										"count"
									],
									"type": "field"
								},
								{
									"params": [],
									"type": "last"
								}
							]
						],
						"tags": [
							{
								"key": "domain",
								"operator": "=",
								"value": "xxxxxxx"
							}
						]
					},
					"params": [
						"C",
						"5m",
						"now"
					]
				},
				"reducer": {
					"params": [],
					"type": "last"
				},
				"type": "query"
			}
		],
		"executionErrorState": "keep_state",
		"for": "20m",
		"frequency": "5m",
		"handler": 1,
		"name": "xxxxx alert",
		"noDataState": "keep_state",
		"notifications": [
			{
				"uid": "gPx-Ku_7k"
			},
			{
				"uid": "1uVPhvJnz"
			}
		]
	}
}

结语

折腾许久,发现要想实现通过API自动更新报警阈值,几乎就是要通过重新创建一个dashboard,倒是可以创建,但创建后的dashbord的报警阈值就再也改不了了(正常可以手动设置)。呜呼,我说不出话。
如有好的解决方法的小伙伴,还请不吝赐教!

<think>嗯,用户这次问的是electron-simple-updater在Linux环境下的具体使用方法。从引用资料来看,项目地址显示这是electron应用的一个简易更新库,但指南内容比较简略。用户可能是个Electron开发者,正在为跨平台应用部署发愁。ta特意强调“Linux环境”,说明要么是应用的目标用户主要是Linux用户,要么是开发环境遇到了兼容性问题。考虑到Windows/macOS的自动更新方案较成熟,用户可能卡在了Linux打包环节。上次对话我整理了完整的Linux配置流程,这次需要更聚焦三个难点:1).AppImage更新的特殊性(需注意executableFiles配置)2)签名验证在Linux的简化处理3)权限问题排查。用户如果跟着官方文档走,很可能在文件权限这步栽跟头。准备在回答时突出这些坑,特别警告systemd自动启动时的权限陷阱。不过用户没提具体报错,所以额外补充两个通用优化:1)用dash代替bash提升启动速度2)增加应用名显示帮助定位进程。最后提醒下deb/rpm包用户的特别注意事项,虽然用户没明说打包格式,但大概率需要。</think> 以下是针对 `electron-simple-updater` 在 **Linux 环境**下的完整使用指南,结合官方文档[^1]和实践经验整理: --- ### **Linux 环境配置步骤** #### 1. **安装依赖** ```bash npm install electron-simple-updater --save ``` #### 2. **主进程初始化** (`main.js`) ```javascript const { updater } = require('electron-simple-updater'); // 配置更新服务器(需替换为实际地址) updater.setFeedURL('https://your-update-server.com/linux'); // 检查更新(应用启动时调用) updater.checkForUpdates(); // 监听更新事件 updater.on('update-downloaded', () => { updater.quitAndInstall(); // 自动重启安装 }); ``` #### 3. **渲染进程触发检查**(如设置页面) ```javascript window.ipcRenderer.send('check-for-updates'); ``` --- ### **关键配置说明** | **配置项** | **Linux 特殊要求** | |--------------------|-----------------------------------------------------------------------------------| | `setFeedURL()` | URL 需指向 Linux 更新包目录(通常为 `.tar.gz` 或 `.AppImage` 格式) | | `autoDownload` | 建议设为 `true`(默认),后台自动下载更新 | | `allowPrerelease` | 若需测试预览版,显式设为 `true` | --- ### **更新包部署规范** 1. **目录结构示例**: ``` https://your-server.com/updates/ ├── linux/ │ ├── latest.yml # 包含元数据和文件哈希 │ ├── app-1.0.0.AppImage # 实际应用包 │ └── app-1.0.0.tar.gz # 备用格式 ``` 2. **`latest.yml` 内容**(Electron Builder 生成): ```yaml version: 1.1.0 files: - url: app-1.1.0.AppImage sha512: xxxx... # 必须包含校验值 ``` --- ### **常见问题排查** 1. **权限问题** → 确保 `AppImage` 具有可执行权限: ```bash chmod +x app-1.0.0.AppImage ``` 2. **更新未触发** → 检查 `latest.yml` 是否与客户端版本号匹配,且 `setFeedURL()` 路径正确。 3. **签名验证失败**(Linux 通常不需代码签名,但需校验 SHA) --- ### **进阶实践** - **自定义提示**:监听 `update-available` 事件,在 UI 中显示更新进度条 ```javascript updater.on('download-progress', (progress) => { console.log(`下载进度: ${Math.floor(progress.percent)}%`); }); ``` - **增量更新**:通过配置差分更新包减小下载体积(需服务端生成 `delta.yml`) --- **安全提示**:生产环境务必启用 HTTPS 和文件哈希校验,避免中间人攻击。 --- ### **相关问题** 1. 如何为 Electron 应用生成 Linux 下的 `.AppImage` 安装包? 2. `electron-simple-updater` 在 Windows/macOS 与 Linux 的配置差异有哪些? 3. 更新失败时如何获取详细错误日志? [^1]: [electron-simple-updater 项目文档](https://gitcode.com/gh_mirrors/el/electron-simple-updater)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值