• home > OS > Linux > monitor >

    grafana前端源码学习笔记

    Author:zhoulujun Date:

    从grafana基本概念到目录结构到插件开发,全程学习笔记心得零散记录。


    Grafana基本概念

    • Organization:有些场景是一个grafana服务商与多个客户合作,客户之间是隔离的,所以grafana也就支持多组织。但在更多的场景下,grafana会被单独部署到某个客户环境中。在grafana中的组织下的每个用户,都可以使用属于这个组织的DataSoure和Dashboard。

    • User:一个用户可以属于一个或多个组织。在不通组织中可以被设置不同角色。Grafana也支持多样的认证方式。比如集成database,或来自外部的SQL server,或是一个LDAP server。

    • Dashboard:面板组件。panel和row汇总到了dashboard中。右上角的time picker可以控制panel的时间。dashboard能被方便的共享。可以使用Snapshot的特性,将当前的所有视图数据导出到静态的JSON文档中。dashboard也可以被打标签。

    • Row:在一个Dashboard,“行“是用来组合各个Panel的。一行有12个单元,可以将panel设置成不同的单位宽度。更不错的是,grafana在所有分辨率的屏幕下,都能适应的很好。

    • Panel:在grafana中,Panel是基础呈现块。每个Panel都提供了查询编辑器Query Editor,辅助我们从DataSource提取所展示的信息。每种Panel都有多样的配置和展现方式,它可以在Dashboard上拖拽和重绘大小。官方提供的Panel有如下:

      • Graph:可以提供折线图、柱状图等能力,可以通过Plugin添加其它图表。Singlestat如同其名,是用来展示单个字段的状态。Dashlist和Text是特殊的panel,它不连接任何Data Source。

      • Singlestat

      • Dashlist

      • Table

      • Text

    • Query Editor:查询编辑器也是数据源间不同的。编辑器可以引用Dashboard的变量,来达到动态控制panel的目的。QE也可以添加多次Query,来获取多个series。每次Query的结果,可以通过输入#xxx给下一次引用,进行更高级的查询。

    • Data Source

      • Data Source

      • Graphite

      • InfluxDB

      • OpenTSDB

      • Prometheus

      • Elasticsearch

      • CloudWatch

    Grafana所涉及的知识点

    • TypeScript 语言

    • AngularJS 框架

    • SystemJS 模块化解决方案

    • Sass css预处理语言

    • Grunt 构建工具

    • NodeJS基础

    • Grunt 能不能换成别的?

    • TypeScript 能不能换成 JavaScript?

    • AngularJS 能不能换成更高版本的 Angular 或者使用其他框架?

    前两个的答案是可以,不过作为非配置工程师,懒得折腾这么多,至于 AngularJS 1.x,涉及到了整个 Grafana 的 View 层问题,在某个论坛看到关于能不能升级的提议,大致是:「你们能不能升级到 Angular 4 啊?」「我们还在升级 Angular 2 的路上」——总之,路漫漫其修远兮,一句话就是,我们现在还得用 AngularJS 来搞定 Template。

    从《Grafana的发展历史》可知,grafana一直在迭代,但是现在感觉不会有大的改动了。

    Grafana核心源码目录结构

    public/app

    • core

      • components # 通用组件

      • controllers # 控制器

      • directives # 指令

      • filters # 过滤器

      • live # websocket

      • routers # 路由

      • services # 服务

      • utils # 工具

    • features # 功能模块

    • headers # typescript头文件

    • partials # 页面片段(相当于传统意义上的页面

    • plugins # 插件 (app/datasource/panel)

    • app.ts # app入口

    • boot.js # 启动app

    • system.conf.js # systemjs配置


    APP插件工程架构


    目录描述
    dist / build存放编译打包后的插件代码
    src插件源码目录
    src/components界面文件, 可选
    src/sasscss样式文件
    src/dashboard仪表板json文件
    src/datasource数据源插件
    src/img图像文件
    src/panel仪表板插件
    src/module.ts唯一入口文件
    src/plugin.json插件描述文件
    Gruntfile.jsGrunt任务描述
    package.json依赖包说明
    README.md说明文档

    grafana6 7 8,每个版本目录结构相差迥异,但是文件名代表的含义大体相同,只是目录结构做了调整。


    架构详解

    dist

    • grafana引入插件主要在插件目录下的dist中读取入口文件,然后将对应的插件配置引入到grafana中;

    • 前面说到的编译运行就是把src的文件以及readme复制到dist中,然后将ts文件编译生成js文件;

    • 如果有后端服务程序,也会通过makefile编译生成到该目录下;

    src/components

    该目录下存放着对应的ts文件和html文件,定义前端的基本操作;

    • html定义页面显示,可使用grafana原有的样式,详情请参考官方开发指南;

    • ts文件定义页面的页面具体操作,并可将页面通过描述嵌入到grafana的页面中;

    • ts文件中的类定义templateUrl可导入HTML文件,然后该类需在module.ts入口文件进行声明,然后在plugin.json对页面进行对应描述即可。

    src/css

    该目录存放一些自定义css样式;

    src/dashboard

    该目录存放着插件自带的仪表板;可以通过grafana制定,然后保存生成json文件,不过应注意要把json文件中的id项改为null,不然会引发Import Dashboard Error;

    src/datasource

    该目录是APP附属的数据源配置, 相当于将数据源插件嵌入到APP中;

    src/img

    该目录存放图像文件,比如图标;

    src/panel

    该目录是APP附属的仪表插件, 相当于将仪表插件嵌入到APP中;待添加

    src/module.ts

    必要文件, 文件内容解析如下(以kubernetes app为例):

    import {KubernetesConfigCtrl} from './components/config/config';
    import {ClustersCtrl} from './components/clusters/clusters';
    import {loadPluginCss} from 'app/plugins/sdk';
    
    loadPluginCss({
      dark: 'plugins/grafana-kubernetes-app/css/dark.css',
      light: 'plugins/grafana-kubernetes-app/css/light.css'
    });
    
    export {
      KubernetesConfigCtrl as ConfigCtrl,
      ClustersCtrl,
    };
    1. 首先导入component目录下的类

    2. 导入加载自定义css的类

    3. 声明自定义的css样式

    4. 声明APP使用到的类
      ConfigCtrl是grafana在配置插件时使用的控制器,将KubernetesConfigCtrl作为ConfigCtrl,该页面会在插件配置的页面中显示。

    src中的module.js文件非常重要,它是插件加载的起点文件,但是里面内容不多,主要是导入controller.js,然后导出为Ctrl。controller.js里面放了主要的js代码。

    src/plugin.json

    必要文件, 文件内容解析如下:

    {
      "type": "app",                             //声明类型:app, datasource, panel
      "name": "kubernetes",                      //插件名称
      "id": "grafana-kubernetes-app",            //插件ID,必须唯一
      "info": {                                  //相关信息
        "description": "Kubernetes app. shows data collected by Prometheus.",
        "author": {
          "name": "Grafana Labs",
          "url": "https://grafana.com/"
        },
        "keywords": ["raintank", "kubernetes", "Prometheus"],
        "logos": {                              //声明图标
          "small": "img/logo.svg",
          "large": "img/logo.svg"
        },
        "links": [                             //链接跳转
          {"name": "Grafana Labs", "url": "https://grafana.com/"},
        ],
        "version": "1.0.1",                   //版本信息
        "updated": "2018-01-18"
      },
      "includes": [                          //对插件的各部分进行引入
        {
            "type": "page",                 //页面类型
            "name": "Clusters",             //显示的名称
            "component": "ClustersCtrl",    //该页面的类
            "role": "Viewer",               //该页面的功能
            "addToNav": true,               //是否加入插件导航栏
            "defaultNav": true              //是否作为插件使能后的默认页面
        },
        {
          "type": "datasource",             //数据源类型
          "name": "kubernetes DS"           //数据源名称
        },
        {
          "type": "dashboard",             //仪表板类型
          "name": "K8s Node",              //仪表板的名称
          "path": "dashboards/k8s-node.json",         //仪表板的文职
          "addToNav": false               
        },
        {
          "type": "panel",                  //仪表类型
          "name": "Kubernetes Node Info"
        },
      ],
      "dependencies": {                    //依赖的grafana版本以及插件
        "grafanaVersion": "5.0+",   
        "plugins": []
      }
    }

    Gruntfile.js

    Grunt任务配置文件,主要架构是引入依赖插件,定义任务信息,配置需要执行的任务;

    package.json

    声明该插件需要使用到的插件和依赖,便于npm安装环境;

    Readme.md

    要求Markdown格式, 可在插件配置的页面的Readme选项卡中显示;

    Grafana插件开发

    官方样例:https://grafana.com/blog/2016/04/08/timing-is-everything.-writing-the-clock-panel-plugin-for-grafana-3.0/

    官方插件合集:https://github.com/grafana/grafana/tree/main/public/app/plugins

    具体可以参看 https://github.com/grafana/simple-json-datasource,最简单的 Datasource 主要有以下模块

    grafana插件Datasource架构图

    在Grafana中,如果dist文件夹存在,grafana会从dist文件夹加载代码,忽略src文件夹内容。先忽略dist文件。

    插件目录


    ├── src

        ├── css

        ├── img

        │   └── server-logo.png

        ├── module

        │   ├── annotationsQueryCtrl.js

        │   ├── configCtrl.js

        │   ├── datasource.js

        │   ├── queryCtrl.js

        │   └── queryOptionsCtrl.js

        ├── module.js

        ├── page

        │   ├── annotationsQuery.html

        │   ├── config.html

        │   ├── query.html

        │   └── queryOptions.html

        └── plugin.json

    ├── Gruntfile.js

    ├── README.md

    ├── package.json

    plugin.json文件

    在plugin.json文件中,有两个关于datasource特定的设置,其中一个必须为true

    • "metrics": true,  // 是否在panel中支持metrics

    • "annotations": false,  // 在dashboard中支持annotations查询

    plugin.json保存plugin的元数据,Grafana在扫描插件目录时查找plugin.json文件,并自动注册插件,文件中的内容会被提取并封装成对象使用。

    module.js

    module.js文件非常重要,它是插件加载的起点文件。与Grafana的其余部分进行交互,插件文件需要导出以下5个模块:

    • Datasource  // Required

    • QueryCtrl  // Required

    • ConfigCtrl  // Required

    • QueryOptionsCtrl  // 

    • AnnotationsQueryCtrl  //

    所以在module中,负责导出这五个模块。 module.js文件代码示例:

    import GenericAnnotationsQueryCtrl from './module/annotationsQueryCtrl';
    import GenericConfigCtrl from './module/configCtrl';
    import GenericDatasource from './module/datasource';
    import GenericQueryCtrl from './module/queryCtrl';
    import GenericQueryOptionsCtrl from './module/queryOptionsCtrl';
    
    export {
        GenericAnnotationsQueryCtrl as AnnotationsQueryCtrl,
        GenericConfigCtrl as ConfigCtrl,
        GenericDatasource as Datasource,
        GenericQueryCtrl as QueryCtrl,
        GenericQueryOptionsCtrl as QueryOptionsCtrl
    };

    module文件夹

    ├── annotationsQueryCtrl.js

    ├── configCtrl.js

    ├── datasource.js

    ├── queryCtrl.js

    └── queryOptionsCtrl.js

    这五个文件对应module.js需要导出的五个模块,将来会被转换为五个angular的控制器。

    page文件夹

    ├── annotationsQuery.html

    ├── config.html

    ├── query.html

    └── queryOptions.html

    这四个文件对应module文件夹下annotationsQueryCtrl、configCtrl、queryCtrl、queryOptionsCtrl四个模块需要绑定的页面模板, datasource模块不需要页面模板。


    Datasource插件-数据源模件

    与Grafana的其余部分进行交互,插件文件需要导出以下5个模块:

    • Datasource  // Required

    • QueryCtrl  // Required

    • ConfigCtrl  // Required

    • QueryOptionsCtrl  // 

    • AnnotationsQueryCtrl  //

    constructor函数

    datasource插件与数据源通信,并将数据转换为时间序列。

    数据源有以下功能:

    • query(options)  // 用于panel查询数据

    • testDatasource()  // 用于自定义数据源的页面,测试当前配置的数据源是可用的

    • annotationQuery(options) // 用于dashboard获取注释信息

    • metricFindQuery(options) // used by query editor to get metric suggestions.

    constructor函数传入的参数有:

    constructor(instanceSettings, $q, backendSrv, templateSrv) {}
    // instanceSettings对象为:
    {
      id: 5,
      jsonData: {
        keepCookies: [],
        tlsAuth: false,
        tlsAuthWithCACert: false,
        tlsSkipVerify: false,
      },
      meta: {
        alerting: false,
        annotations: true,
        baseUrl: "public/plugins/grafana-server-datasource",
        dependencies: {
          grafanaVersion: "3.x.x",
          plugins: [],
        },
        id: "grafana-server-datasource",
        includes: null,
        info: {
          author: {
            name:"liuchunhui",
            url:"https://grafana.com",
          },
          description: "代理服务端作为数据源",
          links: [
            {name: "Github", url: ""},
            {name: "MIT License", url: ""}
          ],
          logos: {
            large:"public/plugins/grafana-server-datasource/img/server-logo.png",
            small:"public/plugins/grafana-server-datasource/img/server-logo.png"
          },
         screenshots:null
         updated:"2018-04-23"
         version:"1.0.0"
        },
        metrics: true,
       module: "plugins/grafana-server-datasource/module",
       name: "代理服务端",
       routes: null,
       type: "datasource",
      }
      name:"代理服务端数据源",
      type:"grafana-server-datasource",
      url:"/api/datasources/proxy/5",
    }
    // $q 是个函数
    // backendSrv对象为:
    {
      $http: ƒ p(e),
      $q: ƒ M(t),
      $timeout: ƒ o(o,s,u),
      HTTP_REQUEST_CANCELLED: -1,
      alertSrv: {
       $rootScope: object,
       $timeout: ƒ o(o,s,u)
       list: []
      }
      contextSrv: {
        isEditor: true,
        isGrafanaAdmin: true,
        isSignedIn: true,
        sidemenu: true,
        sidemenuSmallBreakpoint: false,
       user: {  // 当前登录的用户信息
          email:"admin@localhost",
         gravatarUrl:"/avatar/46d229b033af06a191ff2267bca9ae56",
         helpFlags1:0,
         id:1,
         isGrafanaAdmin:true,
         isSignedIn:true,
         lightTheme:true,
         locale:"zh-CN",
         login:"admin",
         name:"admin",
         orgCount:1,
         orgId:1,
         orgName:"Main Org.",
         orgRole:"Admin",
         timezone:"browser",
        },
        version:"5.0.1",
      },
      inFlightRequests:{},
      noBackendCache:true,
    }
    // templateSrv对象为:
    {
      builtIns: {
        __interval:{text: "1s", value: "1s"},
        __interval_ms:{text: "100", value: "100"}
      },
      grafanaVariables: {},
      index:{},
      regex:/\$(\w+)|\[\[([\s\S]+?)(?::(\w+))?\]\]|\${(\w+)(?::(\w+))?}/g
    }


    query函数

    真正去查询数据时要调用的函数。官方提供的数据源有两种不同的结果,time series和table,目前grafana官方所有数据源和面板都支持time series格式,table格式仅由InfluxDB数据源和表格面板支持。

    我们开发插件时可以自定义类型值,但是要做到开发的datasource插件也适配官方自带的panel插件,那么定义datasource返回的数据格式和grafana的一致。

    datasource.query的time series类型响应格式:

    [{
       "target":"upper_75",
        "datapoints":[
          [622, 1450754160000],
          [365, 1450754220000]
       ]
    }, {
        "target":"upper_90",
        "datapoints":[
          [861, 1450754160000],
          [767, 1450754220000]
        ]
    }]

    datasource.query的table类型响应格式:

    [{
       "columns": [{
          "text": "Time",
            "type": "time",
            "sort": true,
            "desc": true,
       }, {
            "text": "mean",
        }, {
            "text": "sum",
        }],
        "rows": [[
          1457425380000,
            null,
            null
       ], [
          1457425370000,
            1002.76215352,
            1002.76215352
       ]],
        "type": "table"
    }]

    传递给datasource.query函数的请求对象:

    {
       "range": {
          "from": moment,  // 全局时间筛选起始日期
          "raw": {from: "now-7d", to: "now"},
          "to": moment,  // 全局时间筛选结束日期
       },
        "rangeRaw": {
          "from": "now-7d",
          "to": "now",
        },
       "interval": "15m",
        "intervalMs": 900000,
       "targets": [{  // 定义的查询条件们
          "refId": "A",
          "target": "upper_75" 
       }, {
          "refId": "B", 
          "target": "upper_90" 
       }],
       "format": "json",
       "maxDataPoints": 2495, //decided by the panel
        "cacheTimeout": undefined,
        "panelId": 2,
        "timezone": "browser"
    }

    query函数示例:

    query(options) {  // 返回的结果数据,panel插件会通过监听'data-received'获取到
        
        const params = {  // 封装http请求参数
            from: options.range.from.format('x'),
            to: options.range.to.format('x'),
            targets: options.queries,
        };
    
        return this.doRequest({  // 发起http请求并返回结果
            url: this.url + '/card-data',  // 要制定公共接口规范
            method: 'POST',
            data: params
        });
    }
    
    
    doRequest(options) {
        options.withCredentials = this.withCredentials;
        options.headers = this.headers;
        return this.backendSrv.datasourceRequest(options);  // datasourceRequest()是grafana提供的请求datasource函数
    }


    testDatasource函数

    当用户在添加新数据源时点击Save&Test按钮,详细信息首先保存到数据库,然后testDatasource调用数据源插件中定义的函数。

    此函数向数据源发出查询,验证数据源是否配置的正确可用,确保当用户在新仪表板中编写查询时,数据源已正确配置

    函数示例:

    /**
     * 当保存并测试数据源时会调用该函数
     * 测试数据源是否正常工
     * return { status: "", message: "", title: "" }
     */
    testDatasource() {
        return this.doRequest({
            url: this.url + '/',
            method: 'GET',
        }).then(response => {
            if (response.status === 200) {
                return { status: "success", message: "Data source is working", title: "Success" };
            }
        });
    }


    annotationQuery函数

    注释查询,传递给datasource.annotationQuery函数的请求对象:

    {
       "range": { 
          "from": "2016-03-04T04:07:55.144Z", 
          "to": "2016-03-04T07:07:55.144Z" },
       "rangeRaw": { 
          "from": "now-3h", 
          "to": "now" 
       },
       "annotation": {
          "datasource": "generic datasource",
          "enable": true,
          "name": "annotation name"
       }
    }

    datasource.annotationQuery的预期结果:

    [{
       "annotation": {
          "name": "annotation name", //should match the annotation name in grafana
           "enabled": true,
           "datasource": "generic datasource",
        },
        "title": "Cluster outage",
        "time": 1457075272576,
        "text": "Joe causes brain split",
        "tags": "joe, cluster, failure"
    }]

    可以使用grafana平台的数据库存取'注释'

    metricFindQuery 函数

    暂时不知

    ConfigCtrl模块

    当用户编辑或创建此类型的新数据源时,该类将被实例化并视为Angular控制器。 该类需要一个静态模板或templateUrl变量,该模板或变量将被渲染为此控制器的视图。 ConfigCtrl类中的this对象内容为:

    {
      current: {
        name: "代理服务端数据源",  // 数据源名称
        isDefault: true,  // 是否是默认
        type: "grafana-server-datasource",  // 数据源插件的id值
        url: "http://localhost:3001",  // HTTP:数据源对应的url
        access: "proxy",  // HTTP:连接数据源类型,有'direct'和'proxy'两种类型可选
        basicAuth: true,  // Auth:Basic Auth选项
        basicAuthUser: "basic auth user",  // Basic Auth Details:User选项,当basicAuth为true时有效
        basicAuthPassword:"basic auth password",  // Basic Auth Details:Password选项,当basicAuth为true时有效
        withCredentials: true,  // Auth:With Credentials选项
        jsonData: {
         tlsAuth: true,  // Auth:TLS Client Auth选项
          tlsAuthWithCACert: true,  // Auth: With CA Cert选项
          tlsSkipVerify: true,  // Auth: Skip TLS Verification (Insecure)选项值
          keepCookies: ["Advanced Cookoe"],  // Advanced HTTP Settings: cookie的白名单
        },
        secureJsonData: {
          tlsCACert: "TLS Auth CA Cert",  // TLS Auth Details:CA Cert选项,当jsonData下的tlsAuthWithCACert值为true时有效
          tlsClientCert: "TLS Auth Client Cert",  // TLS Auth Details:Client Cert选项,当jsonData下的tlsAuth值为true时有效
          tlsClientKey: "TLS Auth Client Key",  // TLS Auth Details:Client Key选项,当jsonData下的tlsAuth值为true时有效
        },
        secureJsonFields: {},
      },
      meta: {
        baseUrl: "public/plugins/grafana-server-datasource",
        defaultNavUrl: "",
        dependencies: {
          grafanaVersion: "3.x.x",
          plugins: [],
        },
        enabled: false,
        hasUpdate: false,
        id: "grafana-server-datasource",
        includes: null,
        info: {  // plugin.json中配置的信息
         author: {
            name: "liuchunhui", 
            url: "https://grafana.com"
          },
          description: "代理服务端作为数据源",
          links: [
            {name: "Github", url: ""},
            {name: "MIT License", url: ""}
          ],
          logos: {
          large:"public/plugins/grafana-server-datasource/img/server-logo.png",
            small:"public/plugins/grafana-server-datasource/img/server-logo.png"
          },
          screenshots:null,
          updated:"2018-04-23",
          version:"1.0.0"
        },
        jsonData: null,
        latestVersion: "",
        module: "plugins/grafana-server-datasource/module",
        name: "代理服务端",
        pinned: false
        state: "",
        type: "datasource",
    }

    模板页面中使用grafana封装的angular组件,传入this的current对象,实现HTTP、Auth两个模块的定义:

    <datasource-http-settings current="ctrl.current"></datasource-http-settings>


    QueryCtrl模块

    一个JavaScript类,当用户在面板中编辑指标时,它将被实例化并作为Angular控制器处理

    该类必须从app/plugins/sdk.QueryCtrl类继承

    grafana提供的sdk中包含三种插件共我们使用:

    import { PanelCtrl } from 'app/features/panel/panel_ctrl';

    import { MetricsPanelCtrl } from 'app/features/panel/metrics_panel_ctrl';  // 自动添加"Metrics"度量标准查询编辑

    import { QueryCtrl } from 'app/features/panel/query_ctrl';

    该类需要一个静态模板或templateUrl变量,该模板或变量将被渲染为此控制器的视图。

    当用户在panel面板下,切回到Metrics模块时,会初始化该类。所以我们可以在构造函数中做一些我们自己的事情。比如获取指标维度列表,作为用户筛选的展示条件。

    import { QueryCtrl } from 'app/plugins/sdk';
    export default class GenericQueryCtrl extends QueryCtrl {
        constructor($scope, $injector) {
            super($scope, $injector);
    
            // 获取参数列表请求
            this.requestParams().then(response => {
                const targets = response.data.target;
                this.options = response.data.options;
                this.text = response.data.text;
                this.keys = Object.keys(targets);
    
                for (let key in targets) {
                    this.target[key] = this.target[key] || targets[key];
    
                }
            });
        }
        requestParams() {  // 请求获取参数列表
            const params = {
                header: {
                    'Content-Type': 'application/json'
                },
                method: 'GET',
                retry: 0,
                url: this.datasource.url + '/param-list'
            };
            return this.datasource.backendSrv.datasourceRequest(params);  // 使用grafana提供的http请求函数
        }
        onChangeInternal() {  // 刷新面板
            this.panelCtrl.refresh(); // grafana自带方法使面板更新数据
        }
    
        toggleEditorMode() {  // 是否开启编辑模式
            this.target.rawQuery = !this.target.rawQuery;
        }
    }
    
    GenericQueryCtrl.templateUrl = './page/query.html';

    QueryCtrl控制器的query.html模板:

    <query-editor-row query-ctrl="ctrl" has-text-edit-mode="true">
        <div class="gf-form"
             ng-if="!ctrl.target.rawQuery"
             ng-repeat="key in ctrl.keys">
            <span class="gf-form-label width-7">
                {{ctrl.text[key]}}
            </span>
            <select class="gf-form-input width-25"
                    ng-model="ctrl.target[key]"
                    ng-change="ctrl.onChangeInternal()">
                <option ng-repeat="option in ctrl.options[key]"
                        value="{{option.name}}">
                    {{option.desc}}
                </option>
            </select>
        </div>
        <div ng-if="ctrl.target.rawQuery">
            <textarea class="gf-form-input" rows="5" spellcheck="false" ng-blur="ctrl.onChangeInternal()" />
        </div>
    </query-editor-row>

    <query-editor-row query-ctrl="ctrl">标签的内容会加入到Add Query模板中,标签中的has-text-edit-mode="true"属性,能开启Toggle Edit Mode功能。

    QueryCtrl控制器中的target.rawQuery参数,标记着两种编辑模式的切换,但是这两种模式需要写代码定义。

    AnnotationsQueryCtrl模块

    当用户在datasource的模板菜单中选择这种类型的数据源时,将被实例化并作为Angular控制器处理的JavaScript类。

    此类需要一个静态模板或templateUrl变量,该模板或变量将被渲染为此控制器的视图

    绑定到此控制器的字段随后会发送到数据库对象annotationQuery函数。

    在开发插件时能自定义dashboard的Built in query的条件。

    AnnotationQueryCtrl代码:

    export default class GenericAnnotationsQueryCtrl {}
    GenericAnnotationsQueryCtrl.templateUrl = './page/annotationsQuery.html';

    annotationsQuery.html代码:

    <h5 class="section-heading">注解查询条件设定</h5>
    <div class="gf-form-group">
        <div class="gf-form">
            <input type="text" class="gf-form-input" ng-model='ctrl.annotation.query' placeholder="" />
        </div>
    </div>


    Panel插件-面板模块

    和上面数据源模块一样,这么就简单过一下

    plugin.json文件格式

    {
        id: '',  // 重要!!!插件的唯一名称,不能重复!!!id命名约定为 [github username/org]-[plugin name]-[datasource|app|panel]
        type: 'panel',  // 插件类型,有panel/datasource/app
        name: 'Clock',  // 插件名称
        info: {
            description: 'Clock panel for grafana',
            author: {
                "name": "Raintank Inc.",
                "url": "http://raintank.io"
            },
            keywords: ["clock", "panel"],
            logos: '',  // 项目的logo
            version: '1.0.0',
            updated: '2015-03-24',
        },
        dependencies: {
            grafanaVersion: '4.x.x',  // 该插件需要的grafana后端版本
            plugins: [],  // 该插件需要的插件的版本
        }
    }


    grafana提供的监听函数有:

    • init-edit-mode:  // panel的进入编辑状态时的钩子函数

    • panel-teardown:  // clean up时的钩子函数

    • data-received:  //在panel接收到数据或更细数据时的钩子函数

    • data-snapshot-load:  // 在快照模式下载入数据时的钩子函数



    参考资料:

    Grafana学习笔记 https://www.jianshu.com/p/648069dd3ad1

    Grafana插件开发------APP插件开发 https://blog.csdn.net/mr_black_man/article/details/102831891

    Grafana的Datasource插件开发实践二 https://juejin.cn/post/6844903598858436615

    Grafana Panel插件开发实践 https://juejin.cn/post/6844903589119262728

    Grafana 插件开发入门 - 前端视角(React) https://blog.csdn.net/Candy_home/article/details/102665934



    转载本站文章《grafana前端源码学习笔记》,
    请注明出处:https://www.zhoulujun.cn/html/OS/Linux/monitor/8738.html