基于腾讯云监控 API 的 Grafana App 插件开发

Tencent Cloud Monitor App

Grafana 是一个开源的时序性统计和监控平台,支持例如 elasticsearch、graphite、influxdb 等众多的数据源,并以功能强大的界面编辑器著称,允许您对指标进行查询、可视化展示、设置告警等操作,以及自定义配置仪表盘。

Grafana 已经拥有一个强大的贡献者和插件开发者社区。开发者社区提供了三种类型的插件:

  • Panel Plugin: 针对图形展示的面板插件;
  • Datasource Plugin: 针对数据源的插件;
  • App Plugin: 针对完整应用的插件,通常由 Panel Plugin,Datasource Plugin 以及 Dashboards 模板组成;

Tencent Cloud Monitor App 的目录结构

本文主要介绍的是 App Plugin 的开发过程以及相关的代码组织。基于腾讯云云监控 API 的 Tencent Cloud Monitor App 插件(TencentCloud/tencentcloud-monitor-grafana-app),主要由两部分组成: Datasource Plugin 和 Dashboards 模板组成,代码的目录结构如下:

.
├── CHANGELOG.md
├── LICENSE
├── README.md
├── dist                                        // 文件夹,文件夹 src 打包后的代码
├── package.json
├── src
│   ├── components
│   │   ├── config.html
│   │   └── config.ts
│   ├── dashboards                              // Dashboards 典型模板存放
│   │   ├── example_cdb_dashboard.json
│   │   └── example_cvm_dashboard.json
│   ├── datasource                              // Datasource Plguin 代码
│   │   ├── __mocks__
│   │   │   └── core_module.ts
│   │   ├── common
│   │   │   ├── constants.ts
│   │   │   └── sign.ts
│   │   ├── components                          // 自定义的 Angular 组件
│   │   │   ├── custom_select_dropdown.ts
│   │   │   └── multi_condition.ts
│   │   ├── css
│   │   │   └── query_editor.css
│   │   ├── config.ctrl.ts                       // ConfigCtrl 模块
│   │   ├── datasource.ts                        // Datasource 模块
│   │   ├── query.ctrl.ts                        // QueryCtrl 模块
│   │   ├── img
│   │   │   └── tencent-cloud.svg
│   │   ├── partials                             // Datasource Plugin 中的 html 页面
│   │   │   ├── config.html                      // config.ctrl.ts 对应的 html
│   │   │   ├── query.editor.html                // query.ctrl.ts 对应的 html
│   │   ├── module.ts                            // Datasource Plguin 的 module.ts
│   │   ├── plugin.json                          // Datasource Plguin 的 module.ts
│   │   ├── specs                                // 测试用例文件夹
│   │   │   ├── tc_monitor_cdb_datasource.test.ts
│   │   │   └── tc_monitor_cvm_datasource.test.ts
│   │   └── tc_monitor                           // 云监控相关的产品
│   │       ├── cdb
│   │       │   ├── datasource.ts
│   │       │   ├── query.ts
│   │       │   └── query_def.ts
│   │       ├── cvm
│   │       │   ├── datasource.ts
│   │       │   ├── query.ts
│   │       │   └── query_def.ts
│   │       └── index.ts
│   ├── image                                    // 文件夹,存放README.md 中图片
│   ├── img
│   │   └── tencent-cloud.svg
│   ├── module.ts                                // App Plguin 的 module.ts
│   └── plugin.json                              // App Plugin 的 plugion.json
├── jest.config.js                               // jest 框架的配置信息
├── tsconfig.jest.json
├── tsconfig.json
├── tslint.json
├── webpack.config.analyze.js
├── webpack.config.js
└── webpack.config.prod.js
复制代码

在每个 Plugin 开发中存在两个重要的配置文件: plugin.jsonmodule.ts

plugin.json

