ruby-grafana-reporter 0.2.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +105 -86
- data/bin/ruby-grafana-reporter +5 -5
- data/lib/VERSION.rb +3 -2
- data/lib/grafana/abstract_datasource.rb +136 -0
- data/lib/grafana/dashboard.rb +21 -23
- data/lib/grafana/errors.rb +8 -1
- data/lib/grafana/grafana.rb +61 -65
- data/lib/grafana/grafana_alerts_datasource.rb +57 -0
- data/lib/grafana/grafana_annotations_datasource.rb +56 -0
- data/lib/grafana/grafana_property_datasource.rb +25 -0
- data/lib/grafana/graphite_datasource.rb +50 -0
- data/lib/grafana/image_rendering_datasource.rb +44 -0
- data/lib/grafana/panel.rb +9 -3
- data/lib/grafana/prometheus_datasource.rb +45 -0
- data/lib/grafana/sql_datasource.rb +71 -0
- data/lib/grafana/unsupported_datasource.rb +7 -0
- data/lib/grafana/variable.rb +3 -2
- data/lib/grafana/webrequest.rb +71 -0
- data/lib/grafana_reporter/abstract_query.rb +359 -0
- data/lib/grafana_reporter/abstract_report.rb +119 -17
- data/lib/grafana_reporter/alerts_table_query.rb +44 -0
- data/lib/grafana_reporter/annotations_table_query.rb +43 -0
- data/lib/grafana_reporter/application/application.rb +49 -297
- data/lib/grafana_reporter/application/webservice.rb +49 -14
- data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +90 -0
- data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +89 -0
- data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +77 -0
- data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +79 -0
- data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +73 -0
- data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +99 -0
- data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +93 -0
- data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +64 -0
- data/lib/grafana_reporter/asciidoctor/report.rb +47 -76
- data/lib/grafana_reporter/asciidoctor/show_environment_include_processor.rb +46 -0
- data/lib/grafana_reporter/asciidoctor/show_help_include_processor.rb +35 -0
- data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +92 -0
- data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +88 -0
- data/lib/grafana_reporter/asciidoctor/value_as_variable_include_processor.rb +90 -0
- data/lib/grafana_reporter/configuration.rb +108 -43
- data/lib/grafana_reporter/console_configuration_wizard.rb +311 -0
- data/lib/grafana_reporter/demo_report_wizard.rb +101 -0
- data/lib/grafana_reporter/erb/report.rb +43 -0
- data/lib/grafana_reporter/errors.rb +41 -0
- data/lib/grafana_reporter/help.rb +443 -0
- data/lib/grafana_reporter/logger/{two_way_logger.rb → two_way_delegate_logger.rb} +1 -1
- data/lib/grafana_reporter/panel_image_query.rb +29 -0
- data/lib/grafana_reporter/panel_property_query.rb +22 -0
- data/lib/grafana_reporter/query_value_query.rb +79 -0
- data/lib/grafana_reporter/report_webhook.rb +35 -0
- data/lib/ruby_grafana_extension.rb +8 -0
- data/lib/{ruby-grafana-reporter.rb → ruby_grafana_reporter.rb} +13 -0
- metadata +47 -43
- data/lib/grafana/abstract_panel_query.rb +0 -22
- data/lib/grafana/abstract_query.rb +0 -132
- data/lib/grafana/abstract_sql_query.rb +0 -51
- data/lib/grafana/panel_image_query.rb +0 -52
- data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +0 -104
- data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +0 -99
- data/lib/grafana_reporter/asciidoctor/errors.rb +0 -40
- data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +0 -92
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +0 -91
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +0 -69
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +0 -68
- data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +0 -61
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +0 -78
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +0 -73
- data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +0 -20
- data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +0 -43
- data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +0 -202
- data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +0 -70
- data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +0 -66
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +0 -61
- data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +0 -34
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +0 -25
- data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +0 -44
- data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +0 -38
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +0 -310
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -37
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 799071f1a4ed0795aeb9dbdc7fe175d3e023f4d0de3844f0ae57e85343ab47b4
|
4
|
+
data.tar.gz: 6524d4a07cd49c6622d69507e0ee6c3a37c18c358f8a3dc63b56848255c38e4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f52466eb19bc813271c4f67818414f578750f2a7d9254244cb5213be47ffa50e8a1849788935211391b606cc944a84b9bef6b46aec583185bbe94958d2e080a5
|
7
|
+
data.tar.gz: 4eae953b1ad50b9d188d66f3f7bf0c9c6184ff3009da077f2ed07c0d082d7b3d7be75c362143033b27b8256482886e797c78ab750bdde5a85cf198ea8b4fe540
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
[](https://github.com/divinity666/ruby-grafana-reporter/blob/master/LICENSE)
|
2
2
|
[](https://travis-ci.org/github/divinity666/ruby-grafana-reporter?branch=master)
|
3
3
|
[](https://coveralls.io/github/divinity666/ruby-grafana-reporter?branch=master)
|
4
|
+
[](https://badge.fury.io/rb/ruby-grafana-reporter)
|
4
5
|
|
5
6
|
# Ruby Grafana Reporter
|
6
7
|
Reporting Service for Grafana
|
@@ -8,14 +9,11 @@ Reporting Service for Grafana
|
|
8
9
|
## Table of Contents
|
9
10
|
|
10
11
|
* [About the project](#about-the-project)
|
11
|
-
* [Getting started](#getting-started)
|
12
|
-
* [Grafana integration](#grafana-integration)
|
13
|
-
* [Webservice overview](#webservice-overview)
|
14
12
|
* [Features](#features)
|
13
|
+
* [Quick Start](#quick-start)
|
14
|
+
* [Grafana integration](#grafana-integration)
|
15
|
+
* [Webservice overview](#webservice-overview)
|
15
16
|
* [Roadmap](#roadmap)
|
16
|
-
* [Contributing](#contributing)
|
17
|
-
* [Licensing](#licensing)
|
18
|
-
* [Acknowledgements](#acknowledgements)
|
19
17
|
* [Donations](#donations)
|
20
18
|
|
21
19
|
## About the project
|
@@ -24,55 +22,93 @@ Did you ever want to create (professional) reports based on Grafana dashboards?
|
|
24
22
|
I did so in order to being able to automatically get monthly reports of my
|
25
23
|
home's energy usage. That's how it started.
|
26
24
|
|
27
|
-
|
28
|
-
(but not limited to) [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
29
|
-
report templates, which can dynamically integrate Grafana panels, queries,
|
30
|
-
images etc. to create dynamic PDF reports on the fly.
|
31
|
-
|
32
|
-
The report may also be returned in any other format that asciidoctor supports.
|
33
|
-
|
34
|
-
The reporter can run standalone or as a webservice. It is built to
|
35
|
-
integrate without further dependencies with the asciidoctor docker image.
|
36
|
-
|
37
|
-
The complete
|
38
|
-
[API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) can be
|
39
|
-
found here.
|
40
|
-
|
41
|
-
## Getting started
|
42
|
-
|
43
|
-
There exist several ways of installing the reporter. Here I cover the easiest
|
44
|
-
setup by using ruby gems. If you need further installation help, or want to use
|
45
|
-
a "baremetal" ruby setup or a docker integration, please have a look at the more
|
46
|
-
extended [installation documentation](INSTALL.md).
|
47
|
-
|
48
|
-
To install the reporter as a gem, simply run:
|
49
|
-
|
50
|
-
gem install ruby-grafana-reporter
|
51
|
-
|
52
|
-
If no configuration file is in place, you might want to use the configuration
|
53
|
-
wizard, which leads you through all necessary steps:
|
54
|
-
|
55
|
-
ruby-grafana-reporter -w
|
56
|
-
|
57
|
-
Now you're ready to go! Let's check it out!
|
58
|
-
|
59
|
-
ruby-grafana-reporter -t demo_report -o my_first_render.pdf
|
60
|
-
|
61
|
-
If everything works as expected, you should find a file named `my_first_render.pdf`
|
62
|
-
in the current folder, which contains a detailed explanation of all available
|
63
|
-
commands as well as your available configuration options.
|
64
|
-
|
65
|
-
To run the reporter as a service, you only need to call it like this:
|
66
|
-
|
67
|
-
ruby-grafana-reporter
|
68
|
-
|
69
|
-
Neat, isn't it?
|
70
|
-
|
71
|
-
### Grafana integration
|
25
|
+
## Features
|
72
26
|
|
73
|
-
|
74
|
-
(
|
75
|
-
|
27
|
+
* Build reports based on [grafana](https://github.com/grafana/grafana) dashboards, PDF
|
28
|
+
(default) and many other formats supported
|
29
|
+
* Easy-to-use configuration wizard, including fully automated functionality to create a
|
30
|
+
demo report
|
31
|
+
* Include dynamic content from grafana (find here a reference for all
|
32
|
+
[asciidcotor reporter calls](FUNCTION_CALLS.md)):
|
33
|
+
* panels as images
|
34
|
+
* tables based on grafana panel queries or custom database queries (no images!)
|
35
|
+
* single values to be integrated in text, based on grafana panel queries or custom
|
36
|
+
database queries
|
37
|
+
* Multi purpose use of the reporter
|
38
|
+
* webservice to be called directly from grafana
|
39
|
+
* standalone command line tool, e.g. to be automated with `cron` or `bash` scrips
|
40
|
+
* seemlessly runs from asciidocotor docker container without further dependencies
|
41
|
+
* Webhook callbacks before, on cancel and on finishing callbacks (see configuration file)
|
42
|
+
* Solid as a rock, also in case of template errors and whatever else may happen
|
43
|
+
* Full [API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) available
|
44
|
+
|
45
|
+
Functionalities are provided as shown here:
|
46
|
+
|
47
|
+
Database | Image rendering | Panel-based rendering | Query-based rendering
|
48
|
+
------------------------- | :-------: | :-----------: | :------------:
|
49
|
+
all SQL based datasources | supported | supported | supported
|
50
|
+
Graphite | supported | supported | supported
|
51
|
+
Prometheus | supported | supported | supported
|
52
|
+
other datasources | supported | not-supported | not-supported
|
53
|
+
|
54
|
+
## Quick Start
|
55
|
+
|
56
|
+
You don't have a grafana setup runnning already? No worries, just configure
|
57
|
+
`https://play.grafana.org` in the configuration wizard and see the magic
|
58
|
+
happen!
|
59
|
+
|
60
|
+
If your grafana setup requires a login, you'll have to setup an api key for
|
61
|
+
the reporter. Please follow the steps
|
62
|
+
[described here](https://github.com/divinity666/ruby-grafana-reporter/issues/2#issuecomment-811836757)
|
63
|
+
first.
|
64
|
+
|
65
|
+
**Windows:**
|
66
|
+
|
67
|
+
* [Download latest Windows executable](https://github.com/divinity666/ruby-grafana-reporter/releases/latest)
|
68
|
+
* `ruby-grafana-reporter -w`
|
69
|
+
|
70
|
+
**Raspberry Pi:**
|
71
|
+
|
72
|
+
* `sudo apt-get install ruby`
|
73
|
+
* `gem install ruby-grafana-reporter`
|
74
|
+
* `ruby-grafana-reporter -w`
|
75
|
+
|
76
|
+
**Ruby environment:**
|
77
|
+
|
78
|
+
* `gem install ruby-grafana-reporter`
|
79
|
+
* `ruby-grafana-reporter -w`
|
80
|
+
|
81
|
+
**Docker environment** (advanced users):
|
82
|
+
|
83
|
+
* [Download latest single-rb file](https://github.com/divinity666/ruby-grafana-reporter/releases/latest)
|
84
|
+
to an empty folder
|
85
|
+
* create a configuration file by calling `ruby ruby-grafana-reporter -w` (if in doubt,
|
86
|
+
run the command within your docker container)
|
87
|
+
* create file `/<<path-to-single-rb-file-folder>>/startup.sh` with the following
|
88
|
+
content:
|
89
|
+
|
90
|
+
```
|
91
|
+
cd /documents
|
92
|
+
ruby bin/ruby-grafana-reporter
|
93
|
+
```
|
94
|
+
* add asciidoctor your compose yaml:
|
95
|
+
|
96
|
+
```
|
97
|
+
asciidoctor:
|
98
|
+
image: asciidoctor/docker-asciidoctor
|
99
|
+
container_name: asciidoctor
|
100
|
+
hostname: asciidoctor
|
101
|
+
volumes:
|
102
|
+
- /<<path-to-single-rb-file-folder>>:/documents
|
103
|
+
command:
|
104
|
+
sh /documents/startup.sh
|
105
|
+
restart: unless-stopped
|
106
|
+
```
|
107
|
+
* start/restart the asciidoctor docker container
|
108
|
+
|
109
|
+
## Grafana integration
|
110
|
+
|
111
|
+
The key feature of the report is, that it can easily be integrated with grafana.
|
76
112
|
|
77
113
|
For accessing the reporter from grafana, you need to simply add a link to your
|
78
114
|
grafana dashboard:
|
@@ -82,27 +118,27 @@ grafana dashboard:
|
|
82
118
|
* Select `Add`
|
83
119
|
* Fill out as following:
|
84
120
|
* Type: `link`
|
85
|
-
* Url: `http://<<your-server-url>>:<<your-webservice-port>>/render?var-template=
|
86
|
-
* Title: `
|
121
|
+
* Url: `http://<<your-server-url>>:<<your-webservice-port>>/render?var-template=demo_report`
|
122
|
+
* Title: `Demo Report`
|
87
123
|
* Select `Time range`
|
88
124
|
* Select `Variable values`
|
89
125
|
* Select `Add`
|
90
126
|
|
91
|
-
Now go back to your dashboard and click the newly generated
|
127
|
+
Now go back to your dashboard and click the newly generated `Demo Report`
|
92
128
|
link on it. Now the renderer should start it's task and show you the expected
|
93
129
|
results.
|
94
130
|
|
95
|
-
|
96
|
-
|
97
|
-
|
131
|
+
Please note, that the reporter won't automatically refresh your screen to update
|
132
|
+
the progress. Simply hit `F5` to refresh your browser. After the report has been
|
133
|
+
successfully built, it will show the PDF after the next refresh automatically.
|
98
134
|
|
99
|
-
|
135
|
+
You want to select a template in grafana, which shall then be rendered?
|
100
136
|
Piece of cake: Just add a dashboard variable to your grafana dashboard named
|
101
137
|
`template` and let the user select or enter a template name. To make use of it,
|
102
|
-
you should change the link of the
|
103
|
-
`http://<<your-server-url>>:<<your-webservice-port>>/render
|
104
|
-
|
105
|
-
|
138
|
+
you should change the link of the `Demo Report` link to
|
139
|
+
`http://<<your-server-url>>:<<your-webservice-port>>/render?`. On
|
140
|
+
hitting the new link in the dashboard, grafana will add the selected template as
|
141
|
+
a variable and forward it to the reporter.
|
106
142
|
|
107
143
|
## Webservice overview
|
108
144
|
|
@@ -113,23 +149,15 @@ Running the reporter as a webservice provides the following URLs
|
|
113
149
|
/view_report - for viewing the status or receving the result of a specific rendering, is automatically called after a successfull /render call
|
114
150
|
/cancel_report - for cancelling the rendering of a specific report, normally not called manually, but on user interaction in the /view_report or /overview URL
|
115
151
|
|
116
|
-
|
152
|
+
The main endpoint to call for report generation is configured in the previous chapter [Grafana integration](#grafana-integration).
|
117
153
|
|
118
|
-
|
119
|
-
* panels as images
|
120
|
-
* panel table query or custom query results as real document tables (not images!)
|
121
|
-
* single panel value or custom query single value result integrated in texts
|
122
|
-
* Solid as a rock, also in case of template errors (at least it aims to be)
|
123
|
-
* Runs standalone or as a webservice
|
124
|
-
* Seamlessly integrates with asciidoctor docker container
|
125
|
-
* Developed for being able to support other tools than asciidoctor as well
|
154
|
+
However, if you would like to see, currently running report generations and previously generated reports, you may want to call the endpoint `/overview`.
|
126
155
|
|
127
156
|
## Roadmap
|
128
157
|
|
129
158
|
This is just a collection of things, I am heading for in future, without a schedule.
|
130
159
|
|
131
|
-
*
|
132
|
-
* Add a simple plugin system to support specific asciidoctor modifications
|
160
|
+
* Support all grafana datasources
|
133
161
|
* Solve code TODOs
|
134
162
|
* Become [rubocop](https://rubocop.org/) ready
|
135
163
|
|
@@ -138,14 +166,6 @@ This is just a collection of things, I am heading for in future, without a sched
|
|
138
166
|
If you'd like to contribute, please fork the repository and use a feature
|
139
167
|
branch. Pull requests are warmly welcome.
|
140
168
|
|
141
|
-
Though not yet valid for my code, I'd like to see the project become
|
142
|
-
[rubocop](https://rubocop.org/) ready :-)
|
143
|
-
|
144
|
-
Definitely open spots from my side are:
|
145
|
-
|
146
|
-
* This README
|
147
|
-
* Clean and properly setup test cases
|
148
|
-
|
149
169
|
## Licensing
|
150
170
|
|
151
171
|
The code in this project is licensed under MIT license.
|
@@ -160,7 +180,6 @@ Inspired by [Izak Marai's grafana reporter](https://github.com/IzakMarais/report
|
|
160
180
|
## Donations
|
161
181
|
|
162
182
|
If this project saves you as much time as I hope it does, and if you'd like to
|
163
|
-
support my work, feel free donate
|
183
|
+
support my work, feel free donate. :)
|
164
184
|
|
165
185
|
[](https://www.paypal.com/donate?hosted_button_id=35LH6JNLPHPHQ)
|
166
|
-
|
data/bin/ruby-grafana-reporter
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../lib/
|
5
|
-
GrafanaReporter::Application::Application.new.configure_and_run(ARGV)
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/ruby_grafana_reporter'
|
5
|
+
GrafanaReporter::Application::Application.new.configure_and_run(ARGV) unless defined?(Ocra)
|
data/lib/VERSION.rb
CHANGED
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grafana
|
4
|
+
# This abstract class defines the base functionalities for the common datasource implementations.
|
5
|
+
# Additionally it provides a factory method to build a real datasource from a given specification.
|
6
|
+
class AbstractDatasource
|
7
|
+
attr_reader :model
|
8
|
+
|
9
|
+
@@subclasses = []
|
10
|
+
|
11
|
+
# Registers the subclass as datasource, which is asked by {#accepts?}, if it can handle a datasource
|
12
|
+
# model.
|
13
|
+
# @param subclass [Class] class inheriting from this abstract class
|
14
|
+
def self.inherited(subclass)
|
15
|
+
@@subclasses << subclass
|
16
|
+
end
|
17
|
+
|
18
|
+
# Overwrite this method, to specify if the current datasource implementation handles the given model.
|
19
|
+
# This method is called by {#build_instance} to determine, if the current datasource implementation
|
20
|
+
# can handle the given grafana model. By default this method returns false.
|
21
|
+
# @param model [Hash] grafana specification of the datasource to check
|
22
|
+
# @return [Boolean] True if fits, false otherwise
|
23
|
+
def self.handles?(_model)
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
# Factory method to build a datasource from a given datasource Hash description.
|
28
|
+
# @param ds_model [Hash] grafana specification of a single datasource
|
29
|
+
# @return [AbstractDatasource] instance of a fitting datasource implementation
|
30
|
+
def self.build_instance(ds_model)
|
31
|
+
raise InvalidDatasourceQueryProvidedError, ds_model unless ds_model.is_a?(Hash)
|
32
|
+
|
33
|
+
raise InvalidDatasourceQueryProvidedError, ds_model unless ds_model['meta'].is_a?(Hash)
|
34
|
+
|
35
|
+
@@subclasses.each do |datasource_class|
|
36
|
+
return datasource_class.new(ds_model) if datasource_class.handles?(ds_model)
|
37
|
+
end
|
38
|
+
|
39
|
+
UnsupportedDatasource.new(ds_model)
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(model)
|
43
|
+
@model = model
|
44
|
+
end
|
45
|
+
|
46
|
+
# @return [String] category of the datasource, e.g. `tsdb` or `sql`
|
47
|
+
def category
|
48
|
+
@model['meta']['category']
|
49
|
+
end
|
50
|
+
|
51
|
+
# @return [String] type of the datasource, e.g. `mysql`
|
52
|
+
def type
|
53
|
+
@model['type'] || @model['meta']['id']
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return [String] name of the datasource
|
57
|
+
def name
|
58
|
+
@model['name']
|
59
|
+
end
|
60
|
+
|
61
|
+
# @return [Integer] ID of the datasource
|
62
|
+
def id
|
63
|
+
@model['id'].to_i
|
64
|
+
end
|
65
|
+
|
66
|
+
# @abstract
|
67
|
+
#
|
68
|
+
# Executes a request for the current database with the given options.
|
69
|
+
#
|
70
|
+
# Used format of the response will always be the following:
|
71
|
+
#
|
72
|
+
# {
|
73
|
+
# :header => [column_title_1, column_title_2],
|
74
|
+
# :content => [
|
75
|
+
# [row_1_column_1, row_1_column_2],
|
76
|
+
# [row_2_column_1, row_2_column_2]
|
77
|
+
# ]
|
78
|
+
# }
|
79
|
+
#
|
80
|
+
# @param query_description [Hash] query description, which will requested:
|
81
|
+
# @option [String] :from +from+ timestamp
|
82
|
+
# @option [String] :to +to+ timestamp
|
83
|
+
# @option [Integer] :timeout expected timeout for the request
|
84
|
+
# @option [WebRequest] :prepared_request prepared web request for relevant {Grafana} instance, if this is needed by datasource
|
85
|
+
# @option [String] :raw_query raw query, which shall be executed. May include variables, which will be replaced before execution
|
86
|
+
# @option [Hash<Variable>] :variables hash of variables, which can potentially be replaced in the given +:raw_query+
|
87
|
+
# @return [Hash] sql result formatted as stated above
|
88
|
+
def request(query_description)
|
89
|
+
raise NotImplementedError
|
90
|
+
end
|
91
|
+
|
92
|
+
# @abstract
|
93
|
+
#
|
94
|
+
# The different datasources supported by grafana use different ways to store the query in the
|
95
|
+
# panel's JSON model. This method extracts a query from that description, that can be used
|
96
|
+
# by the {AbstractDatasource} implementation of the datasource.
|
97
|
+
#
|
98
|
+
# @param panel_query_target [Hash] grafana panel target, which contains the query description
|
99
|
+
# @return [String] query string, which can be used as +raw_query+ in a {#request}
|
100
|
+
def raw_query_from_panel_model(panel_query_target)
|
101
|
+
raise NotImplementedError
|
102
|
+
end
|
103
|
+
|
104
|
+
private
|
105
|
+
|
106
|
+
# Replaces the grafana variables in the given string with their replacement value.
|
107
|
+
#
|
108
|
+
# @param string [String] string in which the variables shall be replaced
|
109
|
+
# @param variables [Hash<String,Variable>] Hash containing the variables, which shall be replaced in the
|
110
|
+
# given string
|
111
|
+
# @return [String] string in which all variables are properly replaced
|
112
|
+
def replace_variables(string, variables = {})
|
113
|
+
res = string
|
114
|
+
repeat = true
|
115
|
+
repeat_count = 0
|
116
|
+
|
117
|
+
# TODO: find a proper way to replace variables recursively instead of over and over again
|
118
|
+
# TODO: add tests for recursive replacement of variable
|
119
|
+
while repeat && (repeat_count < 3)
|
120
|
+
repeat = false
|
121
|
+
repeat_count += 1
|
122
|
+
variables.each do |var_name, obj|
|
123
|
+
# only set ticks if value is string
|
124
|
+
variable = var_name.gsub(/^var-/, '')
|
125
|
+
res = res.gsub(/(?:\$\{#{variable}(?::(?<format>\w+))?\}|\$#{variable})/) do
|
126
|
+
# TODO: respect datasource requirements for formatting here
|
127
|
+
obj.value_formatted($LAST_MATCH_INFO ? $LAST_MATCH_INFO[:format] : nil)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
repeat = true if res.include?('$')
|
131
|
+
end
|
132
|
+
|
133
|
+
res
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
data/lib/grafana/dashboard.rb
CHANGED
@@ -13,8 +13,8 @@ module Grafana
|
|
13
13
|
@grafana = grafana
|
14
14
|
@model = model
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
init_panels
|
17
|
+
init_variables
|
18
18
|
end
|
19
19
|
|
20
20
|
# @return [String] +from+ time configured in the dashboard.
|
@@ -42,35 +42,33 @@ module Grafana
|
|
42
42
|
|
43
43
|
panels.first
|
44
44
|
end
|
45
|
-
end
|
46
45
|
|
47
|
-
|
46
|
+
private
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
48
|
+
# store variables in array as objects of type Variable
|
49
|
+
def init_variables
|
50
|
+
@variables = []
|
51
|
+
return unless @model.key?('templating')
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
list = @model['templating']['list']
|
54
|
+
return unless list.is_a? Array
|
56
55
|
|
57
|
-
|
58
|
-
@variables << Variable.new(item)
|
56
|
+
list.each { |item| @variables << Variable.new(item) }
|
59
57
|
end
|
60
|
-
end
|
61
58
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
59
|
+
# read panels
|
60
|
+
def init_panels
|
61
|
+
@panels = []
|
62
|
+
return unless @model.key?('panels')
|
66
63
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
64
|
+
@model['panels'].each do |panel|
|
65
|
+
if panel.key?('panels')
|
66
|
+
panel['panels'].each do |subpanel|
|
67
|
+
@panels << Panel.new(subpanel, self)
|
68
|
+
end
|
69
|
+
else
|
70
|
+
@panels << Panel.new(panel, self)
|
71
71
|
end
|
72
|
-
else
|
73
|
-
@panels << Panel.new(panel, self)
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|