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
@@ -6,21 +6,48 @@ module GrafanaReporter
|
|
6
6
|
# make use of `webrick` or similar, so that it can be used without futher dependencies
|
7
7
|
# in conjunction with the standard asciidoctor docker container.
|
8
8
|
class Webservice
|
9
|
-
|
9
|
+
# Array of possible webservice running states
|
10
|
+
STATUS = %I[stopped running stopping].freeze
|
11
|
+
|
12
|
+
def initialize
|
10
13
|
@reports = []
|
14
|
+
@status = :stopped
|
15
|
+
end
|
16
|
+
|
17
|
+
# Runs the webservice with the given {Configuration} object.
|
18
|
+
def run(config)
|
11
19
|
@config = config
|
12
20
|
@logger = config.logger
|
13
|
-
end
|
14
21
|
|
15
|
-
# Runs the webservice with the current set {Configuration} object.
|
16
|
-
def run
|
17
22
|
# start webserver
|
18
23
|
@server = TCPServer.new(@config.webserver_port)
|
19
24
|
@logger.info("Server listening on port #{@config.webserver_port}...")
|
20
25
|
|
21
26
|
@progress_reporter = Thread.new {}
|
22
27
|
|
28
|
+
@status = :running
|
23
29
|
accept_requests_loop
|
30
|
+
@status = :stopped
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return True, if webservice is stopped, false otherwise
|
34
|
+
def stopped?
|
35
|
+
@status == :stopped
|
36
|
+
end
|
37
|
+
|
38
|
+
# @return True, if webservice is up and running, false otherwise
|
39
|
+
def running?
|
40
|
+
@status == :running
|
41
|
+
end
|
42
|
+
|
43
|
+
# Forces stopping the webservice.
|
44
|
+
def stop!
|
45
|
+
@status = :stopping
|
46
|
+
|
47
|
+
# invoke a new request, so that the webservice stops.
|
48
|
+
socket = TCPSocket.new('localhost', @config.webserver_port)
|
49
|
+
socket.send '', 0
|
50
|
+
socket.close
|
24
51
|
end
|
25
52
|
|
26
53
|
private
|
@@ -30,6 +57,14 @@ module GrafanaReporter
|
|
30
57
|
# step 1) accept incoming connection
|
31
58
|
socket = @server.accept
|
32
59
|
|
60
|
+
# TODO: shutdown properly on SIGINT/SIGHUB
|
61
|
+
|
62
|
+
# stop webservice properly, if shall be shutdown
|
63
|
+
if @status == :stopping
|
64
|
+
socket.close
|
65
|
+
break
|
66
|
+
end
|
67
|
+
|
33
68
|
# step 2) print the request headers (separated by a blank line e.g. \r\n)
|
34
69
|
request = ''
|
35
70
|
line = ''
|
@@ -48,9 +83,6 @@ module GrafanaReporter
|
|
48
83
|
rescue WebserviceUnknownPathError => e
|
49
84
|
@logger.debug(e.message)
|
50
85
|
socket.write http_response(404, '', e.message)
|
51
|
-
rescue MissingTemplateError => e
|
52
|
-
@logger.error(e.message)
|
53
|
-
socket.write http_response(400, 'Bad Request', e.message)
|
54
86
|
rescue WebserviceGeneralRenderingError => e
|
55
87
|
@logger.fatal(e.message)
|
56
88
|
socket.write http_response(400, 'Bad Request', e.message)
|
@@ -160,17 +192,17 @@ module GrafanaReporter
|
|
160
192
|
|
161
193
|
# provide report
|
162
194
|
@logger.debug("Returning PDF report at #{report.path}")
|
163
|
-
content = File.read(report.path)
|
195
|
+
content = File.read(report.path, mode: 'rb')
|
164
196
|
return http_response(200, 'OK', content, "Content-Type": 'application/pdf') if content.start_with?('%PDF')
|
165
197
|
|
166
|
-
# TODO: properly provide file as zip
|
167
198
|
http_response(200, 'OK', content, "Content-Type": 'application/octet-stream',
|
168
|
-
"Content-Disposition": 'attachment;
|
199
|
+
"Content-Disposition": 'attachment; '\
|
200
|
+
"filename=report_#{attrs['report_id']}.zip")
|
169
201
|
end
|
170
202
|
|
171
203
|
def render_report(attrs)
|
172
204
|
# build report
|
173
|
-
template_file = "#{@config.templates_folder}#{attrs['var-template']}
|
205
|
+
template_file = "#{@config.templates_folder}#{attrs['var-template']}"
|
174
206
|
|
175
207
|
file = Tempfile.new('gf_pdf_', @config.reports_folder)
|
176
208
|
begin
|
@@ -179,9 +211,10 @@ module GrafanaReporter
|
|
179
211
|
@logger.debug("File permissions could not be set for #{file.path}: #{e.message}")
|
180
212
|
end
|
181
213
|
|
182
|
-
report = @config.report_class.new(@config
|
214
|
+
report = @config.report_class.new(@config)
|
215
|
+
Thread.report_on_exception = false
|
183
216
|
Thread.new do
|
184
|
-
report.create_report
|
217
|
+
report.create_report(template_file, file, attrs)
|
185
218
|
end
|
186
219
|
@reports << report
|
187
220
|
|
@@ -211,7 +244,9 @@ module GrafanaReporter
|
|
211
244
|
"<td>#{report.start_time}</td>"\
|
212
245
|
"<td>#{report.end_time}</td>"\
|
213
246
|
"<td>#{report.template}</td>"\
|
214
|
-
"<td>#{report.execution_time.to_i} secs</td
|
247
|
+
"<td>#{report.execution_time.to_i} secs</td>"\
|
248
|
+
"<td>#{report.status} (#{(report.progress * 100).to_i}%)</td>"\
|
249
|
+
"<td>#{report.error.join('<br>')}</td>"\
|
215
250
|
"<td>#{!report.done && !report.cancel ? "<a href=\"/cancel_report?report_id=#{report.object_id}\">Cancel</a> " : ''}"\
|
216
251
|
"#{(report.status == 'finished') || (report.status == 'cancelled') ? "<a href=\"/view_report?report_id=#{report.object_id}\">View</a> " : ' '}"\
|
217
252
|
"<a href=\"/view_log?report_id=#{report.object_id}\">Log</a></td>"\
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'processor_mixin'
|
4
|
+
|
5
|
+
module GrafanaReporter
|
6
|
+
module Asciidoctor
|
7
|
+
# Implements the hook
|
8
|
+
# include::grafana_alerts[<options>]
|
9
|
+
#
|
10
|
+
# Returns the results of alerts query as a asciidoctor table.
|
11
|
+
#
|
12
|
+
# == Used document parameters
|
13
|
+
# +grafana_default_instance+ - name of grafana instance, 'default' if not specified
|
14
|
+
#
|
15
|
+
# +grafana_default_dashboard+ - uid of grafana default dashboard to use
|
16
|
+
#
|
17
|
+
# +from+ - 'from' time for the sql query
|
18
|
+
#
|
19
|
+
# +to+ - 'to' time for the sql query
|
20
|
+
#
|
21
|
+
# == Supported options
|
22
|
+
# +columns+ - see {AlertsTableQuery#pre_process} (*mandatory*)
|
23
|
+
#
|
24
|
+
# +instance+ - name of grafana instance, 'default' if not specified
|
25
|
+
#
|
26
|
+
# +dashboard+ - uid of grafana dashboard to query for, empty string if no filter is wanted
|
27
|
+
#
|
28
|
+
# +panel+ - id of the panel to query for
|
29
|
+
#
|
30
|
+
# +from+ - 'from' time for the sql query
|
31
|
+
#
|
32
|
+
# +to+ - 'to' time for the sql query
|
33
|
+
#
|
34
|
+
# +format+ - see {AbstractQuery#format_columns}
|
35
|
+
#
|
36
|
+
# +replace_values+ - see {AbstractQuery#replace_values}
|
37
|
+
#
|
38
|
+
# +filter_columns+ - see {AbstractQuery#filter_columns}
|
39
|
+
class AlertsTableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
|
40
|
+
include ProcessorMixin
|
41
|
+
|
42
|
+
# :nodoc:
|
43
|
+
def handles?(target)
|
44
|
+
target.start_with? 'grafana_alerts'
|
45
|
+
end
|
46
|
+
|
47
|
+
# :nodoc:
|
48
|
+
def process(doc, reader, _target, attrs)
|
49
|
+
return if @report.cancel
|
50
|
+
|
51
|
+
@report.next_step
|
52
|
+
instance = attrs['instance'] || doc.attr('grafana_default_instance') || 'default'
|
53
|
+
dashboard_id = attrs['dashboard'] || doc.attr('grafana_default_dashboard')
|
54
|
+
panel_id = attrs['panel']
|
55
|
+
@report.logger.debug("Processing AlertsTableIncludeProcessor (instance: #{instance},"\
|
56
|
+
" dashboard: #{dashboard_id}, panel: #{panel_id})")
|
57
|
+
|
58
|
+
query = AlertsTableQuery.new(@report.grafana(instance))
|
59
|
+
assign_dashboard_defaults(query, @report.grafana(instance).dashboard(dashboard_id)) if dashboard_id
|
60
|
+
defaults = {}
|
61
|
+
defaults['dashboardId'] = dashboard_id if dashboard_id
|
62
|
+
defaults['panelId'] = panel_id if panel_id
|
63
|
+
|
64
|
+
assign_doc_and_item_variables(query, doc.attributes, attrs)
|
65
|
+
selected_attrs = attrs.select do |k, _v|
|
66
|
+
k =~ /(?:columns|limit|folderId|dashboardId|panelId|dahboardTag|dashboardQuery|state|query)/x
|
67
|
+
end
|
68
|
+
query.raw_query = defaults.merge(selected_attrs.each_with_object({}) { |(k, v), h| h[k] = v })
|
69
|
+
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
70
|
+
|
71
|
+
begin
|
72
|
+
reader.unshift_lines query.execute
|
73
|
+
rescue GrafanaReporterError => e
|
74
|
+
@report.logger.error(e.message)
|
75
|
+
reader.unshift_line "|#{e.message}"
|
76
|
+
rescue StandardError => e
|
77
|
+
@report.logger.fatal(e.message)
|
78
|
+
reader.unshift_line "|#{e.message}"
|
79
|
+
end
|
80
|
+
|
81
|
+
reader
|
82
|
+
end
|
83
|
+
|
84
|
+
# @see ProcessorMixin#build_demo_entry
|
85
|
+
def build_demo_entry(_panel)
|
86
|
+
"|===\ninclude::grafana_alerts[columns=\"panelId,name,state\"]\n|==="
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'processor_mixin'
|
4
|
+
|
5
|
+
module GrafanaReporter
|
6
|
+
module Asciidoctor
|
7
|
+
# Implements the hook
|
8
|
+
# include::grafana_annotations[<options>]
|
9
|
+
#
|
10
|
+
# Returns the results of alerts query as a asciidoctor table.
|
11
|
+
#
|
12
|
+
# == Used document parameters
|
13
|
+
# +grafana_default_instance+ - name of grafana instance, 'default' if not specified
|
14
|
+
#
|
15
|
+
# +grafana_default_dashboard+ - uid of grafana default dashboard to use
|
16
|
+
#
|
17
|
+
# +from+ - 'from' time for the sql query
|
18
|
+
#
|
19
|
+
# +to+ - 'to' time for the sql query
|
20
|
+
#
|
21
|
+
# == Supported options
|
22
|
+
# +columns+ - see {AnnotationsTableQuery#pre_process} (*mandatory*)
|
23
|
+
#
|
24
|
+
# +instance+ - name of grafana instance, 'default' if not specified
|
25
|
+
#
|
26
|
+
# +dashboard+ - uid of grafana dashboard to query for, empty string if no filter is wanted
|
27
|
+
#
|
28
|
+
# +panel+ - id of the panel to query for
|
29
|
+
#
|
30
|
+
# +from+ - 'from' time for the sql query
|
31
|
+
#
|
32
|
+
# +to+ - 'to' time for the sql query
|
33
|
+
#
|
34
|
+
# +format+ - see {AbstractQuery#format_columns}
|
35
|
+
#
|
36
|
+
# +replace_values+ - see {AbstractQuery#replace_values}
|
37
|
+
#
|
38
|
+
# +filter_columns+ - see {AbstractQuery#filter_columns}
|
39
|
+
class AnnotationsTableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
|
40
|
+
include ProcessorMixin
|
41
|
+
|
42
|
+
# :nodoc:
|
43
|
+
def handles?(target)
|
44
|
+
target.start_with? 'grafana_annotations'
|
45
|
+
end
|
46
|
+
|
47
|
+
# :nodoc:
|
48
|
+
def process(doc, reader, _target, attrs)
|
49
|
+
return if @report.cancel
|
50
|
+
|
51
|
+
@report.next_step
|
52
|
+
instance = attrs['instance'] || doc.attr('grafana_default_instance') || 'default'
|
53
|
+
dashboard_id = attrs['dashboard'] || doc.attr('grafana_default_dashboard')
|
54
|
+
panel_id = attrs['panel']
|
55
|
+
@report.logger.debug("Processing AnnotationsTableIncludeProcessor (instance: #{instance})")
|
56
|
+
|
57
|
+
query = AnnotationsTableQuery.new(@report.grafana(instance))
|
58
|
+
assign_dashboard_defaults(query, @report.grafana(instance).dashboard(dashboard_id)) if dashboard_id
|
59
|
+
defaults = {}
|
60
|
+
defaults['dashboardId'] = dashboard_id if dashboard_id
|
61
|
+
defaults['panelId'] = panel_id if panel_id
|
62
|
+
|
63
|
+
assign_doc_and_item_variables(query, doc.attributes, attrs)
|
64
|
+
selected_attrs = attrs.select do |k, _v|
|
65
|
+
k =~ /(?:columns|limit|alertId|dashboardId|panelId|userId|type|tags)/
|
66
|
+
end
|
67
|
+
query.raw_query = defaults.merge(selected_attrs.each_with_object({}) { |(k, v), h| h[k] = v })
|
68
|
+
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
69
|
+
|
70
|
+
begin
|
71
|
+
reader.unshift_lines query.execute
|
72
|
+
rescue GrafanaReporterError => e
|
73
|
+
@report.logger.error(e.message)
|
74
|
+
reader.unshift_line "|#{e.message}"
|
75
|
+
rescue StandardError => e
|
76
|
+
@report.logger.fatal(e.message)
|
77
|
+
reader.unshift_line "|#{e.message}"
|
78
|
+
end
|
79
|
+
|
80
|
+
reader
|
81
|
+
end
|
82
|
+
|
83
|
+
# @see ProcessorMixin#build_demo_entry
|
84
|
+
def build_demo_entry(_panel)
|
85
|
+
"|===\ninclude::grafana_annotations[columns=\"time,panelId,newState,prevState,text\"]\n|==="
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'processor_mixin'
|
4
|
+
|
5
|
+
module GrafanaReporter
|
6
|
+
module Asciidoctor
|
7
|
+
# Implements the hook
|
8
|
+
# grafana_panel_image::<panel_id>[<options>]
|
9
|
+
#
|
10
|
+
# Stores the queried panel as a temporary image file and returns an asciidoctor link
|
11
|
+
# to be included in the report.
|
12
|
+
#
|
13
|
+
# == Used document parameters
|
14
|
+
# +grafana_default_instance+ - name of grafana instance, 'default' if not specified
|
15
|
+
#
|
16
|
+
# +grafana_default_dashboard+ - uid of grafana default dashboard to use
|
17
|
+
#
|
18
|
+
# +from+ - 'from' time for the sql query
|
19
|
+
#
|
20
|
+
# +to+ - 'to' time for the sql query
|
21
|
+
#
|
22
|
+
# == Supported options
|
23
|
+
# +field+ - property to query for, e.g. +description+ or +title+ (*mandatory*)
|
24
|
+
#
|
25
|
+
# +instance+ - name of grafana instance, 'default' if not specified
|
26
|
+
#
|
27
|
+
# +dashboard+ - uid of grafana dashboard to use
|
28
|
+
#
|
29
|
+
# +from+ - 'from' time for the sql query
|
30
|
+
#
|
31
|
+
# +to+ - 'to' time for the sql query
|
32
|
+
class PanelImageBlockMacro < ::Asciidoctor::Extensions::BlockMacroProcessor
|
33
|
+
include ProcessorMixin
|
34
|
+
use_dsl
|
35
|
+
|
36
|
+
named :grafana_panel_image
|
37
|
+
|
38
|
+
# :nodoc:
|
39
|
+
def process(parent, target, attrs)
|
40
|
+
return if @report.cancel
|
41
|
+
|
42
|
+
@report.next_step
|
43
|
+
instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
|
44
|
+
dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
|
45
|
+
@report.logger.debug("Processing PanelImageBlockMacro (instance: #{instance}, dashboard: #{dashboard},"\
|
46
|
+
" panel: #{target})")
|
47
|
+
|
48
|
+
begin
|
49
|
+
query = PanelImageQuery.new(@report.grafana(instance).dashboard(dashboard).panel(target))
|
50
|
+
assign_dashboard_defaults(query, @report.grafana(instance).dashboard(dashboard))
|
51
|
+
assign_doc_and_item_variables(query, parent.document.attributes, attrs)
|
52
|
+
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
53
|
+
|
54
|
+
image = query.execute
|
55
|
+
image_path = @report.save_image_file(image)
|
56
|
+
rescue GrafanaReporterError => e
|
57
|
+
@report.logger.error(e.message)
|
58
|
+
return create_paragraph(parent, e.message, attrs)
|
59
|
+
rescue StandardError => e
|
60
|
+
@report.logger.fatal(e.message)
|
61
|
+
return create_paragraph(parent, e.message, attrs)
|
62
|
+
end
|
63
|
+
|
64
|
+
attrs['target'] = image_path
|
65
|
+
create_image_block(parent, attrs)
|
66
|
+
end
|
67
|
+
|
68
|
+
# @see ProcessorMixin#build_demo_entry
|
69
|
+
def build_demo_entry(panel)
|
70
|
+
return nil unless panel
|
71
|
+
return nil unless panel.model['type'] == 'graph'
|
72
|
+
|
73
|
+
"grafana_panel_image::#{panel.id}[dashboard=\"#{panel.dashboard.id}\",width=\"50%\"]"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'processor_mixin'
|
4
|
+
|
5
|
+
module GrafanaReporter
|
6
|
+
module Asciidoctor
|
7
|
+
# Implements the hook
|
8
|
+
# grafana_panel_image:<panel_id>[<options>]
|
9
|
+
#
|
10
|
+
# Stores the queried panel as a temporary image file and returns an asciidoctor link
|
11
|
+
# to be included in the report.
|
12
|
+
#
|
13
|
+
# == Used document parameters
|
14
|
+
# +grafana_default_instance+ - name of grafana instance, 'default' if not specified
|
15
|
+
#
|
16
|
+
# +grafana_default_dashboard+ - uid of grafana default dashboard to use
|
17
|
+
#
|
18
|
+
# +from+ - 'from' time for the sql query
|
19
|
+
#
|
20
|
+
# +to+ - 'to' time for the sql query
|
21
|
+
#
|
22
|
+
# == Supported options
|
23
|
+
# +field+ - property to query for, e.g. +description+ or +title+ (*mandatory*)
|
24
|
+
#
|
25
|
+
# +instance+ - name of grafana instance, 'default' if not specified
|
26
|
+
#
|
27
|
+
# +dashboard+ - uid of grafana dashboard to use
|
28
|
+
#
|
29
|
+
# +from+ - 'from' time for the sql query
|
30
|
+
#
|
31
|
+
# +to+ - 'to' time for the sql query
|
32
|
+
class PanelImageInlineMacro < ::Asciidoctor::Extensions::InlineMacroProcessor
|
33
|
+
include ProcessorMixin
|
34
|
+
use_dsl
|
35
|
+
|
36
|
+
named :grafana_panel_image
|
37
|
+
|
38
|
+
# :nodoc:
|
39
|
+
def process(parent, target, attrs)
|
40
|
+
return if @report.cancel
|
41
|
+
|
42
|
+
@report.next_step
|
43
|
+
instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
|
44
|
+
dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
|
45
|
+
@report.logger.debug("Processing PanelImageInlineMacro (instance: #{instance}, dashboard: #{dashboard},"\
|
46
|
+
" panel: #{target})")
|
47
|
+
|
48
|
+
begin
|
49
|
+
query = PanelImageQuery.new(@report.grafana(instance).dashboard(dashboard).panel(target))
|
50
|
+
# set alt text to a default, because otherwise asciidoctor fails
|
51
|
+
attrs['alt'] = '' unless attrs['alt']
|
52
|
+
assign_dashboard_defaults(query, @report.grafana(instance).dashboard(dashboard))
|
53
|
+
assign_doc_and_item_variables(query, parent.document.attributes, attrs)
|
54
|
+
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
55
|
+
|
56
|
+
image = query.execute
|
57
|
+
image_path = @report.save_image_file(image)
|
58
|
+
rescue GrafanaReporterError => e
|
59
|
+
@report.logger.error(e.message)
|
60
|
+
return create_inline(parent, :quoted, e.message)
|
61
|
+
rescue StandardError => e
|
62
|
+
@report.logger.fatal(e.message)
|
63
|
+
return create_inline(parent, :quoted, e.message)
|
64
|
+
end
|
65
|
+
|
66
|
+
create_inline(parent, :image, nil, { target: image_path, attributes: attrs })
|
67
|
+
end
|
68
|
+
|
69
|
+
# @see ProcessorMixin#build_demo_entry
|
70
|
+
def build_demo_entry(panel)
|
71
|
+
return nil unless panel
|
72
|
+
return nil unless panel.model['type'] == 'graph'
|
73
|
+
|
74
|
+
"see here: grafana_panel_image:#{panel.id}[dashboard=\"#{panel.dashboard.id}\","\
|
75
|
+
'width="90%"] - a working inline image'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|