plugin.json(Required): 用于描述插件的相关信息。在 Grafana 服务启动时会扫描所有的插件文件夹并挂载每个插件的 dist 目录,并查找 plugin.json 文件,根据文件的内容完成插件的自动注册。

在 Tencent Cloud Monitor App 中存在两种类型的 Plugin, 其配置文件如下: App Plugin 中配置 plugin.json

{
  "type": "app",                                          // 插件的类型: panel | app | datasource
  "name": "Tencent Cloud Monitor",                        // 插件名称
  "id": "tencentcloud-monitor-app",                       // 插件ID, 必须唯一
  "info": {
    "description": "Tencent Cloud Monitor App for Grafana",
    "author": {
      "name": "Tencent Cloud"
    },
    "keywords": [
      "tencentcloud",
      "tencentcloudmonitor",
      "grafana",
      "plugins"
    ],
    "logos": {
      "small": "img/tencent-cloud.svg",
      "large": "img/tencent-cloud.svg"
    },
    "version": "1.0.0",
    "updated": "2019-04-10"
  },
  "includes": [                                            // App Plugin 中包含的 Datasource Plugin 和 Dashboards 模板信息
    {
      "type": "dashboard",
      "name": "【实例】CDB 单机监控",
      "path": "dashboards/example_cdb_dashboard.json"
    },
    {
      "type": "dashboard",
      "name": "【实例】CVM 单机监控",
      "path": "dashboards/example_cvm_dashboard.json"
    },
    {
      "type": "datasource",
      "name": "Tencent Cloud Monitor Datasource"
    }
  ],
  "dependencies": {
    "grafanaVersion": "6.0",
    "plugins": []
  }
}
复制代码

Datasource Plugin 中配置 plugin.json

{
  "type": "datasource",
  "name": "Tencent Cloud Monitor Datasource",
  "id": "tencentcloud-monitor-datasource",
  "metrics": true,                           // Datasource plugin 特有的属性,是否在 panel 中支持 metrics
  "annotations": true,                       // Datasource plugin 特有的属性,是否在 dashboard 中支持 annotations 查询
  "queryOptions": {
    "maxDataPoints": true
  },
  "routes": [],
  "info": {
    "author": {
      "name": "Tencent Cloud"
    },
    "logos": {
      "small": "img/tencent-cloud.svg",
      "large": "img/tencent-cloud.svg"
    }
  }
}
复制代码

特别注意 Datasource Plugin 的 plugin.json 配置中必须存在 metricannotations,且其中至少有一个属性的值为 true

module.ts

module.ts(Required): Plugin 入口文件,决定了 Plugin 的具体实现的。根据插件的类型不同其内容也有所差异。

/* App Plugin 的 module.ts 需要导出1个模块 */
export {
  ConfigCtrl,
};

/* Datasource Plugin 的 module.ts 通常需要导出5个模块 */
export {
  Datasource,                 // Required
  ConfigCtrl,                 // Required
  QueryCtrl,                  // Required
  AnnotationsQueryCtrl,
  QueryOptionsCtrl
};
复制代码

Tencent Cloud Monitor App 开发实践

基于腾讯云云监控 API —— Tencent Cloud Monitor App 完整结构图如下所示:

在整个应用开发中最为重要的是 Datasource Plugin 模块的开发,下面我们以该模块为例进行详细介绍。

Datasource Plugin 的开发

Datasource Plugin 中有3个必须文件:DatasourceQueryCtrlConfigCtrl

Datasource

Datasource 类作为数据入口,主要负责与数据源进行通信。 针对 Tencent Cloud Monitor App 中不同的产品,都必须有一个对应 Datasource 实现类。因此我们定义了一个 Datasource 类的接口协议,每个产品的 Datasource 类都必须遵循这个接口协议:

interface DatasourceInterface {
  instanceSettings: any;
  backendSrv: any;
  templateSrv: any;
  query(options: any);
  testDatasource();
  metricFindQuery(query: any);
  getRegions(service: string);
  getMetrics(service: string, region: string);
  getInstances(service: string, region: string, params: any);
  getZones?: (service: string, region: string) => any;
}
复制代码

