Exporter实现
server.js中注册路由:
app.use('/metrics',monitorRouter)
monitor.js完成业务逻辑:
const express = require('express')
const Prometheus = require('prom-client')
const DashboardRepository = require("../repository/dashboard.repository");
const DashboardController = require('../controller/dashboard.controller')
const Util = require("../utils/commonFunction")
const labelNames = [
'id',
'taskName',
'station',
'model',
'sn',
]
const monitorRouter = express.Router()
const register = new Prometheus.Registry()
const injectSuccessRate = new Prometheus.Gauge({
name:'inject_success_rate',
help:'Inject success rate'
})
const injectSuccessNum = new Prometheus.Gauge({
name:'inject_success_num',
help:'Inject success number'
})
const injectFailedNum = new Prometheus.Gauge({
name:'inject_failed_num',
help:'Inject failed number'
})
const injectWarningNum = new Prometheus.Gauge({
name:'inject_warning_num',
help:'Inject warning number'
})
const averageInjectRate = new Prometheus.Gauge({
name:'inject_average_rate',
help:'Average inject rate'
})
const taskStatus = new Prometheus.Gauge({
name:'task_status',
help:'Task status',
labelNames
})
const taskProgress = new Prometheus.Gauge({
name:'task_progress',
help:'Progress',
labelNames
})
const taskBeginTime = new Prometheus.Gauge({
name:'task_begin_time',
help:'Begin Time',
labelNames
})
const taskEndTime = new Prometheus.Gauge({
name:'task_end_time',
help:'End Time',
labelNames
})
const taskDataRate = new Prometheus.Gauge({
name:'task_data_rate',
help:'Data Rate',
labelNames
})
const taskFileSize = new Prometheus.Gauge({
name:'task_file_size',
help:'File Size',
labelNames
})
const taskExpectDuration = new Prometheus.Gauge({
name:'task_expect_duration',
help:'Expect Duration',
labelNames
})
const taskDuration = new Prometheus.Gauge({
name:'task_duration',
help:'Duration',
labelNames
})
register.registerMetric(injectSuccessRate)
register.registerMetric(injectSuccessNum)
register.registerMetric(injectFailedNum)
register.registerMetric(injectWarningNum)
register.registerMetric(averageInjectRate)
register.registerMetric(taskStatus)
register.registerMetric(taskProgress)
register.registerMetric(taskBeginTime)
register.registerMetric(taskEndTime)
register.registerMetric(taskDataRate)
register.registerMetric(taskFileSize)
register.registerMetric(taskExpectDuration)
register.registerMetric(taskDuration)
monitorRouter.get('/',async(req,res)=>{
res.set('Content-Type',Prometheus.register.contentType);
const data = await DashboardController.getUploadStatics()
const {successRate,successNum,failedNum,warningNum,injectRate} = data;
injectSuccessRate.set(+successRate);
injectSuccessNum.set(+successNum);
injectFailedNum.set(+failedNum);
injectWarningNum.set(+warningNum);
averageInjectRate.set(+injectRate);
let tasks = await DashboardRepository.getAllUploadTasks();
tasks = await DashboardController.generateTaskResult(tasks);
async function processTasks() {
for (const task of tasks) {
let {
id,taskName,station,model,
sn,progress,status,beginTime,
endTime,expectedDuration,spendTime,dataRate,fileSize
} = task;
await taskStatus.labels({
id,
taskName,
station,
model,
sn,
}).set(+status);
await taskProgress.labels({
id,
taskName,
station,
model,
sn,
}).set(+progress)
const timeBegin = new Date(beginTime);
const timeEnd = new Date(endTime);
await taskBeginTime.labels({
id,station,model,sn,taskName
}).set(timeBegin.getTime());
await taskEndTime.labels({
id,station,model,sn,taskName
}).set(timeEnd.getTime());
await taskDataRate.labels({
id,station,model,sn,taskName
}).set(+dataRate)
await taskFileSize.labels({
id,station,model,sn,taskName
}).set(+fileSize)
await taskExpectDuration.labels({
id,station,model,sn,taskName
}).set(Util.getDurationSeconds(expectedDuration))
await taskDuration.labels({
id,station,model,sn,taskName
}).set(Util.getDurationSeconds(spendTime))
}
}
await processTasks();
register.metrics().then(data=>res.status(200).send(data))
})
module.exports = monitorRouter
访问后端地址+"/metrics"即可访问exporter数据。
注意:设置的labels尽量设置为不会发生变化的常量,Prometheus中会将(指标名+其labels)标识为一个时间序列,当labels发生变化后,则成为一个新的时间序列,在后面grafana的聚合展示中会出现问题。
部署Prometheus
prometheus的yaml文件
# my global config
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
# scrape_timeout is set to the global default (10s).
# Alertmanager configuration
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
- job_name: "prometheus"
# metrics_path defaults to '/metrics'
# scheme defaults to 'http'.
static_configs:
- targets: ["localhost:9090"]
- job_name: "inject_task_monitor"
static_configs:
- targets: ["10.51.22.248:32235"]
Grafana配置
效果
表格配置
Query
Transform
Convert field type
顾名思义,是用来改变指标数据类型的;因为项目需要以ID倒序,因此需要将ID的数据类型改为Number
Group by
以ID进行分组:
Organize fields
重写排列表格的列:
Sort by
以ID倒序:
All & Overrides
依据项目需求自行配置:
其他
- 部署方式不在本文展开,依据需求部署;
- 每次更改完grafana配置后自己的保存JSON,别白干了
- Grafana的可玩性真的很高,作为一名前端er,不得不感慨,他们前端太强了~