Grafana的插件开发
Grafana Panel Plugin 开发
Grafana 插件开发
上⼀次分享提到过Grafana的插件氛围三种类型(Panel, Datasource, App),这⼀次主要记录Panel类型的插件开发.
0. 起⼿式
根据官⽹的描述, 插件包⼀般放在/var/lib/grafana/plugins或者data/plugins(相对Grafana源码⽬录). 前者是⽣产环境, 后者是开发环境. 所以我们这⼀次选择后者, 毕竟⼀会⼉要从源码修改Grafana的前端代码, 然后启动go语⾔编写的后端.
基础知识准备:
angularjs, systemjs, typescript, jquery, echarts, grunt, nodejs and golang.
1. ⽬录结构
先把官⽹上说明需要的⽂件⽬录加上.
1. johnnyb-awesome-datasource
2. |-- dist # 存放编译打包后的插件代码
3. |-- spec # 测试代码
4. | |-- datasource_spec.js
5. | |-- query_ctrl_spec.js
6. | |-- test-main.js
7. |-- src # 插件源码
8. | |-- img # 需要的图⽚, ⽐如LOGO, 可选
9. | | |-- logo.svg
10. | |-- partials # 界⾯⽂件, 可选
11. | | |-- annotations.editor.html
12. | | |-- config.html
13. | | |-- query.editor.html
14. | |-- datasource.js
15. | |-- module.js # 唯⼀⼊⼝⽂件
16. | |-- plugin.json # 插件描述⽂件
17. | |-- query_ctrl.js
18. |-- Gruntfile.js # Grunt任务
19. |-- LICENSE
20. |-- package.json
21. |-- README.md # 这也会显⽰在插件说明中
README.md: The only difference from how GitHub renders markdown is that html is not allowed.
实际上并不需要严格按照上述⽬录存放⽂件, 关键点在于: 插件⽬录下需要有src/, dist/. src/中需要有module.js和plugin.json. 其他开⼼就好.所以实际上, 我的⽬录结构是这样:
1. practice-panel
2. |-- dist # 存放编译打包后的插件代码
3. |-- src # 插件源码
4. | |-- partials # 界⾯⽂件, 可选
5. | | |-- module.html
6. | | |-- module.editor.html
7. | |-- module.js # 唯⼀⼊⼝⽂件
8. | |-- plugin.json # 插件描述⽂件
9. | |-- controller.js # 分离出来的Controller, 也可全部放在module.js⾥⾯
10. |-- Gruntfile.js # Grunt任务描述
11. |-- package.json
12. |-- README.md
2. 插件描述⽂件(.json)
然后来认识⼀个⽂件, 这个⽂件是⽤来描述插件的. 包括插件的唯⼀标识, 名字, 作者, 版本等等. 全⽂是这样的:
1. {
2. "id": "",
3. "type": "",
4. "name": "",
5. "info": {
6. "description": "",
7. "author": {
8. "name": "",
9. "url": ""
10. },
11. "keywords": [],
12. "logos": [
13. "small": "",
14. "large": ""
15. ],
16. "version": ""
17. },
18. "dependencies": {
19. "grafanaVersion": "",
20. "plugins": []
21. }
22. }
具体的含义, 参考附录中的官⽅说明链接. 本次的内容参考源码⽂件.
3. ⼊⼝⽂件
这基本上就是约定, Grafana会从插件包的dist/第⼀个读取的⽂件就是module.js⽂件. 不管⽤什么语⾔编写, 最终都要保证dist/module.js可读.
4. 可⽤依赖资源
Grafana的前端模块化⽅案采⽤的. 如果熟悉任何⼀种模块化⽅案都⾏, 这⾥的影响并不是很⼤, 除了需要添加依赖资源. 在插件开发过程中,开发者是⽆法添加任何依赖资源的. 因为插件是作为Grafana前
端整体的⼀部分在运⾏. 所有的资源配置都写在Grafana源码⽬录
的public/f.js⽂件中, 资源都放在public/vendor/⽬录中.
默认可⽤资源如下:
1. virtual-scroll
2. mousetrap
3. remarkable
4. tether
5. eventemitter3
6. tether-drop
7. moment
8. jquery
9. lodash-src
10. lodash
11. angular
12. bootstrap
13. angular-route
14. angular-sanitize
15. angular-ui
16. angular-strap
17. angular-dragdrop
18. angular-bindonce
19. spectrum
20. bootstrap-tagsinput
21. jquery.flot
22. jquery.flot.pie
23. jquery.flot.selection
go语言开发环境搭建24. jquery.flot.stack
25. jquery.flot.stackpercent
26. jquery.flot.time
27. sshair
28. jquery.flot.fillbelow
29. jquery.flot.gauge
30. d3
31. jquery.flot.dashes
是的, 像D3, jquery, moment, lodash这些⾮常有⽤的图表基础库都有了, 甚⾄很贴⼼的连AngularJS全家桶都有. 美中不⾜的是AngularJS版本偏低: 1.6.1.
但这⼀次练习, 我们要⽤echarts来构建图表. 很遗憾, Grafana没有这项资源. 所以总共需要修改⼆个地⽅.
将echarts.min.js放⼊public/vendor/⽬录
修改public/f.js⽂件, 在paths节点中添加代码: 'echarts': 'vendor/echarts.min.js', 上下⽂看起来像这样:
1. 'tether-drop': 'vendor/npm/tether-drop/dist/js/drop.js',
2. 'moment': 'vendor/moment.js',
3. 'echarts': 'vendor/echarts.min.js',
4. 'jquery': 'vendor/jquery/dist/jquery.js',
5. 开始编码
MetricsPanelCtrl类
准备⼯作基本完成了, 但是编码之前, 需要认识⼀个类: MetricsPanelCtrl. 这个类的源码⽂件位于Grafana源码⽬录
下public/app/features/panel/metrics_panel_ctrl.ts. MetricsPanelCtrl类继承⾃PanelCtrl类, 是我们完成本次Panel类型插件开发必须要⽤到的.它主要是解决了以下三个问题:
1. 在进⼊编辑状态后, 使metrics Tab成为默认⾯板.
1. constructor($scope, $injector) {
2. super($scope, $injector);
3. // make metrics tab the default
4. this.editorTabIndex = 1;
5. // ... other code
6. }
2. 订阅事件:
1. ('refresh', MetricsPanelRefresh.bind(this));
2. ('init-edit-mode', InitMetricsPanelEditMode.bind(this));
3. ('panel-teardown', PanelTearDown.bind(this));
3. 提供设置数据源后的响应:
1. setDatasource(datasource) {
2. // ... other code
3.
4. this.panel.datasource = datasource.value;
5. this.datasourceName = datasource.name;
6. this.datasource = null;
7. fresh();
8. }
插件事件
因为⽂档中并⽆特别描述, 所以以下是已知的插件⽀持的事件:
refresh can be used to response when refresh button was clicked.
init-edit-mode can be used to add tabs when editing a panel
panel-teardown can be used for clean up
data-received is an event in that is triggered on data refresh and can be hooked into
data-snapshot-load is an event triggered to load data when in snapshot mode.
data-error is used to handle errors on dashboard refresh.
编写⼀个controller.js
Controller类必须实现link⽅法或者init⽅法. 这是Grafana的插件机制决定的. 与此同时, Controller的实例对象也将作为AngularJS组件的上下⽂对象存在.
1. // app/core/directives/plugin_component.ts
2. function getPluginComponentDirective(options) {
3. // other code
4. return function() {
5. return {
6. // other code
7. link: (scope, elem, attrs, ctrl) => {
8. if (ctrl.link) {
9. ctrl.link(scope, elem, attrs, ctrl);
10. }
11. if (ctrl.init) {
12. ctrl.init();
13. }
14. }
15. }
16. }
17. }
⽽这个函数是作为AngularJS的指令处理函数存在的. 所以我们的controller.js看起来⾄少应该是这样的:
1. import { MetricsPanelCtrl } from 'app/plugins/sdk';
2.
3. export class Controller extends MetricsPanelCtrl {
4. constructor() {
5. // initialize
6. // subscribe events
7. }
8.
9. link(scope, elem, attrs, ctrl) {
10. // impelement linking
11. }
12. }
完整实现细节请参考源码⽂件.
是的, 此时还没有界⾯. 在编写界⾯之前, 我们先了解⼀下插件的⼆种状态.
6. 插件状态
插件有⼆种状态, ⼀种是只读状态, ⼀种是编辑状态. 只读状态就是打开⼀个dashboard时各个Panel表现的状态. 编辑状态是点击”Edit”之后, 进⼊的可以影响数据源的状态. 我们需要分别为这⼆种状态编写页⾯.
完整实现细节参考源码⽂件.
7. HTML + CSS

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。