备注:

// Datasource 类如果要实现以下功能函数,则必须遵循 Grafana 命名协议约定,所以 Datasource 类的接口协议也是按照该要求进行设计。
query(options)             // Required, used by panels to get data
testDatasource()           // Required, used by datasource configuration page to make sure the connection is working
annotationQuery(options)   // used by dashboards to get annotations
metricFindQuery(options)   // used by query editor to get metric suggestions.
复制代码

Datasource 类的主要代码:

/* Datasource Plugin 中的 datasource 类 */
import { Datasources, SERVICES } from './tc_monitor';   // Datasources 是每个云产品对应的 Datasource 实现类组成的对象
export class TCMonitorDatasource implements DatasourceInterface {
  instanceSettings: any;
  backendSrv: any;
  templateSrv: any;

  /** @ngInject */
  constructor(instanceSettings, backendSrv, templateSrv) {
    this.instanceSettings = instanceSettings;
    this.backendSrv = backendSrv;
    this.templateSrv = templateSrv;
    _.forEach(Datasources, (_class, key) => {                   // 自动实例化每个云产品的 Datasource 类
      this[key] = new _class(this.instanceSettings, this.backendSrv, this.templateSrv);
    });
  }
  testDatasource() {...}                 // 根据选中的云产品去调用每个云产品 Datasource 类中对应的 testDatasource()
  query(options) {...}                   // 根据选中的云产品去调用每个云产品 Datasource 类中对应的 query()
  metricFindQuery(query) {...}           // 根据选中的云产品去调用每个云产品 Datasource 类中对应的 getRegions()
  getRegions() {...}                     // 根据选中的云产品去调用每个云产品 Datasource 类中对应的 getMetrics()
  getMetrics() {...}                     // 根据选中的云产品去调用每个云产品 Datasource 类中对应的 getZones()
  getInstances() {...}
  getZones() {...}
}

/*CVM 产品中的 datasource 模块*/ 
export default class CVMDatasource implements DatasourceInterface {
  constructor() {...}
  testDatasource() {...}
  query(options) {...}
  metricFindQuery(query) {...}
  getRegions() {...}
  getMetrics() {...}
  getInstances() {...}
  getZones() {...}
}
复制代码

在新增产品时只需在 tc_monitor 目录中增加对应子目录实现各自的 datasource.ts 类(继承DatasourceInterface 协议),再在tc_monitor 目录的 index.tx 文件中通过 Datasources 配置该类入口。

QueryCtrl

当用户在 Dashboard 页面对 Panel 进行编辑时,QueryCtrl 类将被实例化并作为 Angular 控制器,并根据类中的 templateUrl 去加载对应的 View 视图,以图形化的界面提供接口数据查询。该类必须继承自 grafana/app/plugins/sdk。具体页面展示以及主要代码逻辑如下:

import { QueryCtrl } from 'grafana/app/plugins/sdk';

export class TCMonitorDatasourceQueryCtrl extends QueryCtrl {
  static templateUrl = 'datasource/partials/query.editor.html';
  datasource: any;                  // 对应 datasource.ts 实例的对象
  panelCtrl: any;                   // 对应 Panel 的实例对象
  target: {                         // 具体的查询条件信息保存
    refId: string;
    namespace: string;
    service: string;
    showInstanceDetails: boolean;
  };
  defaults = {                      // 初始化值
    namespace: '',
    service: '',
    showInstanceDetails: false,
    ...InitServiceState,
  };

  lastQuery: string;
  lastQueryError?: string;

  /** @ngInject */
  constructor($scope, $injector, private templateSrv) {
    super($scope, $injector);
    _.defaultsDeep(this.target, this.defaults);
    this.panelCtrl.events.on('data-received', this.onDataReceived.bind(this), $scope);
  }

