目录

一、目的

二、实现案例

三、Echart集成Grafana

四、附录


一、目的

grafana提供时序数据展示,默认提供的模板可能无法满足需求,比如我目前需要一个双层饼图,grafana只能提供最为基础的 PIE chart,而grafana提供了插件开发的功能,故可以把echart相关图表集成到grafana中获取满足自己需求的图表。

产出结果示例:

grafana通过java api设置数据源 grafana 自定义数据源_ajax

二、实现案例

案例集成:

  • 数据源:时序数据库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通过java api设置数据源 grafana 自定义数据源_监控类_02

构建完成之后 ,重启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上面捞就行,如图:

grafana通过java api设置数据源 grafana 自定义数据源_linux_03

 获取到左边源码图,粘贴到插件funtion位置,自行修改,如图示例:

grafana通过java api设置数据源 grafana 自定义数据源_ajax_04

 我这边编写的数据获取使用录入了的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,结果如图:

grafana通过java api设置数据源 grafana 自定义数据源_监控类_05

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);