- Logstash
- Logstash - 入门示例
- 入门示例 - 下载安装
- 入门示例 - hello world
- 入门示例 - 配置语法
- 入门示例 - plugin的安装
- 入门示例 - 长期运行
- Logstash - 插件配置
- 插件配置 - input配置
- input配置 - file
- input配置 - stdin
- input配置 - syslog
- input配置 - tcp
- 插件配置 - codec配置
- codec配置 - json
- codec配置 - multiline
- codec配置 - collectd
- codec配置 - netflow
- 插件配置 - filter配置
- filter配置 - date
- filter配置 - grok
- filter配置 - dissect
- filter配置 - geoip
- filter配置 - json
- filter配置 - kv
- filter配置 - metrics
- filter配置 - mutate
- filter配置 - ruby
- filter配置 - split
- filter配置 - elapsed
- 插件配置 - output配置
- output配置 - elasticsearch
- output配置 - email
- output配置 - exec
- output配置 - file
- output配置 - nagios
- output配置 - statsd
- output配置 - stdout
- output配置 - tcp
- output配置 - hdfs
- Logstash - 场景示例
- 场景示例 - nginx访问日志
- 场景示例 - nginx错误日志
- 场景示例 - postfix日志
- 场景示例 - ossec日志
- 场景示例 - windows系统日志
- 场景示例 - Java日志
- 场景示例 - MySQL慢查询日志
- Logstash - 性能与测试
- 性能与测试 - generator方式
- 性能与测试 - 监控方案
- 监控方案 - logstash-input-heartbeat方式
- 监控方案 - jmx启动参数方式
- 监控方案 - API方式
- Logstash - 扩展方案
- 扩展方案 - 通过redis传输
- 扩展方案 - 通过kafka传输
- 扩展方案 - AIX 平台上的logstash-forwarder-java
- 扩展方案 - rsyslog
- 扩展方案 - nxlog
- 扩展方案 - heka
- 扩展方案 - fluent
- 扩展方案 - Message::Passing
- Logstash - 源码解析
- 源码解析 - pipeline流程
- 源码解析 - Event的生成
- Logstash - 插件开发
- 插件开发 - utmp插件示例
- Beats
- Beats - filebeat
- Beats - packetbeat网络流量分析
- Beats - metricbeat
- Beats - winlogbeat
- ElasticSearch
- ElasticSearch - 架构原理
- 架构原理 - segment、buffer和translog对实时性的影响
- 架构原理 - segment merge对写入性能的影响
- 架构原理 - routing和replica的读写过程
- 架构原理 - shard的allocate控制
- 架构原理 - 自动发现的配置
- ElasticSearch - 接口使用示例
- 接口使用示例 - 增删改查操作
- 接口使用示例 - 搜索请求
- 接口使用示例 - Painless脚本
- 接口使用示例 - reindex接口
- ElasticSearch - 性能优化
- 性能优化 - bulk提交
- 性能优化 - gateway配置
- 性能优化 - 集群状态维护
- 性能优化 - 缓存
- 性能优化 - fielddata
- 性能优化 - curator工具
- 性能优化 - profile接口
- ElasticSearch - rally测试方案
- ElasticSearch - 多集群互联
- ElasticSearch - 别名的应用
- ElasticSearch - 映射与模板的定制
- ElasticSearch - puppet-elasticsearch模块的使用
- ElasticSearch - 计划内停机升级的操作流程
- ElasticSearch - 镜像备份
- ElasticSearch - rollover和shrink
- ElasticSearch - Ingest节点
- ElasticSearch - Hadoop 集成
- Hadoop 集成 - spark streaming交互
- ElasticSearch - 权限管理
- 权限管理 - Shield
- 权限管理 - Search-Guard 在 Elasticsearch 2.x 上的运用
- ElasticSearch - 监控方案
- 监控方案 - 监控相关接口
- 监控相关接口 - 集群健康状态
- 监控相关接口 - 节点状态
- 监控相关接口 - 索引状态
- 监控相关接口 - 任务管理
- 监控相关接口 - cat 接口的命令行使用
- 监控方案 - 日志记录
- 监控方案 - 实时bigdesk方案
- 监控方案 - cerebro
- 监控方案 - zabbix trapper方案
- ElasticSearch - ES在运维监控领域的其他玩法
- ES在运维监控领域的其他玩法 - percolator接口
- ES在运维监控领域的其他玩法 - watcher报警
- ES在运维监控领域的其他玩法 - ElastAlert
- ES在运维监控领域的其他玩法 - 时序数据库
- ES在运维监控领域的其他玩法 - Grafana
- ES在运维监控领域的其他玩法 - juttle
- ES在运维监控领域的其他玩法 - Etsy的Kale异常检测
- Kibana 5
- Kibana 5 - 安装、配置和运行
- Kibana 5 - 生产环境部署
- Kibana 5 - discover功能
- Kibana 5 - 各visualize功能
- 各visualize功能 - area
- 各visualize功能 - table
- 各visualize功能 - line
- 各visualize功能 - markdown
- 各visualize功能 - metric
- 各visualize功能 - pie
- 各visualize功能 - tile map
- 各visualize功能 - vertical bar
- Kibana 5 - dashboard功能
- Kibana 5 - timelion 介绍
- Kibana 5 - console 介绍
- Kibana 5 - setting功能
- Kibana 5 - 常用sub agg示例
- 常用sub agg示例 - 函数堆栈链分析
- 常用sub agg示例 - 分图统计
- 常用sub agg示例 - TopN的时序趋势图
- 常用sub agg示例 - 响应时间的百分占比趋势图
- 常用sub agg示例 - 响应时间的概率分布在不同时段的相似度对比
- Kibana 5 - 源码解析
- 源码解析 - .kibana索引的数据结构
- 源码解析 - 主页入口
- 源码解析 - discover解析
- 源码解析 - visualize解析
- 源码解析 - dashboard解析
- Kibana 5 - 插件
- 插件 - 可视化开发示例
- 插件 - 后端开发示例
- 插件 - 完整app开发示例
- Kibana 5 - Kibana报表
- 竞品对比
插件 - 可视化开发示例
上一节,我们看到了一个完整的 Kibana 插件的官方用例。一般来说,我们不太会需要自己从头到尾写一个 angular app 出来。最常见的情况,应该是在 Kibana 功能的基础上做一定的二次开发和扩展。其中,可视化效果应该是重中之重。本节,以一个红绿灯效果,演示如何开发一个 Kibana 可视化插件。
插件目录生成
Kibana 开发组提供了一个简单的工具,辅助我们生成一个 Kibana 插件的目录结构:
npm install -g yo
npm install -g generator-kibana-plugin
mkdir traffic_light_vis
cd traffic_light_vis
yo kibana-plugin
但是这个是针对完整的 app 扩展的,很多目录对于可视化插件来说,并没有用。所以,我们可以自己手动创建目录:
mkdir -p traffic_light_vis/public
cd traffic_light_vis
touch index.js package.json
cd public
touch traffic_light_vis.html traffic_light_vis.js traffic_light_vis.less traffic_light_vis_controller.js traffic_light_vis_params.html
其中 index.js
内容如下:
'use strict';
module.exports = function (kibana) {
return new kibana.Plugin({
uiExports: {
visTypes: ['plugins/traffic_light_vis/traffic_light_vis']
}
});
};
package.json
内容如下:
{
"name": "traffic_light_vis",
"version": "0.1.0",
"description": "An awesome Kibana plugin for red/yellow/green status visualize"
}
这两个基础文件格式都比较固定,除了改个名就基本 OK 了。
然后我们看最关键的可视化对象定义 public/traffic_light_vis.js
内容:
define(function (require) {
// 加载样式表
require('plugins/traffic_light_vis/traffic_light_vis.less');
// 加载控制器程序
require('plugins/traffic_light_vis/traffic_light_vis_controller');
// 注册到 vis_types
require('ui/registry/vis_types').register(TrafficLightVisProvider);
function TrafficLightVisProvider(Private) {
// TemplateVisType 基类,适用于基础的 metric 和数据表格式的可视化定义。实际上,Kibana4 的 metric_vis 和 table_vis 就继承自这个,
// Kibana4 还有另一个基类叫 VisLibVisType,其他使用 D3.js 做可视化的,继承这个。
var TemplateVisType = Private(require('ui/template_vis_type/TemplateVisType'));
var Schemas = Private(require('ui/Vis/Schemas'));
// 模板化的 visType 对象定义,用来配置和展示
return new TemplateVisType({
name: 'traffic_light',
// 显示在 visualize 选择列表里的名称,描述,小图标
title: 'Traffic Light',
description: 'Great for one-glance status readings, the traffic light visualization expresses in green / yellow / red the position of a single value in relation to low and high thresholds.',
icon: 'fa-car',
// 可视化效果模板页面
template: require('plugins/traffic_light_vis/traffic_light_vis.html'),
params: {
defaults: {
fontSize: 60
},
// 编辑参数的页面
editor: require('plugins/traffic_light_vis/traffic_light_vis_params.html')
},
// 在编辑页面上可以选择的 aggregation 类型。
schemas: new Schemas([
{
group: 'metrics',
name: 'metric',
title: 'Metric',
min: 1,
defaults: [
{ type: 'count', schema: 'metric' }
]
}
])
});
}
// export the provider so that the visType can be required with Private()
return TrafficLightVisProvider;
});
然后就是可视化效果的模板页面了,traffic_light_vis.html
毫无疑问也是一个 angular 风格的:
<div ng-controller="TrafficLightVisController" class="traffic-light-vis">
<div class="metric-container" ng-repeat="metric in metrics">
<div class="traffic-light-container" ng-style="{'width': vis.params.width+'px', 'height': (2.68 * vis.params.width)+'px' }">
<div class="traffic-light">
<div class="light red" ng-class="{'on': (!vis.params.invertScale && metric.value <= vis.params.redThreshold) || (vis.params.invertScale && metric.value >= vis.params.redThreshold) }"></div>
<div class="light yellow" ng-class="{'on': (!vis.params.invertScale && metric.value > vis.params.redThreshold && metric.value < vis.params.greenThreshold) || (vis.params.invertScale && metric.value < vis.params.redThreshold && metric.value > vis.params.greenThreshold) }"></div>
<div class="light green" ng-class="{'on': (!vis.params.invertScale && metric.value >= vis.params.greenThreshold) || (vis.params.invertScale && metric.value <= vis.params.greenThreshold) }"></div>
</div>
</div>
<div>{{metric.label}}</div>
</div>
</div>
这里可以看到:
- 把 div 绑定到了
TrafficLightVisController
控制器上,这个也是之前在 js 里已经加载过的。 - 通过
ng-repeat
循环展示不同的 metric,也就是说模板渲染的时候,收到的是一个metrics
数组。这个来源当然是在控制器里。 - 然后具体的数据判断,即什么灯亮什么灯灭,通过了
vis.params.*
的运算判断。这些变量当然是在编辑页面里设置的。
所以下一步看编辑页面 traffic_light_vis_params.html
:
<div class="form-group">
<label>Traffic light width - {{ vis.params.width }}px</label>
<input type="range" ng-model="vis.params.width" class="form-control" min="30" max="120"/>
</div>
<div class="form-group">
<label>Red threshold <span ng-bind-template="({{!vis.params.invertScale ? 'below':'above'}} this value will be red)"></span></label>
<input type="number" ng-model="vis.params.redThreshold" class="form-control"/>
</div>
<div class="form-group">
<label>Green threshold <span ng-bind-template="({{!vis.params.invertScale ? 'above':'below'}} this value will be green)"></span></label>
<input type="number" ng-model="vis.params.greenThreshold" class="form-control"/>
</div>
<div class="form-group">
<label>
<input type="checkbox" ng-model="vis.params.invertScale">
Invert scale
</label>
</div>
内容很简单,就是通过 ng-model
设置绑定变量,跟之前 HTML 里的联动。
最后一步,看控制器 traffic_light_vis_controller.js
:
define(function (require) {
var module = require('ui/modules').get('kibana/traffic_light_vis', ['kibana']);
module.controller('TrafficLightVisController', function ($scope, Private) {
var tabifyAggResponse = Private(require('ui/agg_response/tabify/tabify'));
var metrics = $scope.metrics = [];
$scope.processTableGroups = function (tableGroups) {
tableGroups.tables.forEach(function (table) {
table.columns.forEach(function (column, i) {
metrics.push({
label: column.title,
value: table.rows[0][i]
});
});
});
};
$scope.$watch('esResponse', function (resp) {
if (resp) {
metrics.length = 0;
$scope.processTableGroups(tabifyAggResponse($scope.vis, resp));
}
});
});
});
要点在:
$scope.$watch('esResponse', function(resp){})
监听整个页面的请求响应,在有新数据过来的时候更新页面效果;agg_response/tabify/tabify
把响应结果转换成二维表格形式。
最后加上一段样式表,这里就不贴了,见:https://github.com/logzio/kibana-visualizations/blob/master/traffic_light_vis/traffic_light_vis.less。
本节介绍的示例,出自 logz.io 官方博客和对应的 github 开源项目。logz.io 是基于 Kibana4.1 写的插件。我这里修正成了基于最新 Kibana4.3 的实现。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论