Grafana SimpleJson插件实现自定义数据源
SimpleJson数据源简介
Grafana作为最火热的开源数据可视化工具,最大的特点就是支持多种数据源以及丰富的插件库了。官方提供了Elasictsearch、Prometheus、Mysql等常见数据库的数据源,社区也提供了支持Zabbix监控数据展示的数据源,但是实际应用中仍会遇到现有数据源无法满足需求的情况。比如Grafana没有现成插件支持从MongoDB等其他数据库中读取数据。
SimpleJson是Grafana开源社区提供的数据源,它本身并不依赖某种特定的后端存储,只需要后端能实现Grafana报表的几个查询接口就行,可以说给开发者提供了很大的想象空间了。
SimpleJson 基本原理
SimpleJson是Grafana众多数据源插件中的一种,但它又不像其他插件配置好数据库信息就能用,开发者需要自己实现一部分数据源插件的功能来使SimpleJson插件能够使用。
Grafana官方的数据源插件开发指南中写到:
Data source plugins enables people to develop plugins for any database that communicates over http. Its up to the plugin to transform the data into time series data so that any grafana panel can then show it.
也就是说一个 DataSource 插件主要是实现了一个 HTTP 服务,把后端数据源中的数据提取成HTTP协议中的数据体并返回给Grafana。
对照一下 DataSource 插件开发和 SimpleJson 的实现要求:
DataSource | SimpleJson | |
---|---|---|
可用性测试接口 | ✔ | ✔ |
指标展示接口 | ✔ | ✔ |
数据查询接口 | ✔ | ✔ |
注释展示接口 | ✔ | ✔ |
配置文件 | ✔ | |
配置控制器 | ✔ | |
数据查询控制器 | ✔ | |
注释查询控制器 | ✔ |
可以看到SimpleJson其实是对数据源插件的进一步简化,只要求开发者处理跟数据处理相关的接口即可。在开发指南中,数据源插件的上述功能都要通过JavaScript对象来实现的,而SimpleJson只需要开发者实现满足上面那些接口的HTTP服务,也就是说你可以用自己熟悉的语言来实现。
SimpleJson后端需要实现的四个接口:
/
用于数据源配置界面的"Test connection"调用,若后端服务器正常应返回 200 状态码/search
用于 panel 面板中查询有哪些可用的指标/query
基于用户的查询语句,返回相应的数据/annotations
返回注释内容
后端实现
SimpleJson的Github仓库中推荐了4个后端实现用于参考:
- https://github.com/bergquist/fake-simple-json-datasource
- https://github.com/smcquay/jsonds
- https://github.com/ContextLogic/eventmaster
- https://gist.github.com/linar-jether/95ff412f9d19fdf5e51293eb0c09b850 (Python/pandas backend)
分别是用 JavaScript,Go,Python等语言实现的,在下面的实践案例中我用的是基于Python pandas库的后端实现
实践案例
场景:工作中需要对eureka服务列表完整性进行监控,不仅要能在服务下线时告警还需要能够通过报表展示过去一段时间的情况,毕竟有时候告警响应不及时或者被其他告警信息淹没时,还是需要监控图表来展示往期状态的。
Grafana本身没有存储功能,数据都是存储在数据源插件中配置的后端数据库中,得益于SimpleJson的开放性,我们可以选择Sqlite甚至CSV文件这些轻量的东西来保存数据。
SimpleJson的 Python实现中,主要是通过这段代码来处理核心逻辑:
这段是实例代码,效果是展示一个正弦函数的曲线图
def get_sine(freq, ts_range): freq = int(freq) ts = pd.date_range(ts_range['$gt'], ts_range['$lte'], freq='H') return pd.Series(np.sin(np.arange(len(ts)) * np.pi * freq * 2 / float(len(ts))), index=ts).to_frame('value') add_reader('sine_wave', get_sine)
add_reader函数是增加一个指标并将指标与一个函数绑定,也就是这里的get_sine函数,用于从后端读取数据并处理成特定的数据结构(不过这个例子中没有后端数据)。
get_sine函数接受两个参数,freq和ts_range,ts_range就是Grafana右上角的时间范围,freq属于指标的额外参数,当你在查询面板输入查询语句 sine_wave:24,就会调用 get_sine(24, ts_range)。
然后get_sine函数利用Pandas的series和data_frame 两种数据结构,最后返回一个类似这样的数据:
sine_wave | |
---|---|
2019-11-30 | 1 |
2019-12-01 | 0 |
每行数据都是一个 datapoint,根据时间戳和值在图表上打数据点,而sine_wave就是这些数据点从属的指标名称。
如果你要加个自己的指标和处理函数,大概就是写这些代码:
def <处理函数>(<额外参数,可选>, ts_range): data_point = <根据时间范围,从后端数据中读取符合条件的时间戳和对应的值, 每个时间戳需要是Pandas的datetime类型> return <将data_point处理成Pandas的data frame数据结构并返回> add_reader('<指标名称>', <处理函数>)
思考与总结
- 依赖倒置原则: Grafana支持多种数据源,并不为每种数据源都去适配一个专门的解决方案,而是通过声明接口,让各种数据源去实现,这就是软件设计模式中著名的依赖倒置原则的体现了,在生产活动中的说法就是标准化是规模化的前提了。
- 通过不断简化降低上手门槛:SimpleJson使用户自定义数据源更加方便,就是因为它屏蔽了查询界面UI设计这些用户不太关心的高级设置,只把最重要的数据处理接口交给用户,又有许多开发者提供后端实现模板进一步简化了工作量,让我这样只有一些Python编程基础的人也能自定义数据源。说明软件中的插件设计要尽量灵活可配置,让高手玩家能够深度定制;但是在推广过程中也需要不断简单化,让更多小白都能有上手机会。
- 点赞
- 收藏
- 分享
- 文章举报
- ExpandableListView的完美实现,JSON数据源,右边自定义图片
- Struts2之—集成Json插件实现Ajax
- 扩展GridView实现的一个自定义无刷新分页,排序,支持多种数据源的控件TwfGridView
- PHP 利用JsonSerializable接口实现自定义json编码
- 利用C++实现自定义插件
- 自定义JQuery插件(附图片轮播banner实现)
- 动态加载与插件系统的初步实现(四):解析JSON、扩展Fiddler
- Phonegap(Cordova自定义插件)实现分享功能
- .NET 插件系统框架设计(二) 使用对象序列化实现自定义配置文件管理
- 自定义SimpleMappingExceptionResolver实现个性化的异常处理
- struts2之使用JSON插件实现Ajax(处理枚举类型)
- 使用ajax、pageHelpler分页插件、利用json数据特性实现分页查询
- phoneGap在iOS上的简单使用:自定义实现友盟分享插件
- emacs使用 simple-httpd和impatient-mode插件实现livereload
- YbSoftwareFactory 代码生成插件【二十四】:MVC中实现动态自定义路由
- 自定义实现Json字符串向C#对象的转变
- 自定义序列化器类继承serializers.ModelSerializer实现模型数据简化映射到json格式
- Django自定义插件实现网站登录验证码功能
- Spring 多数据源 -------使用自定义注解方式实现动态切换数据源
- 源码推荐:Json/xml自动生成model类插件 高度自定义的TabBarController