  // Panel 实例的数据接收处理函数
  onDataReceived(dataList) {
    this.lastQueryError = undefined;
    this.lastQuery = '';
    const anySeriesFromQuery: any = _.find(dataList, { refId: this.target.refId });
    if (anySeriesFromQuery) {
      this.lastQuery = anySeriesFromQuery.query;
    }
  }

  // Panel 数据查询失败的调用函数
  onDataError(err) {
    this.handleQueryCtrlError(err);
  }

  handleQueryCtrlError(err) {...}
  // 省略其它详细代码
}
复制代码

对应视图 View 中的部分代码如下,<query-editor-row query-ctrl="ctrl"></query-editor-row> 标签的内容会加入到Add Query模板中:

<query-editor-row query-ctrl="ctrl" class="generic-datasource-query-row" has-text-edit-mode="true">
  <div class="gf-form-inline">
    <div class="gf-form">
      <label class="gf-form-label query-keyword width-9">Namespace</label>
      <div class="gf-form-select-wrapper gf-form-select-wrapper--caret-indent">
        <select class="gf-form-input min-width-12" ng-model="ctrl.target.namespace" ng-options="f as f for f in ctrl.namespaces"
          ng-change="ctrl.onNamespaceChange()"></select>
      </div>
    </div>
  </div>
  <!-- 省略更多详情 -->

  <!-- 新增不同的云产品,需要在该处增加新产品独有的配置页面 -->
  <!-- CVM -->
  <cvm-query
    ng-if="ctrl.target.service==='cvm'"
    target="ctrl.target.cvm"
    show-detail="ctrl.checkShowDetail('instance')"
    datasource="ctrl.datasource"
    on-change="ctrl.onInstanceQueryChange()"
    region="ctrl.replace(ctrl.target.cvm.region)"
  ></cvm-query>

  <!-- Global error message -->
  <div class="gf-form" ng-show="ctrl.lastQueryError">
    <pre class="gf-form-pre alert alert-error">{{ctrl.lastQueryError}}</pre>
  </div>
</query-editor-row>
复制代码

QueryCtrl 类是查询面板的入口,其中 NamespaceRegionMetricNamePeriodInsatnce 查询条件是腾讯云产品共有的,其业务逻辑实现在 QueryCtrl 类中。对于自定义业务,则可在自定义QueryCtrl 类中实现单独的 Angular 组件。以上面图片显示的面板为例,其中 ShowDetail 控制获取特定业务的实例列表数据,因此需抽象到单独的 Angular 组件中。新增产品则需要在 tc_monitor 目录实现各自的 query.ts 类,并在 index.tx 文件中通过 import 注册该组件,则对应在 query.editor.html 中引入产品实现的组件即可。

ConfigCtrl 类

ConfigCtrl 类是添加数据源的面板进行控制。 当用户对该 App Plugin 的数据源进行配置时,该类会被实例化为 Angular 的控制器,并根据类中的 templateUrl 去加载对应的 View 视图,用于呈现数据源自定义配置的面板。具体页面展示示例如下:

/* 文件路径为 /src/datasource/config.ctrl.ts */
import * as _ from 'lodash';
import { SERVICES } from './tc_monitor';

export class TCMonitorDatasourceConfigCtrl {
  static templateUrl = 'datasource/partials/config.html';   // 指定该Controller 对应 View 文件,且实际路径为 /src/datasource/partials/config.html
  current: any;
  /** @ngInject */
  constructor($scope) {
    this.current.jsonData.services = SERVICES;
    _.forEach(this.current.jsonData.services, (service) => {
      this.current.jsonData[service.service] = true;
    });
  }
}
复制代码

结束

Tencent Cloud Monitor App 已经在 github.com 上开源了,欢迎大家多提 issues,顺便给我们 Star 鼓励一下。
项目地址:TencentCloud/tencentcloud-monitor-grafana-app (github.com/TencentClou…)

项目代码开发成员:

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值