GrafanaTable插件源码阅读(进阶)前端视角
作者:玲子0909_366 | 来源:互联网 | 2023-08-25 20:40
GrafanaTable插件源码阅读(进阶)-前端视角,Go语言社区,Golang程序员人脉社
前言
之前已经带大家阅读了 Grafana 入门、安装和命令 (mac) 和 Grafana 插件开发入门 - 前端视角(React)两片文章~
相信大家对于Grafana插件已经有了一个初步的认识,下一步,我们来进阶版,看下 table插件 的书写
Table源文件分析
源文件位置:https://github.com/grafana/grafana/tree/master/public/app/plugins/panel,主要分析的就是table 和 table2 文件
Table 和 Table2 的区别
Table 是Angular写的,Table2是react写的。
由于我日常用React比较多,所以选了table2
Table2 源码分析
文件目录分析
TablePanel.tsx (展示内容)
1. 主要使用了 @grafana/ui 中的 PanelProps, ThemeContext,Table
2. const { data, options } = this.props; 看到这句话,打印了一下,发现数据来源是 this.props.data.series[0]
// Libraries
import React, { Component } from 'react';
// Types
import { PanelProps, ThemeContext } from '@grafana/ui';
import { Options } from './types';
import Table from '@grafana/ui/src/components/Table/Table';
interface Props extends PanelProps {}
export class TablePanel extends Component {
constructor(props: Props) {
super(props);
}
render() {
const { data, options } = this.props;
if (data.series.length <1) {
return No Table Data...
;
}
return (
{theme => }
);
}
}
TablePanelEditor.tsx (可编辑区域)
1.this.props.onOptionsChange 是内部定义的函数
2. showHeader, fixedHeader, rotate, fixedColumns 四个参数也是默认的传值
//// Libraries
import _ from 'lodash';
import React, { PureComponent } from 'react';
// Types
import { PanelEditorProps, Switch, FormField } from '@grafana/ui';
export class TablePanelEditor extends PureComponent {
OnToggleShowHeader= () => {
this.props.onOptionsChange({ ...this.props.options, showHeader: !this.props.options.showHeader });
};
OnToggleFixedHeader= () => {
this.props.onOptionsChange({ ...this.props.options, fixedHeader: !this.props.options.fixedHeader });
};
OnToggleRotate= () => {
this.props.onOptionsChange({ ...this.props.options, rotate: !this.props.options.rotate });
};
OnFixedColumnsChange= ({ target }: any) => {
this.props.onOptionsChange({ ...this.props.options, fixedColumns: target.value });
};
render() {
const { showHeader, fixedHeader, rotate, fixedColumns } = this.props.options;
return (
);
}
}
types.ts(传入参数定义 + 默认值)
1.传入参数类型定义【估计是typescript的原因】
2.初始化时候的默认值设置
import { ColumnStyle } from '@grafana/ui/src/components/Table/TableCellBuilder';
export interface Options {
showHeader: boolean;
fixedHeader: boolean;
fixedColumns: number;
rotate: boolean;
styles: ColumnStyle[];
}
export const defaults: OptiOns= {
showHeader: true,
fixedHeader: true,
fixedColumns: 0,
rotate: false,
styles: [
{
type: 'date',
pattern: 'Time',
alias: 'Time',
dateFormat: 'YYYY-MM-DD HH:mm:ss',
},
{
unit: 'short',
type: 'number',
alias: '',
decimals: 2,
colors: ['rgba(245, 54, 54, 0.9)', 'rgba(237, 129, 40, 0.89)', 'rgba(50, 172, 45, 0.97)'],
pattern: '/.*/',
thresholds: [],
},
],
};
module.tsx (入口文件)
1.设置相关区域 - 目测是固定的格式
A. setDefaults(默认值)
B. setEditor (编辑器页面)
import { PanelPlugin } from '@grafana/ui';
import { TablePanelEditor } from './TablePanelEditor';
import { TablePanel } from './TablePanel';
import { Options, defaults } from './types';
export const plugin = new PanelPlugin (TablePanel).setDefaults(defaults).setEditor(TablePanelEditor);
我的修改
我需要的是类似于log的效果,左边是时间,右边是具体的日志,主要修改的内容是TablePanel.tsx,注释了TablePanelEditor.tsx的展示
修改后的样子展示
忽略我狂野的打码
TablePanel.tsx - 修改版
1. 主要修改了一下表格的返回顺序
// Libraries
import React, { Component } from 'react';
// Types
import { PanelProps, ThemeContext, Table } from '@grafana/ui';
import { Options } from './types';
import moment from 'moment';
import './index.css';
interface Props extends PanelProps {}
export class TablePanel extends Component {
constructor(props: Props) {
super(props);
}
render() {
const { data, options } = this.props;
if (data.series.length <1) {
return No Table Data...
;
}
// 数据处理,把日期放在第一个
// 如果你们没有日期展示顺序问题的话,忽略
const rows = [];
for (let i = 0; i
{
!!rows.length > 0 && rows.map((row, row_index, row_array) => {
return
{
!!fields.length > 0 && fields.map((column, column_index, column_array) => {
return
{ column.type === "time" &&
{ moment(row[column_index]).format("YYYY-MM-DD HH:mm:ss") }
}
{
column.type !== "time" &&
{ row[column_index] }
}
}, this)
}
}, this)
}
);
}
}
TablePanelEditor.tsx
注释相关无用内容,毕竟其实日志无需编辑
//// Libraries
import React, { PureComponent } from 'react';
// Types
import { PanelEditorProps, Switch, FormField } from '@grafana/ui';
import { Options } from './types';
export class TablePanelEditor extends PureComponent > {
render() {
return (
);
}
}
小插曲
本来以为开开心心的做完了,结果,因为线上版本是6.1.3的缘故不兼容。
我内心充满了拒绝。。只能呢硬着头皮看 table 插件的内容,table插件是Angular写的,如果大家对语法不熟悉的话,可以看下相关语法。
环境搭建+开发
我查了一下,相关几个demo支持的版本,最后选择clock-panel这个demo来进行操作
文件目录
和react或者angular文件不同的是,这个clock-panel 开放了webpack配置
plugin.json
当我看到,dependencies 依赖的 grafanaVersion 是 5.x.x ,我觉得就可以试一下了
{
"type": "panel",
"name": "logs",
"id": "grafana-logs-panel",
"info":
{
"description": "Clock panel for grafana",
"author":
{
"name": "Grafana Labs",
"url": "https://grafana.com"
},
"keywords": ["logs", "panel"],
"logos":
{
"small": "img/logo.svg",
"large": "img/logo.svg"
},
"links": [
{
"name": "Project site",
"url": "https://github.com/grafana/clock-panel"
},
{
"name": "MIT License",
"url": "https://github.com/grafana/clock-panel/blob/master/LICENSE"
}],
"version": "1.0.3",
"updated": "2019-05-24"
},
"dependencies":
{
"grafanaVersion": "5.x.x",
"plugins": []
}
}
修改后的文件目录
只留下了我用的文件
log_ctrl.ts(了解一下处理逻辑)
1. 事件监听函数 this.events.on('data-received', this.onDataReceived.bind(this)); 来更新一下,注入 data 的值
事件监听函数参考(6.3.4做了一些封装):https://github.com/grafana/grafana/blob/master/packages/grafana-ui/src/types/events.ts
import { MetricsPanelCtrl } from 'grafana/app/plugins/sdk';
import moment from 'moment-timezone';
import './external/moment-duration-format';
import _ from 'lodash';
import './css/clock-panel.css';
export class LogCtrl extends MetricsPanelCtrl {
static templateUrl = 'partials/module.html';
/** @ngInject */
constructor($scope, $injector) {
super($scope, $injector);
_.defaultsDeep(this.panel, this.panelDefaults);
this.events.on('data-received', this.onDataReceived.bind(this));
this.events.on('data-snapshot-load', this.onDataReceived.bind(this));
this.events.on('panel-initialized', this.render.bind(this));
this.events.on('component-did-mount', this.render.bind(this));
this.events.on('render', this.render.bind(this));
}
render() {
console.log("this.data ,", this.data);
}
onDataReceived(dataList: any) {
console.log("dataList, ",dataList);
this.dataRaw = dataList;
// let data = dataList[0].datapoints ;
this.data = dataList[0].datapoints ;
// this.data = [];
// // 数据处理
for (let i = 0; i
module.html
两列展示,列1和列0换了下顺序
打包
执行打包命令,直接用 dist 目录的文件就OK啦~
npm run build
结束语
啦啦啦~~~ 终于结束啦~~~
我自己觉得Grafana的源码没有很难阅读,大家都可以去读一下~
插件也没有很难写~内置函数比较多,找不到的话全局查找一下就可以啦~