ruby-grafana-reporter 0.1.6 → 0.3.0
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/LICENSE +0 -0
- data/README.md +95 -173
- data/bin/ruby-grafana-reporter +5 -0
- data/lib/VERSION.rb +5 -3
- data/lib/grafana/abstract_panel_query.rb +22 -20
- data/lib/grafana/abstract_query.rb +132 -127
- data/lib/grafana/abstract_sql_query.rb +51 -42
- data/lib/grafana/dashboard.rb +77 -66
- data/lib/grafana/errors.rb +66 -61
- data/lib/grafana/grafana.rb +133 -131
- data/lib/grafana/panel.rb +41 -39
- data/lib/grafana/panel_image_query.rb +52 -49
- data/lib/grafana/variable.rb +217 -259
- data/lib/grafana_reporter/abstract_report.rb +112 -109
- data/lib/grafana_reporter/application/application.rb +158 -229
- data/lib/grafana_reporter/application/errors.rb +33 -30
- data/lib/grafana_reporter/application/webservice.rb +230 -0
- data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +101 -99
- data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +96 -96
- data/lib/grafana_reporter/asciidoctor/errors.rb +40 -37
- data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +92 -86
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +91 -86
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +69 -67
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +68 -65
- data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +61 -58
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +78 -75
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +73 -70
- data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +20 -18
- data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +43 -41
- data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +30 -202
- data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +70 -67
- data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +66 -65
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +88 -57
- data/lib/grafana_reporter/asciidoctor/help.rb +435 -0
- data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +36 -32
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +28 -23
- data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +44 -43
- data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +40 -36
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +312 -309
- data/lib/grafana_reporter/asciidoctor/report.rb +179 -159
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +42 -34
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +44 -32
- data/lib/grafana_reporter/configuration.rb +304 -326
- data/lib/grafana_reporter/console_configuration_wizard.rb +269 -0
- data/lib/grafana_reporter/errors.rb +48 -38
- data/lib/grafana_reporter/logger/two_way_logger.rb +58 -52
- data/lib/ruby-grafana-reporter.rb +32 -27
- metadata +116 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '00728deba4250ed327170393bbeaac1b1d6d1002463a5a243285ac570f09231f'
|
4
|
+
data.tar.gz: 2985a11f6404e622ff279dbe3e328b38e4202bf665b2fef9e23746bbfd6c3459
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 92de552918a451f9bac1196dfbb05dc1ad64e0059f4c90fe06c079e5e181fee96a07858ae0c5815e3dbf37358c4aa271fcd8d129bb6721f3c8a53f285325fc25
|
7
|
+
data.tar.gz: aff95df6e4b5a8636905ec498433d1fcdae6d7b9aa2d26640815a68160c2f74c39078adfbe32a67c9115855ddd97683c6844ea0347e18cf010586e2bd036faed
|
data/LICENSE
CHANGED
File without changes
|
data/README.md
CHANGED
@@ -1,234 +1,155 @@
|
|
1
|
-
[](https://github.com/divinity666/ruby-grafana-reporter/blob/
|
1
|
+
[](https://github.com/divinity666/ruby-grafana-reporter/blob/master/LICENSE)
|
2
|
+
[](https://travis-ci.org/github/divinity666/ruby-grafana-reporter?branch=master)
|
3
|
+
[](https://coveralls.io/github/divinity666/ruby-grafana-reporter?branch=master)
|
4
|
+
[](https://badge.fury.io/rb/ruby-grafana-reporter)
|
2
5
|
|
3
6
|
# Ruby Grafana Reporter
|
4
|
-
|
7
|
+
Reporting Service for Grafana
|
5
8
|
|
6
|
-
|
7
|
-
I did so in order to being able to automatically get monthly reports of my
|
8
|
-
home's energy usage. That's how it started.
|
9
|
-
|
10
|
-
The reporter provides a full extension setup for the famous
|
11
|
-
[Asciidoctor](https://github.com/asciidoctor/asciidoctor) and can perfectly
|
12
|
-
integrate in a docker environment.
|
13
|
-
|
14
|
-
As a result of the reporter, you receive PDF documents or any other format that
|
15
|
-
is supported by [Asciidoctor](https://github.com/asciidoctor/asciidoctor).
|
16
|
-
|
17
|
-
## Documentation
|
18
|
-
|
19
|
-
Find the complete
|
20
|
-
[API documentation](https://rubydoc.info/github/divinity666/ruby-grafana-reporter)
|
21
|
-
at this link.
|
22
|
-
|
23
|
-
## Installing
|
24
|
-
|
25
|
-
There exist several ways of installing the reporter. All of them have in
|
26
|
-
common, that they require a working ruby environment. Check with the following
|
27
|
-
commands, that the tools are setup and run properly:
|
28
|
-
|
29
|
-
ruby -v
|
30
|
-
gem -v
|
9
|
+
## Table of Contents
|
31
10
|
|
32
|
-
|
11
|
+
* [About the project](#about-the-project)
|
12
|
+
* [Getting started](#getting-started)
|
13
|
+
* [Grafana integration](#grafana-integration)
|
14
|
+
* [Webservice overview](#webservice-overview)
|
15
|
+
* [Documentation](#documentation)
|
16
|
+
* [Features](#features)
|
17
|
+
* [Roadmap](#roadmap)
|
18
|
+
* [Contributing](#contributing)
|
19
|
+
* [Licensing](#licensing)
|
20
|
+
* [Acknowledgements](#acknowledgements)
|
21
|
+
* [Donations](#donations)
|
33
22
|
|
34
|
-
|
35
|
-
your own single file application by calling
|
23
|
+
## About the project
|
36
24
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
To install on a plain ruby installation, follow these steps:
|
25
|
+
Did you ever want to create (professional) reports based on Grafana dashboards?
|
26
|
+
I did so in order to being able to automatically get monthly reports of my
|
27
|
+
home's energy usage. That's how it started.
|
42
28
|
|
43
|
-
|
29
|
+
The reporter provides reporting capabilities for Grafana. It is based on
|
30
|
+
(but not limited to) [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
31
|
+
report templates, which can dynamically integrate Grafana panels, queries,
|
32
|
+
images etc. to create dynamic PDF reports on the fly.
|
44
33
|
|
45
|
-
|
34
|
+
The report may also be returned in any other format that asciidoctor supports.
|
46
35
|
|
47
|
-
or
|
36
|
+
The reporter can run standalone or as a webservice. It is built to
|
37
|
+
integrate without further dependencies with the asciidoctor docker image.
|
48
38
|
|
49
|
-
|
39
|
+
Can't wait to see, what functions the reporter provides within the asciidoctor
|
40
|
+
templates? Have a look at the [function documentation](FUNCTION_CALLS.md).
|
50
41
|
|
51
|
-
|
52
|
-
in that folder:
|
42
|
+
## Getting started
|
53
43
|
|
54
|
-
|
44
|
+
There exist several ways of installing the reporter. If you need further
|
45
|
+
installation help, or want to use a "baremetal" ruby setup or a docker
|
46
|
+
integration, please have a look at the more extended
|
47
|
+
[installation documentation](INSTALL.md).
|
55
48
|
|
56
|
-
|
49
|
+
Windows users may directly use the provided executable.
|
57
50
|
|
58
|
-
|
51
|
+
Following these steps sets up the reporter on a fresh Raspberry Pi installation:
|
59
52
|
|
53
|
+
sudo apt-get install ruby
|
60
54
|
gem install ruby-grafana-reporter
|
61
55
|
|
62
|
-
|
63
|
-
|
64
|
-
irb
|
65
|
-
require 'ruby-grafana-reporter'
|
66
|
-
GrafanaReporter::Application::Application.new.configure_and_run
|
67
|
-
|
68
|
-
The gem installation might mainly be interesting, if you would like to use the
|
69
|
-
reporter as a library and include it in other application setups.
|
70
|
-
|
71
|
-
### Docker integration
|
72
|
-
|
73
|
-
Essentially you need to make the application available within your asciidoctor
|
74
|
-
docker container and run the following command
|
75
|
-
|
76
|
-
ruby bin/ruby-grafana-reporter.rb -h
|
77
|
-
|
78
|
-
If you are unsure, on how to make it available in the container, you may refer
|
79
|
-
to the information in chapter 'Run as a service' for the docker integration
|
80
|
-
below.
|
56
|
+
That's it. Let's now configure a grafana setup with the configuration wizard:
|
81
57
|
|
82
|
-
|
58
|
+
ruby-grafana-reporter -w
|
83
59
|
|
84
|
-
|
85
|
-
|
60
|
+
It is strongly recommended, to also create the demo PDF file, as stated at the end
|
61
|
+
of the procedure, to get a detailed documentation of all the reporter capabilities.
|
62
|
+
The whole [function documentation](FUNCTION_CALLS.md) is also available at the
|
63
|
+
previous link.
|
86
64
|
|
87
|
-
|
88
|
-
templates-folder: templates
|
89
|
-
reports-folder: reports
|
90
|
-
|
91
|
-
grafana:
|
92
|
-
default:
|
93
|
-
host: <<url to your grafana host, e.g. https://localhost:3000>>
|
94
|
-
api_key: <<api key to be used by the reporter>>
|
95
|
-
datasources: # mandatory, if the api_key has only viewer rights, optional otherwise
|
96
|
-
"<<data source name in grafana>>": <<data source id in grafana>>
|
97
|
-
|
98
|
-
default-document-attributes:
|
99
|
-
imagesdir: .
|
65
|
+
To run the reporter as a service, you only need to call it like this:
|
100
66
|
|
101
|
-
|
102
|
-
properly.
|
67
|
+
ruby-grafana-reporter
|
103
68
|
|
104
|
-
|
69
|
+
Neat, isn't it?
|
105
70
|
|
106
|
-
|
71
|
+
### Grafana integration
|
107
72
|
|
108
|
-
|
73
|
+
The key feature of the report is, that it can easily be integrated with grafana
|
74
|
+
(I've not even been talking about the features it is providing for that, but
|
75
|
+
you'll find them having a look in the example results above).
|
109
76
|
|
110
|
-
|
111
|
-
|
77
|
+
For accessing the reporter from grafana, you need to simply add a link to your
|
78
|
+
grafana dashboard:
|
112
79
|
|
113
|
-
|
80
|
+
* Open the dashboard configuration
|
81
|
+
* Select `Links`
|
82
|
+
* Select `Add`
|
83
|
+
* Fill out as following:
|
84
|
+
* Type: `link`
|
85
|
+
* Url: `http://<<your-server-url>>:<<your-webservice-port>>/render?var-template=myfirsttemplate`
|
86
|
+
* Title: `MyFirstReport`
|
87
|
+
* Select `Time range`
|
88
|
+
* Select `Variable values`
|
89
|
+
* Select `Add`
|
114
90
|
|
115
|
-
|
116
|
-
|
91
|
+
Now go back to your dashboard and click the newly generated 'MyFirstReport'
|
92
|
+
link on it. Now the renderer should start it's task and show you the expected
|
93
|
+
results.
|
117
94
|
|
118
|
-
|
95
|
+
But now the fun just starts! Try out the functions stated in the
|
96
|
+
'MyFirstReport' PDF file, to include the dynamic content in your asciidoctor
|
97
|
+
template.
|
119
98
|
|
120
|
-
|
121
|
-
|
99
|
+
Additionally you might want to make the selection of the template variable.
|
100
|
+
Piece of cake: Just add a dashboard variable to your grafana dashboard named
|
101
|
+
`template` and let the user select or enter a template name. To make use of it,
|
102
|
+
you should change the link of the 'MyFirstReport' link to
|
103
|
+
`http://<<your-server-url>>:<<your-webservice-port>>/render?`
|
122
104
|
|
123
|
-
|
124
|
-
|
125
|
-
include::grafana_help[]
|
105
|
+
That's it. Let me know your feedback!
|
126
106
|
|
127
|
-
|
128
|
-
|
129
|
-
Now you're ready to go! Let's check it out!
|
130
|
-
|
131
|
-
### Barebone ruby installation
|
132
|
-
|
133
|
-
ruby bin/ruby-grafana-reporter.rb myconfig --template myfirsttemplate.adoc --output myfirstrender.pdf
|
134
|
-
|
135
|
-
You should now find a PDF document named `myfirstrender.pdf` which includes a detailed
|
136
|
-
help page on how to use the ruby grafana reporter functions in asciidoctor, as well
|
137
|
-
as a list of all environment variables that can be accessed.
|
138
|
-
|
139
|
-
### GEM installation
|
140
|
-
|
141
|
-
require 'ruby-grafana-reporter'
|
142
|
-
GrafanaReporter::Application::Application.new.configure_and_run(["myconfig", "--template", "myfirsttemplate.adoc", "--output", "myfirstrender.pdf"])
|
143
|
-
|
144
|
-
### Docker integration
|
145
|
-
|
146
|
-
Same as in barebone ruby installation. Make sure you are running the command
|
147
|
-
from inside the container, e.g. by using `docker exec`.
|
148
|
-
|
149
|
-
## Run as a service
|
107
|
+
## Webservice overview
|
150
108
|
|
151
109
|
Running the reporter as a webservice provides the following URLs
|
152
110
|
|
153
|
-
/render - for rendering a template
|
154
111
|
/overview - for all running or retained renderings
|
155
|
-
/
|
156
|
-
/
|
157
|
-
|
158
|
-
### Barebone ruby installation
|
159
|
-
|
160
|
-
ruby bin/ruby-grafana-reporter.rb myconfig
|
112
|
+
/render - for rendering a template, 'var-template' is the only mandatory GET parameter
|
113
|
+
/view_report - for viewing the status or receving the result of a specific rendering, is automatically called after a successfull /render call
|
114
|
+
/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
|
161
115
|
|
162
|
-
|
163
|
-
choice:
|
116
|
+
The main endpoint to call for report generation is configured in the previous chapter [Grafana integration](#grafana-integration).
|
164
117
|
|
165
|
-
|
118
|
+
However, if you would like to see, currently running report generations and previously generated reports, you may want to call the endpoint `/overview`.
|
166
119
|
|
167
|
-
|
168
|
-
|
169
|
-
require 'ruby-grafana-reporter'
|
170
|
-
GrafanaReporter::Application::Application.new.configure_and_run(["myconfig"])
|
171
|
-
|
172
|
-
Test your configuration by requesting the following URL in a browser of your
|
173
|
-
choice:
|
174
|
-
|
175
|
-
http://<<your-server-url>>:8815/render?var-template=myfirsttemplate.adoc
|
176
|
-
|
177
|
-
### Docker integration
|
178
|
-
|
179
|
-
Assuming you have a `docker-compose` setup running, you may want to add the
|
180
|
-
following to your services secion in your `docker-compose.yml`:
|
181
|
-
|
182
|
-
asciidoctor:
|
183
|
-
image: asciidoctor/docker-asciidoctor
|
184
|
-
container_name: asciidoctor
|
185
|
-
hostname: asciidoctor
|
186
|
-
volumes:
|
187
|
-
- /<<an-empty-local-path>>:/documents
|
188
|
-
command:
|
189
|
-
sh /documents/startup.sh
|
190
|
-
restart: unless-stopped
|
191
|
-
|
192
|
-
Additionally you need to create a `startup.sh` file in the folder
|
193
|
-
`<<an-empty-local-path>>` with the following content:
|
194
|
-
|
195
|
-
cd /documents
|
196
|
-
ruby bin/ruby-grafana-reporter.rb myconfig
|
197
|
-
|
198
|
-
After restarting the container, the service should be running.
|
120
|
+
## Documentation
|
199
121
|
|
200
|
-
|
201
|
-
|
122
|
+
The [function documentation](FUNCTION_CALLS.md) contains a complete overview of
|
123
|
+
all possible grafana calls, to generate dynamic report templates.
|
202
124
|
|
203
|
-
|
125
|
+
The [API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) can be
|
126
|
+
found here.
|
204
127
|
|
205
128
|
## Features
|
206
129
|
|
207
|
-
*
|
208
|
-
|
209
|
-
*
|
210
|
-
*
|
130
|
+
* Build report template including all imaginable grafana content:
|
131
|
+
* panels as images
|
132
|
+
* panel table query or custom query results as real document tables (not images!)
|
133
|
+
* single panel value or custom query single value result integrated in texts
|
134
|
+
* Solid as a rock, also in case of template errors and whatever else may happen
|
135
|
+
* Fully controllable as command line application or as a webservice
|
211
136
|
* Seamlessly integrates with asciidoctor docker container
|
212
|
-
* Developed
|
137
|
+
* Developed to support other tools than asciidoctor as well
|
213
138
|
|
214
139
|
## Roadmap
|
215
140
|
|
216
141
|
This is just a collection of things, I am heading for in future, without a schedule.
|
217
142
|
|
218
|
-
* Add documentation for configuration file
|
219
|
-
* Share (anonymized) rspec tests in this repo
|
220
143
|
* Add a simple plugin system to support specific asciidoctor modifications
|
221
144
|
* Solve code TODOs
|
222
145
|
* Become [rubocop](https://rubocop.org/) ready
|
146
|
+
* Clean and properly setup test cases
|
223
147
|
|
224
148
|
## Contributing
|
225
149
|
|
226
150
|
If you'd like to contribute, please fork the repository and use a feature
|
227
151
|
branch. Pull requests are warmly welcome.
|
228
152
|
|
229
|
-
Though not yet valid for my code, I'd like to see the project become
|
230
|
-
[rubocop](https://rubocop.org/) ready :-)
|
231
|
-
|
232
153
|
## Licensing
|
233
154
|
|
234
155
|
The code in this project is licensed under MIT license.
|
@@ -236,6 +157,7 @@ The code in this project is licensed under MIT license.
|
|
236
157
|
## Acknowledgements
|
237
158
|
* [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
238
159
|
* [asciidoctor-pdf](https://github.com/asciidoctor/asciidoctor-pdf)
|
160
|
+
* [grafana](https://github.com/grafana/grafana)
|
239
161
|
|
240
162
|
Inspired by [Izak Marai's grafana reporter](https://github.com/IzakMarais/reporter)
|
241
163
|
|
data/lib/VERSION.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'abstract_query'
|
4
|
+
|
5
|
+
module Grafana
|
6
|
+
# @abstract
|
7
|
+
#
|
8
|
+
# Used as a superclass for all queries, which rely on a {Panel} object.
|
9
|
+
#
|
10
|
+
# @see AbstractQuery
|
11
|
+
class AbstractPanelQuery < AbstractQuery
|
12
|
+
attr_reader :panel
|
13
|
+
|
14
|
+
# Initializes the variables of the query using {AbstractQuery#extract_dashboard_variables}.
|
15
|
+
# @param panel [Panel] panel for which the query shall be executed
|
16
|
+
def initialize(panel)
|
17
|
+
super()
|
18
|
+
@panel = panel
|
19
|
+
extract_dashboard_variables(@panel.dashboard)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,127 +1,132 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
#
|
16
|
-
# - calls {#
|
17
|
-
# -
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@result
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
# -
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
48
|
-
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
@variables[k.to_s]
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
#
|
71
|
-
#
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
# @
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# @
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Grafana
|
4
|
+
# @abstract Override {#url}, #{#request}, {#pre_process} and {#post_process} in subclass.
|
5
|
+
#
|
6
|
+
# Superclass containing everything for all queries towards grafana.
|
7
|
+
class AbstractQuery
|
8
|
+
attr_accessor :from, :to, :timeout, :result
|
9
|
+
attr_reader :variables
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@variables = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Runs the whole process to receive values properly from this query:
|
16
|
+
# - calls {#pre_process}
|
17
|
+
# - executes this query against the given {Grafana} instance
|
18
|
+
# - calls {#post_process}
|
19
|
+
# - returns the result
|
20
|
+
#
|
21
|
+
# @param grafana [Grafana] {Grafana} object, against which the query is executed
|
22
|
+
# @return [Object] result of the query
|
23
|
+
def execute(grafana)
|
24
|
+
return @result unless @result.nil?
|
25
|
+
|
26
|
+
pre_process(grafana)
|
27
|
+
@result = grafana.execute_http_request(url, request, timeout)
|
28
|
+
post_process
|
29
|
+
@result
|
30
|
+
end
|
31
|
+
|
32
|
+
# Used to retrieve default configurations from the given {Dashboard} and store them as settings in the query.
|
33
|
+
#
|
34
|
+
# Following data is extracted:
|
35
|
+
# - +from+, by {Dashboard#from_time}
|
36
|
+
# - +to+, by {Dashboard#to_time}
|
37
|
+
# - and all variables as {Variable}, prefixed with +var-+, as grafana also does it
|
38
|
+
def extract_dashboard_variables(dashboard)
|
39
|
+
@from = dashboard.from_time
|
40
|
+
@to = dashboard.to_time
|
41
|
+
dashboard.variables.each { |item| merge_variables({ "var-#{item.name}": item }) }
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
# Merges the given Hash with the stored variables.
|
46
|
+
#
|
47
|
+
# Can be used to easily set many values at once in the local variables hash.
|
48
|
+
#
|
49
|
+
# Please note, that the values of the Hash need to be of type {Variable}.
|
50
|
+
#
|
51
|
+
# @param hash [Hash<String,Variable>] Hash containing variable name as key and {Variable} as value
|
52
|
+
# @return [AbstractQuery] this object
|
53
|
+
def merge_variables(hash)
|
54
|
+
hash.each do |k, v|
|
55
|
+
if @variables[k.to_s].nil?
|
56
|
+
@variables[k.to_s] = v
|
57
|
+
else
|
58
|
+
@variables[k.to_s].raw_value = v.raw_value
|
59
|
+
end
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# @return [Hash<String, Variable>] all grafana variables stored in this query, i.e. the variable name
|
65
|
+
# is prefixed with +var-+
|
66
|
+
def grafana_variables
|
67
|
+
@variables.select { |k, _v| k =~ /^var-.+/ }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Replaces the grafana variables in the given string with their replacement value.
|
71
|
+
#
|
72
|
+
# @param string [String] string in which the variables shall be replaced
|
73
|
+
# @param variables [Hash<String,Variable>] Hash containing the variables, which shall be replaced in the
|
74
|
+
# given string
|
75
|
+
# @return [String] string in which all variables are properly replaced
|
76
|
+
def replace_variables(string, variables = {})
|
77
|
+
res = string
|
78
|
+
repeat = true
|
79
|
+
repeat_count = 0
|
80
|
+
|
81
|
+
# TODO: find a proper way to replace variables recursively instead of over and over again
|
82
|
+
# TODO: add tests for recursive replacement of variable
|
83
|
+
while repeat && (repeat_count < 3)
|
84
|
+
repeat = false
|
85
|
+
repeat_count += 1
|
86
|
+
variables.each do |var_name, obj|
|
87
|
+
# only set ticks if value is string
|
88
|
+
variable = var_name.gsub(/^var-/, '')
|
89
|
+
res = res.gsub(/(?:\$\{#{variable}(?::(?<format>\w+))?\}|(?<!\.)\$#{variable}(?!\.))/) do
|
90
|
+
obj.value_formatted($LAST_MATCH_INFO ? $LAST_MATCH_INFO[:format] : nil)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
repeat = true if res.include?('$')
|
94
|
+
end
|
95
|
+
|
96
|
+
res
|
97
|
+
end
|
98
|
+
|
99
|
+
# @abstract
|
100
|
+
#
|
101
|
+
# @return [String] String containing the relative URL to execute the query
|
102
|
+
def uri
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
|
106
|
+
# @abstract
|
107
|
+
#
|
108
|
+
# @return [Hash] Hash containing the request parameters, which shall be overwritten or extended in
|
109
|
+
# {Grafana#execute_http_request}
|
110
|
+
def request
|
111
|
+
raise NotImplementedError
|
112
|
+
end
|
113
|
+
|
114
|
+
# @abstract
|
115
|
+
#
|
116
|
+
# Use this function to perform all necessary actions, before the query is actually executed.
|
117
|
+
# Here you can e.g. set values of variables or similar.
|
118
|
+
#
|
119
|
+
# @param grafana [Grafana] {Grafana} object, against which the query shall be executed
|
120
|
+
def pre_process(grafana)
|
121
|
+
raise NotImplementedError
|
122
|
+
end
|
123
|
+
|
124
|
+
# @abstract
|
125
|
+
#
|
126
|
+
# Use this function to format the raw result of the @result variable to conform to the expected return value.
|
127
|
+
# You might also want to {#replace_variables} in the @result or similar.
|
128
|
+
def post_process
|
129
|
+
raise NotImplementedError
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|