目录
一、目的
二、实现案例
三、Echart集成Grafana
四、附录
一、目的
grafana提供时序数据展示,默认提供的模板可能无法满足需求,比如我目前需要一个双层饼图,grafana只能提供最为基础的 PIE chart,而grafana提供了插件开发的功能,故可以把echart相关图表集成到grafana中获取满足自己需求的图表。
产出结果示例:
二、实现案例
案例集成:
- 数据源:时序数据库Influxdb (可自由调整,都可以兼容,比如Prometheus)
- 图表模板:echart (大部分图表应该都可以兼容)
grafana集成influxdb很容易,这边不再赘述。
简单贴一下安装过程,方便大家:
grafana安装:
grafana安装:
wget https://dl.grafana.com/oss/release/grafana-7.1.0-1.x86_64.rpm
sudo yum -y install grafana-7.1.0-1.x86_64.rpm
基本命令:
启动:
systemctl start grafana-server
systemctl restart grafana-server
查看版本:
grafana-server -v
访问:ip:3000 进入控制台,默认账号密码admin
influxdb安装:
influxdb安装:
下载 rpm 文件
wget https://dl.influxdata.com/influxdb/releases/influxdb-1.8.2.x86_64.rpm
安装
sudo yum localinstall influxdb-1.8.2.x86_64.rpm
启动 InfluxDB:
systemctl start influxdb
设为开机启动:
systemctl enable influxdb
连接 InfluxDB
( -precision 参数表明了任何返回的时间戳的格式和精度,rfc3339 是让 InfluxDB 返回 RFC339 格式(YYYY-MM-DDTHH:MM:SS.nnnnnnnnnZ)的时间戳。)
influx -precision rfc3339
创建数据库
CREATE DATABASE mydb
influxdb插入数据:
INSERT cost,name='云服务器' value=1048
INSERT cost,name='负载均衡' value=335
INSERT cost,name='物理机房' value=510
INSERT cost,name='网络带宽' value=251
INSERT cost,name='serverless' value=234
INSERT cost,name='对象存储' value=147
INSERT cost,name='其他费用' value=102
数据源这边ok了,grafana这边需要集成插件到控制台,插件下载地址( )。
插件下载完成后,需要上传到grafana插件目录,并进行构建:
#下载grafana插件开发相关node_modules
npm install
#构建yarn
yarn install
#Build plugin in development mode or run in watch mode
yarn dev
#Build plugin in production mode ,可先跳过
yarn build
源码结构图:
构建完成之后 ,重启grafana:
systemctl restart grafana-server
注意:插件开发构建过程中npm构建失败很常见,yarn构建失败,需要自己联调,一定要构建完成才能使用。
(我这边基于官方grafana插件编写构建失败拖了很长时间,服务器访问github还需要自己修改host,有时候还不成功,这个插件构建时应该没有那种问题,出现问题了一步一步走就ok,我这边都成功了)。
主要引起的原因:
nodejs版本,我这边使用最新的 v12.18.3
grafana版本,github上提示支持 6.3+ & 7.0+,我这边使用的7.1.0
执行构建命令时,root用户可能执行失败,切换下用户,文件授权也需要自行调整
三、Echart集成Grafana
直接去echart上面捞就行,如图:
获取到左边源码图,粘贴到插件funtion位置,自行修改,如图示例:
我这边编写的数据获取使用录入了的influxdb+外部ajax远程请求一个接口完成简单计算,为了试用它的ajax功能,有需要的可以贴过去试用:
if (data.series.length==0) {
return
}
let s = 1
$.ajax({
type: "GET",
async: false,
url: "http://10.200.19.43:9041/test1",
success: function (res) {
s = res
}
});
const names = data.series[0].fields.find((f) => f.type === 'number').values.buffer;
const values = data.series[1].fields.find((f) => f.type === 'number').values.buffer;
const result = values.map((a,i) => ({name: names[i], value: a*s}));
console.log(s)
console.log(result)
option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
data: ['云服务器', '负载均衡', '对象存储', '网络带宽', '阿里云', '腾讯云', '物理机']
},
series: [
{
name: '费用来源',
type: 'pie',
selectedMode: 'single',
radius: [0, '30%'],
label: {
position: 'inner',
fontSize: 14,
},
labelLine: {
show: false
},
data: [
{value: 1548, name: '阿里云'},
{value: 775, name: '腾讯云'},
{value: 679, name: '物理机'}
]
},
{
name: '费用来源',
type: 'pie',
radius: ['45%', '60%'],
labelLine: {
length: 30,
},
label: {
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
backgroundColor: '#F6F8FC',
borderColor: '#8C8D8E',
borderWidth: 1,
borderRadius: 4,
rich: {
a: {
color: '#6E7079',
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#8C8D8E',
width: '100%',
borderWidth: 1,
height: 0
},
b: {
color: '#4C5058',
fontSize: 14,
fontWeight: 'bold',
lineHeight: 33
},
per: {
color: '#fff',
backgroundColor: '#4C5058',
padding: [3, 4],
borderRadius: 4
}
}
},
data: result
}
]
};
echartsInstance.setOption(option);
至此完成一个案例echart集成gragana,结果如图:
influxdb v2.0 跨表集成案例:
console.log(data)
if (data.series.length==0) {
return
}
let s = 1
// $.ajax({
// type: "GET",
// async: false,
// url: "http://10.200.19.43:9041/test1",
// success: function (res) {
// s = res
// }
// });
//data.series.map((s) =>console.log(s.fields[1]));
const names = [];
const values = [];
const totalNames = [];
const totalValues = [];
for (var i = 0; i < data.series.length; i++) {
if(data.series[i].refId=='A'){
names.push(data.series[i].fields[1].labels.instanceType);
values.push(data.series[i].fields[1].state.calcs.lastNotNull);
} else if(data.series[i].refId=='B'){
totalNames.push(data.series[i].fields[1].labels.name);
totalValues.push(data.series[i].fields[1].state.calcs.lastNotNull);
} else if(data.series[i].refId=='C'){
names.push(data.series[i].fields[1].labels.storageClass);
values.push(data.series[i].fields[1].state.calcs.lastNotNull);
}
}
//data.series.map((s) =>(s.refId==='A'?s.fields[1].labels.instanceType:''));
const result = values.map((a,i) => ({name: names[i], value: a*s}));
const totalResult = totalValues.map((a,i) => ({name: totalNames[i], value: a*s}));
console.log(s)
console.log(result)
option = {
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)'
},
legend: {
data: ["实例", "存储"]
},
series: [
{
name: '费用来源',
type: 'pie',
selectedMode: 'single',
radius: [0, '30%'],
label: {
position: 'inner',
fontSize: 14,
},
labelLine: {
show: false
},
data: totalResult
},
{
name: '费用来源',
type: 'pie',
radius: ['45%', '60%'],
labelLine: {
length: 30,
},
label: {
formatter: '{a|{a}}{abg|}\n{hr|}\n {b|{b}:}{c} {per|{d}%} ',
backgroundColor: '#F6F8FC',
borderColor: '#8C8D8E',
borderWidth: 1,
borderRadius: 4,
rich: {
a: {
color: '#6E7079',
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#8C8D8E',
width: '100%',
borderWidth: 1,
height: 0
},
b: {
color: '#4C5058',
fontSize: 14,
fontWeight: 'bold',
lineHeight: 33
},
per: {
color: '#fff',
backgroundColor: '#4C5058',
padding: [3, 4],
borderRadius: 4
}
}
},
data: result
}
]
};
echartsInstance.setOption(option);