ruby-grafana-reporter 0.1.6
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 +7 -0
- data/LICENSE +20 -0
- data/README.md +248 -0
- data/lib/VERSION.rb +3 -0
- data/lib/grafana/abstract_panel_query.rb +20 -0
- data/lib/grafana/abstract_query.rb +127 -0
- data/lib/grafana/abstract_sql_query.rb +42 -0
- data/lib/grafana/dashboard.rb +66 -0
- data/lib/grafana/errors.rb +61 -0
- data/lib/grafana/grafana.rb +131 -0
- data/lib/grafana/panel.rb +39 -0
- data/lib/grafana/panel_image_query.rb +49 -0
- data/lib/grafana/variable.rb +259 -0
- data/lib/grafana_reporter/abstract_report.rb +109 -0
- data/lib/grafana_reporter/application/application.rb +229 -0
- data/lib/grafana_reporter/application/errors.rb +30 -0
- data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +99 -0
- data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +96 -0
- data/lib/grafana_reporter/asciidoctor/errors.rb +37 -0
- data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +86 -0
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +86 -0
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +67 -0
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +65 -0
- data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +58 -0
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +75 -0
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +70 -0
- data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +18 -0
- data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +41 -0
- data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +202 -0
- data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +67 -0
- data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +65 -0
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +57 -0
- data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +32 -0
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +23 -0
- data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +43 -0
- data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +36 -0
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +309 -0
- data/lib/grafana_reporter/asciidoctor/report.rb +159 -0
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +34 -0
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +32 -0
- data/lib/grafana_reporter/configuration.rb +326 -0
- data/lib/grafana_reporter/errors.rb +38 -0
- data/lib/grafana_reporter/logger/two_way_logger.rb +52 -0
- data/lib/ruby-grafana-reporter.rb +27 -0
- metadata +88 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1ed0c1b79ce0e155cc974eaa86c09221e106376660515903765cb9e78e9c00f1
|
4
|
+
data.tar.gz: 5e6fb779aa14cfbcc75f4f6916b24013fdcb036bf1a9fb46f844bbf0eaa99771
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: caac9139284da4855b6ca4686b4283129ca455ad0ad3b68b0e06c0232e48facacd4e813efe0960cb277f1d8d8ce64e30209af04fd6ab7eadac778a973c0192a3
|
7
|
+
data.tar.gz: b738db7b1bc73c95369682c977e7db4757920539ec07ba386f7b91af7ea3321403f759a75ad4041c3bd94756eea2c1e70bc24759e9a9ee72fcec871958c3d85f
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2020 Christian Kohlmeyer
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESs
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,248 @@
|
|
1
|
+
[](https://github.com/divinity666/ruby-grafana-reporter/blob/main/LICENSE)
|
2
|
+
|
3
|
+
# Ruby Grafana Reporter
|
4
|
+
(Asciidoctor) Reporter Service for Grafana
|
5
|
+
|
6
|
+
Did you ever want to create (professional) reports based on Grafana dashboards?
|
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
|
31
|
+
|
32
|
+
Download the ruby grafana reporter to a folder of your choice.
|
33
|
+
|
34
|
+
You may want to use the single file application as well. BTW, you may build
|
35
|
+
your own single file application by calling
|
36
|
+
|
37
|
+
ruby bin/get_single_file_application.rb
|
38
|
+
|
39
|
+
### Barebone ruby installation
|
40
|
+
|
41
|
+
To install on a plain ruby installation, follow these steps:
|
42
|
+
|
43
|
+
Install asciidoctor
|
44
|
+
|
45
|
+
gem install asciidoctor asciidoctor-pdf zip
|
46
|
+
|
47
|
+
or simply use
|
48
|
+
|
49
|
+
bundle install
|
50
|
+
|
51
|
+
To check if all dependencies are setup properly, run the following command
|
52
|
+
in that folder:
|
53
|
+
|
54
|
+
ruby bin/ruby-grafana-reporter.rb -h
|
55
|
+
|
56
|
+
### GEM installation
|
57
|
+
|
58
|
+
To install as a gem, simply run:
|
59
|
+
|
60
|
+
gem install ruby-grafana-reporter
|
61
|
+
|
62
|
+
To see if it works properly, you may run:
|
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.
|
81
|
+
|
82
|
+
## Initial Configuration
|
83
|
+
|
84
|
+
Create a first configuration file, named e.g. `myconfig` with the following
|
85
|
+
content:
|
86
|
+
|
87
|
+
grafana-reporter:
|
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: .
|
100
|
+
|
101
|
+
Check out if the configuration is valid and your grafana instance can be accessed
|
102
|
+
properly.
|
103
|
+
|
104
|
+
### Barebone ruby installation
|
105
|
+
|
106
|
+
ruby bin/ruby-grafana-reporter.rb myconfig --test default
|
107
|
+
|
108
|
+
### GEM installation
|
109
|
+
|
110
|
+
require 'ruby-grafana-reporter'
|
111
|
+
GrafanaReporter::Application::Application.new.configure_and_run(["myconfig", "--test", "default"])
|
112
|
+
|
113
|
+
### Docker integration
|
114
|
+
|
115
|
+
Same as in barebone ruby installation. Make sure you are running the command
|
116
|
+
from inside the container, e.g. by using `docker exec`.
|
117
|
+
|
118
|
+
## Hello World example
|
119
|
+
|
120
|
+
Create a first asciidoctor template file in your `templates-folder`, e.g.
|
121
|
+
`myfirsttemplate.adoc` with the following content:
|
122
|
+
|
123
|
+
= First Ruby Grafana Reporter Example
|
124
|
+
|
125
|
+
include::grafana_help[]
|
126
|
+
|
127
|
+
include::grafana_environment[]
|
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
|
150
|
+
|
151
|
+
Running the reporter as a webservice provides the following URLs
|
152
|
+
|
153
|
+
/render - for rendering a template
|
154
|
+
/overview - for all running or retained renderings
|
155
|
+
/view_report - for viewing the status or receving the result of a specific rendering
|
156
|
+
/cancel_report - for cancelling the rendering of a specific report
|
157
|
+
|
158
|
+
### Barebone ruby installation
|
159
|
+
|
160
|
+
ruby bin/ruby-grafana-reporter.rb myconfig
|
161
|
+
|
162
|
+
Test your configuration by requesting the following URL in a browser of your
|
163
|
+
choice:
|
164
|
+
|
165
|
+
http://<<your-server-url>>:8815/render?var-template=myfirsttemplate.adoc
|
166
|
+
|
167
|
+
### GEM installation
|
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.
|
199
|
+
|
200
|
+
Test your configuration by requesting the following URL in a browser of your
|
201
|
+
choice:
|
202
|
+
|
203
|
+
http://<<your-server-url>>:8815/render?var-template=myfirsttemplate.adoc
|
204
|
+
|
205
|
+
## Features
|
206
|
+
|
207
|
+
* Integrate grafana panel images, grafana panel query results as table or single values,
|
208
|
+
custom SQL query results as tables, alers, annotations and many more
|
209
|
+
* Solid as a rock, also in case of template errors (at least it aims to be)
|
210
|
+
* Runs standalone or as a webservice
|
211
|
+
* Seamlessly integrates with asciidoctor docker container
|
212
|
+
* Developed for being able to support other tools than asciidoctor as well
|
213
|
+
|
214
|
+
## Roadmap
|
215
|
+
|
216
|
+
This is just a collection of things, I am heading for in future, without a schedule.
|
217
|
+
|
218
|
+
* Add documentation for configuration file
|
219
|
+
* Share (anonymized) rspec tests in this repo
|
220
|
+
* Add a simple plugin system to support specific asciidoctor modifications
|
221
|
+
* Solve code TODOs
|
222
|
+
* Become [rubocop](https://rubocop.org/) ready
|
223
|
+
|
224
|
+
## Contributing
|
225
|
+
|
226
|
+
If you'd like to contribute, please fork the repository and use a feature
|
227
|
+
branch. Pull requests are warmly welcome.
|
228
|
+
|
229
|
+
Though not yet valid for my code, I'd like to see the project become
|
230
|
+
[rubocop](https://rubocop.org/) ready :-)
|
231
|
+
|
232
|
+
## Licensing
|
233
|
+
|
234
|
+
The code in this project is licensed under MIT license.
|
235
|
+
|
236
|
+
## Acknowledgements
|
237
|
+
* [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
238
|
+
* [asciidoctor-pdf](https://github.com/asciidoctor/asciidoctor-pdf)
|
239
|
+
|
240
|
+
Inspired by [Izak Marai's grafana reporter](https://github.com/IzakMarais/reporter)
|
241
|
+
|
242
|
+
## Donations
|
243
|
+
|
244
|
+
If this project saves you as much time as I hope it does, and if you'd like to
|
245
|
+
support my work, feel free donate, even a cup of coffee is appreciated :)
|
246
|
+
|
247
|
+
[](https://www.paypal.com/donate?hosted_button_id=35LH6JNLPHPHQ)
|
248
|
+
|
data/lib/VERSION.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'abstract_query'
|
2
|
+
|
3
|
+
module Grafana
|
4
|
+
# @abstract
|
5
|
+
#
|
6
|
+
# Used as a superclass for all queries, which rely on a {Panel} object.
|
7
|
+
#
|
8
|
+
# @see AbstractQuery
|
9
|
+
class AbstractPanelQuery < AbstractQuery
|
10
|
+
attr_reader :panel
|
11
|
+
|
12
|
+
# Initializes the variables of the query using {AbstractQuery#extract_dashboard_variables}.
|
13
|
+
# @param panel [Panel] panel for which the query shall be executed
|
14
|
+
def initialize(panel)
|
15
|
+
super()
|
16
|
+
@panel = panel
|
17
|
+
extract_dashboard_variables(@panel.dashboard)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Grafana
|
2
|
+
# @abstract Override {#url}, #{#request}, {#pre_process} and {#post_process} in subclass.
|
3
|
+
#
|
4
|
+
# Superclass containing everything for all queries towards grafana.
|
5
|
+
class AbstractQuery
|
6
|
+
attr_accessor :from, :to, :timeout, :result
|
7
|
+
attr_reader :variables
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@variables = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
# Runs the whole process to receive values properly from this query:
|
14
|
+
# - calls {#pre_process}
|
15
|
+
# - executes this query against the given {Grafana} instance
|
16
|
+
# - calls {#post_process}
|
17
|
+
# - returns the result
|
18
|
+
#
|
19
|
+
# @param grafana [Grafana] {Grafana} object, against which the query is executed
|
20
|
+
# @return [Object] result of the query
|
21
|
+
def execute(grafana)
|
22
|
+
return @result unless @result.nil?
|
23
|
+
|
24
|
+
pre_process(grafana)
|
25
|
+
@result = grafana.execute_http_request(url, request, timeout)
|
26
|
+
post_process
|
27
|
+
@result
|
28
|
+
end
|
29
|
+
|
30
|
+
# Used to retrieve default configurations from the given {Dashboard} and store them as settings in the query.
|
31
|
+
#
|
32
|
+
# Following data is extracted:
|
33
|
+
# - +from+, by {Dashboard#from_time}
|
34
|
+
# - +to+, by {Dashboard#to_time}
|
35
|
+
# - and all variables as {Variable}, prefixed with +var-+, as grafana also does it
|
36
|
+
def extract_dashboard_variables(dashboard)
|
37
|
+
@from = dashboard.from_time
|
38
|
+
@to = dashboard.to_time
|
39
|
+
dashboard.variables.each { |item| merge_variables({ "var-#{item.name}": item }) }
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# Merges the given Hash with the stored variables.
|
44
|
+
#
|
45
|
+
# Can be used to easily set many values at once in the local variables hash.
|
46
|
+
#
|
47
|
+
# Please note, that the values of the Hash need to be of type {Variable}.
|
48
|
+
#
|
49
|
+
# @param hash [Hash<String,Variable>] Hash containing variable name as key and {Variable} as value
|
50
|
+
# @return [AbstractQuery] this object
|
51
|
+
def merge_variables(hash)
|
52
|
+
hash.each do |k, v|
|
53
|
+
if @variables[k.to_s].nil?
|
54
|
+
@variables[k.to_s] = v
|
55
|
+
else
|
56
|
+
@variables[k.to_s].raw_value = v.raw_value
|
57
|
+
end
|
58
|
+
end
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return [Hash<String, Variable>] all grafana variables stored in this query, i.e. the variable name is prefixed with +var-+
|
63
|
+
def grafana_variables
|
64
|
+
@variables.select { |k, _v| k =~ /^var-.+/ }
|
65
|
+
end
|
66
|
+
|
67
|
+
# Replaces the grafana variables in the given string with their replacement value.
|
68
|
+
#
|
69
|
+
# @param string [String] string in which the variables shall be replaced
|
70
|
+
# @param variables [Hash<String,Variable>] Hash containing the variables, which shall be replaced in the given string
|
71
|
+
# @return [String] string in which all variables are properly replaced
|
72
|
+
def replace_variables(string, variables = {})
|
73
|
+
res = string
|
74
|
+
repeat = true
|
75
|
+
repeat_count = 0
|
76
|
+
|
77
|
+
# TODO find a proper way to replace variables recursively instead of over and over again
|
78
|
+
# TODO add tests for recursive replacement of variable
|
79
|
+
while repeat and repeat_count < 3
|
80
|
+
repeat = false
|
81
|
+
repeat_count += 1
|
82
|
+
variables.each do |var_name, obj|
|
83
|
+
# only set ticks if value is string
|
84
|
+
variable = var_name.gsub(/^var-/, '')
|
85
|
+
res = res.gsub(/(?:\$\{#{variable}(?::(?<format>[\w]+))?\}|(?<!\.)\$#{variable}(?!\.))/) do
|
86
|
+
obj.value_formatted($~[:format])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
repeat = true if res.include?('$')
|
90
|
+
end
|
91
|
+
|
92
|
+
res
|
93
|
+
end
|
94
|
+
|
95
|
+
# @abstract
|
96
|
+
#
|
97
|
+
# @return [String] String containing the relative URL to execute the query
|
98
|
+
def uri
|
99
|
+
raise NotImplementedError
|
100
|
+
end
|
101
|
+
|
102
|
+
# @abstract
|
103
|
+
#
|
104
|
+
# @return [Hash] Hash containing the request parameters, which shall be overwritten or extended in {Grafana#execute_http_request}
|
105
|
+
def request
|
106
|
+
raise NotImplementedError
|
107
|
+
end
|
108
|
+
|
109
|
+
# @abstract
|
110
|
+
#
|
111
|
+
# Use this function to perform all necessary actions, before the query is actually executed.
|
112
|
+
# Here you can e.g. set values of variables or similar.
|
113
|
+
#
|
114
|
+
# @param grafana [Grafana] {Grafana} object, against which the query shall be executed
|
115
|
+
def pre_process(grafana)
|
116
|
+
raise NotImplementedError
|
117
|
+
end
|
118
|
+
|
119
|
+
# @abstract
|
120
|
+
#
|
121
|
+
# Use this function to format the raw result of the @result variable to conform to the expected return value.
|
122
|
+
# You might also want to {#replace_variables} in the @result or similar.
|
123
|
+
def post_process
|
124
|
+
raise NotImplementedError
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Grafana
|
2
|
+
# @abstract
|
3
|
+
#
|
4
|
+
# Used as a superclass for all queries, which execute SQL queries against {Grafana}.
|
5
|
+
#
|
6
|
+
# @see AbstractQuery
|
7
|
+
class AbstractSqlQuery < AbstractQuery
|
8
|
+
attr_reader :sql, :datasource_id
|
9
|
+
|
10
|
+
# @param raw_sql [String] raw sql statement, as it can be sent to a SQL database
|
11
|
+
# @param datasource_id [Integer] ID of the datasource against which the query is run
|
12
|
+
def initialize(raw_sql, datasource_id)
|
13
|
+
super()
|
14
|
+
@sql = raw_sql
|
15
|
+
@datasource_id = datasource_id
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [String] relative URL, where the request has to be sent to.
|
19
|
+
def url
|
20
|
+
'/api/tsdb/query'
|
21
|
+
end
|
22
|
+
|
23
|
+
# @return [Hash] request, which executes the SQL statement against the specified datasource
|
24
|
+
def request
|
25
|
+
{ body: { from: @from, to: @to, queries: [rawSql: @sql, datasourceId: @datasource_id.to_i, format: 'table'] }.to_json, request: Net::HTTP::Post }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Replaces all variables in the SQL statement.
|
29
|
+
def pre_process(grafana)
|
30
|
+
raise MissingSqlQueryError if @sql.nil?
|
31
|
+
unless grafana.datasource_id_exists?(@datasource_id.to_i)
|
32
|
+
raise DatasourceDoesNotExistError.new('id', @datasource_id)
|
33
|
+
end
|
34
|
+
|
35
|
+
@sql = replace_variables(@sql, grafana_variables)
|
36
|
+
# remove comments in query
|
37
|
+
@sql.gsub!(/--[^\r\n]*(?:[\r\n]+|$)/, ' ')
|
38
|
+
@sql.gsub!(/\r\n/, ' ')
|
39
|
+
@sql.gsub!(/\n/, ' ')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|