暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

一种Grafana数据源插件开发的方案(纯后端)

悟空的筋斗云 2019-05-10
371

背景

目前, Grafana官方已支持多种数据源, 例如: Prometheus, InfluxDB, MySQL, OpenTSDB, Elasticsearch等, 已经能满足绝大部分的需求. 但是, 在某些特定的情况下可能需要编写自己的数据源插件, 这要求开发者懂一些前端的东西, 笔者是个前端文盲, 因此另辟蹊径研究了纯后端的实现方案.

基本要求


  • 后端开发

    Java, php, Golang, Python等都可以实现, 只要能满足需求即可, 本文以Golang为例.



  • Nginx或者其他七层负载均衡器

    这个只要求会一些的简单请求参数判断就可以了, 本文以Nginx为例.


原理概述

Grafana前端(配置Panel来可视化数据, 这里选择配置好的InfluxDB数据源), 首先Panel(可以是Graph或者其他图表)会发送请求获取数据然后再进行渲染, 数据会通过配置好的InfluxDB数据源向实际的后端数据源获取, 此时我们在实际数据源和数据源插件之间增加一个Nginx来代理请求, 通过特定的查询语句的前缀来区分是否是我们自定义的请求, 如果是那么代理到我们自己的上游后端, 否则直接转到原来的后端(也就是真正的InfluxDB), 这样一来我们就完成了对Grafana前端的"欺骗", 届时我们自己的后端按照InfluxDB数据源要求的格式返回数据即可, 换作是Prometheus数据源活着的其他数据源也是类似的, 这样,就极大的扩展了支持的数据源, 因为后端就算不是对应的数据源也可以提供数据了.

实施

这里只提供一个简单的例子.

  • 后端实现:

  1. package main


  2. import (

  3. "net/http"

  4. )


  5. const testData = `{

  6. "results": [

  7. {

  8. "statement_id": 0,

  9. "series": [

  10. {

  11. "name": "test",

  12. "tags": {

  13. "cluster": "song",

  14. "model": "cache",

  15. "project": "test",

  16. "protocol": "cache/Hint/web"

  17. },

  18. "columns": [

  19. "time",

  20. "total"

  21. ],

  22. "values": [

  23. [

  24. 1557449700000,

  25. null

  26. ],

  27. [

  28. 1557450000000,

  29. null

  30. ],

  31. [

  32. 1557450300000,

  33. null

  34. ],

  35. [

  36. 1557450600000,

  37. null

  38. ],

  39. [

  40. 1557450900000,

  41. null

  42. ],

  43. [

  44. 1557451200000,

  45. null

  46. ],

  47. [

  48. 1557451500000,

  49. null

  50. ],

  51. [

  52. 1557451800000,

  53. null

  54. ],

  55. [

  56. 1557452100000,

  57. null

  58. ],

  59. [

  60. 1557452400000,

  61. null

  62. ],

  63. [

  64. 1557452700000,

  65. null

  66. ],

  67. [

  68. 1557453000000,

  69. null

  70. ],

  71. [

  72. 1557453300000,

  73. null

  74. ]

  75. ]

  76. }

  77. ]

  78. }

  79. ]

  80. }`


  81. func testHandler(w http.ResponseWriter, r *http.Request) {

  82. w.Write([]byte(testData))

  83. }


  84. func main() {

  85. mux := http.NewServeMux()


  86. mux.HandleFunc("/test", testHandler)

  87. http.ListenAndServe(":12345", mux)

  88. }

复制
  • Nginx配置

  1. upstream influxdb

  2. {

  3. server 127.0.0.1:8086;

  4. }


  5. upstream myifx

  6. {

  7. server 192.168.10.1:12345;

  8. }


  9. server {

  10. listen 8086;

  11. server_name influxdb.ximply.com;


  12. set $myifx 0;

  13. if ($arg_q ~* (myprefix.*)) {

  14. set $myifx 1;

  15. }


  16. location / {

  17. proxy_set_header Host $host;

  18. proxy_set_header X-Real-IP $remote_addr;

  19. proxy_set_header REMOTE-HOST $remote_addr;

  20. proxy_set_header X-Forwarded-For $remote_addr;


  21. if ($myifx = 1) {

  22. proxy_pass http://myifx/test?q=$arg_q;

  23. break;

  24. }

  25. proxy_pass http://influxdb;

  26. }


  27. #access_log off;

  28. access_log /home/www/log/ifx.access.log;

  29. error_log /home/www/log/error.log;

  30. }

复制
  • Grafana Graph 面板 查询语句为: myprefix{"from":$__from,"to":$__to,","protocol":"test"}

注: 首先我们要选择InfluxDB作为数据源, 然后这里的 myprefix
一定要跟Nginx那边的参数判断保持一致, 这样才能进行区分, 另外查询语句可以自己定义格式, 我这里是比较通用的Json格式, 里面的参数可以加入Grafana本身的变量以及自己定义的变量, protocol
这个是用来区别具体请求的(例如获取CPU使用率, 获取内存使用率等, 根据自己的需求来定义).

最后

该方案算是有点投机取巧, 不过在某些需要的情况下还是可以使用的, 可以作为开发自定义数据源插件的一个扩展吧, 如果有前端资源的话, 还是建议按照官方流程来做.

文章转载自悟空的筋斗云,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论