ruby-grafana-reporter 0.3.0 → 0.4.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +81 -71
  3. data/bin/ruby-grafana-reporter +5 -5
  4. data/lib/VERSION.rb +3 -2
  5. data/lib/grafana/abstract_datasource.rb +116 -0
  6. data/lib/grafana/dashboard.rb +1 -3
  7. data/lib/grafana/errors.rb +15 -0
  8. data/lib/grafana/grafana.rb +53 -56
  9. data/lib/grafana/grafana_alerts_datasource.rb +57 -0
  10. data/lib/grafana/grafana_annotations_datasource.rb +56 -0
  11. data/lib/grafana/grafana_property_datasource.rb +25 -0
  12. data/lib/grafana/graphite_datasource.rb +44 -0
  13. data/lib/grafana/image_rendering_datasource.rb +44 -0
  14. data/lib/grafana/panel.rb +9 -3
  15. data/lib/grafana/prometheus_datasource.rb +39 -0
  16. data/lib/grafana/sql_datasource.rb +65 -0
  17. data/lib/grafana/variable.rb +1 -0
  18. data/lib/grafana/webrequest.rb +71 -0
  19. data/lib/grafana_reporter/abstract_query.rb +401 -0
  20. data/lib/grafana_reporter/abstract_report.rb +54 -3
  21. data/lib/grafana_reporter/alerts_table_query.rb +44 -0
  22. data/lib/grafana_reporter/annotations_table_query.rb +43 -0
  23. data/lib/grafana_reporter/application/application.rb +12 -8
  24. data/lib/grafana_reporter/application/webservice.rb +18 -6
  25. data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +90 -0
  26. data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +89 -0
  27. data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +76 -0
  28. data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +77 -0
  29. data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +72 -0
  30. data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +98 -0
  31. data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +93 -0
  32. data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +23 -0
  33. data/lib/grafana_reporter/asciidoctor/report.rb +24 -31
  34. data/lib/grafana_reporter/asciidoctor/show_environment_include_processor.rb +46 -0
  35. data/lib/grafana_reporter/asciidoctor/show_help_include_processor.rb +35 -0
  36. data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +92 -0
  37. data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +88 -0
  38. data/lib/grafana_reporter/asciidoctor/value_as_variable_include_processor.rb +90 -0
  39. data/lib/grafana_reporter/configuration.rb +12 -6
  40. data/lib/grafana_reporter/console_configuration_wizard.rb +115 -65
  41. data/lib/grafana_reporter/demo_report_wizard.rb +87 -0
  42. data/lib/grafana_reporter/errors.rb +33 -0
  43. data/lib/grafana_reporter/help.rb +447 -0
  44. data/lib/grafana_reporter/logger/two_way_logger.rb +1 -1
  45. data/lib/grafana_reporter/panel_image_query.rb +29 -0
  46. data/lib/grafana_reporter/panel_property_query.rb +22 -0
  47. data/lib/grafana_reporter/query_value_query.rb +79 -0
  48. data/lib/grafana_reporter/report_webhook.rb +35 -0
  49. data/lib/{ruby-grafana-reporter.rb → ruby_grafana_reporter.rb} +0 -3
  50. metadata +37 -35
  51. data/lib/grafana/abstract_panel_query.rb +0 -22
  52. data/lib/grafana/abstract_query.rb +0 -132
  53. data/lib/grafana/abstract_sql_query.rb +0 -51
  54. data/lib/grafana/panel_image_query.rb +0 -52
  55. data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +0 -101
  56. data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +0 -96
  57. data/lib/grafana_reporter/asciidoctor/errors.rb +0 -40
  58. data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +0 -92
  59. data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +0 -91
  60. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +0 -69
  61. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +0 -68
  62. data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +0 -61
  63. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +0 -78
  64. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +0 -73
  65. data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +0 -20
  66. data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +0 -43
  67. data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +0 -30
  68. data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +0 -70
  69. data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +0 -66
  70. data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +0 -88
  71. data/lib/grafana_reporter/asciidoctor/help.rb +0 -435
  72. data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +0 -36
  73. data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +0 -28
  74. data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +0 -44
  75. data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +0 -40
  76. data/lib/grafana_reporter/asciidoctor/query_mixin.rb +0 -312
  77. data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -42
  78. data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -44
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ # This class is used to query alerts from grafana.
5
+ class AlertsTableQuery < AbstractQuery
6
+ # Check if mandatory {Grafana::Variable} +columns+ is specified in variables.
7
+ #
8
+ # The value of the +columns+ variable has to be a comma separated list of column titles, which
9
+ # need to be included in the following list:
10
+ # - limit
11
+ # - dashboardId
12
+ # - panelId
13
+ # - query
14
+ # - state
15
+ # - folderId
16
+ # - dashboardQuery
17
+ # - dashboardTag
18
+ # @return [void]
19
+ def pre_process
20
+ raise MissingMandatoryAttributeError, 'columns' unless @raw_query['columns']
21
+
22
+ @from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] ||
23
+ @variables['grafana_default_from_timezone'])
24
+ @to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] ||
25
+ @variables['grafana_default_to_timezone'])
26
+ @datasource = Grafana::GrafanaAlertsDatasource.new(nil)
27
+ end
28
+
29
+ # Filter the query result for the given columns and sets the result in the preformatted SQL
30
+ # result stlye.
31
+
32
+ # Additionally it applies {QueryMixin#format_columns}, {QueryMixin#replace_values} and
33
+ # {QueryMixin#filter_columns}.
34
+ # @return [void]
35
+ def post_process
36
+ @result = format_columns(@result, @variables['format'])
37
+ @result = replace_values(@result, @variables.select { |k, _v| k =~ /^replace_values_\d+/ })
38
+ @result = filter_columns(@result, @variables['filter_columns'])
39
+
40
+ # TODO: move formatting to Asciidoctor namespace
41
+ @result = @result[:content].map { |row| "| #{row.map { |item| item.to_s.gsub('|', '\\|') }.join(' | ')}" }
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ # This class is used to query annotations from grafana.
5
+ class AnnotationsTableQuery < AbstractQuery
6
+ # Check if mandatory {Grafana::Variable} +columns+ is specified in variables.
7
+ #
8
+ # The value of the +columns+ variable has to be a comma separated list of column titles, which
9
+ # need to be included in the following list:
10
+ # - limit
11
+ # - alertId
12
+ # - userId
13
+ # - type
14
+ # - tags
15
+ # - dashboardId
16
+ # - panelId
17
+ # @return [void]
18
+ def pre_process
19
+ raise MissingMandatoryAttributeError, 'columns' unless @raw_query['columns']
20
+
21
+ @from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] ||
22
+ @variables['grafana_default_from_timezone'])
23
+ @to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] ||
24
+ @variables['grafana_default_to_timezone'])
25
+ @datasource = Grafana::GrafanaAnnotationsDatasource.new(nil)
26
+ end
27
+
28
+ # Filters the query result for the given columns and sets the result
29
+ # in the preformatted SQL result style.
30
+ #
31
+ # Additionally it applies {QueryMixin#format_columns}, {QueryMixin#replace_values} and
32
+ # {QueryMixin#filter_columns}.
33
+ # @return [void]
34
+ def post_process
35
+ @result = format_columns(@result, @variables['format'])
36
+ @result = replace_values(@result, @variables.select { |k, _v| k =~ /^replace_values_\d+/ })
37
+ @result = filter_columns(@result, @variables['filter_columns'])
38
+
39
+ # TODO: move formatting to Asciidoctor namespace
40
+ @result = result[:content].map { |row| "| #{row.map { |item| item.to_s.gsub('|', '\\|') }.join(' | ')}" }
41
+ end
42
+ end
43
+ end
@@ -19,8 +19,12 @@ module GrafanaReporter
19
19
  # Contains the {Configuration} object of the application.
20
20
  attr_accessor :config
21
21
 
22
+ # Stores the {Webservice} object of the application
23
+ attr_reader :webservice
24
+
22
25
  def initialize
23
26
  @config = Configuration.new
27
+ @webservice = Webservice.new
24
28
  end
25
29
 
26
30
  # This is the main method, which is called, if the application is
@@ -33,11 +37,11 @@ module GrafanaReporter
33
37
  action_wizard = false
34
38
 
35
39
  parser = OptionParser.new do |opts|
36
- if ENV['OCRA_EXECUTABLE']
37
- opts.banner = "Usage: #{ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '')} [options]"
38
- else
39
- opts.banner = "Usage: #{Gem.ruby} #{$PROGRAM_NAME} [options]"
40
- end
40
+ opts.banner = if ENV['OCRA_EXECUTABLE']
41
+ "Usage: #{ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '')} [options]"
42
+ else
43
+ "Usage: #{Gem.ruby} #{$PROGRAM_NAME} [options]"
44
+ end
41
45
 
42
46
  opts.on('-c', '--config CONFIG_FILE_NAME', 'Specify custom configuration file,'\
43
47
  " instead of #{CONFIG_FILE}.") do |file_name|
@@ -137,18 +141,18 @@ module GrafanaReporter
137
141
  when Configuration::MODE_CONNECTION_TEST
138
142
  res = Grafana::Grafana.new(config.grafana_host(config.test_instance),
139
143
  config.grafana_api_key(config.test_instance),
140
- logger: config.logger, ssl_cert: config.ssl_cert).test_connection
144
+ logger: config.logger).test_connection
141
145
  puts res
142
146
 
143
147
  when Configuration::MODE_SINGLE_RENDER
144
148
  begin
145
149
  config.report_class.new(config, config.template, config.to_file).create_report
146
150
  rescue StandardError => e
147
- puts e.message
151
+ puts "#{e.message}\n#{e.backtrace.join("\n")}"
148
152
  end
149
153
 
150
154
  when Configuration::MODE_SERVICE
151
- Webservice.new(config).run
155
+ @webservice.run(config)
152
156
  end
153
157
 
154
158
  0
@@ -6,21 +6,30 @@ 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
- def initialize(config)
9
+ def initialize
10
10
  @reports = []
11
+ @running = false
12
+ end
13
+
14
+ # Runs the webservice with the given {Configuration} object.
15
+ def run(config)
11
16
  @config = config
12
17
  @logger = config.logger
13
- end
14
18
 
15
- # Runs the webservice with the current set {Configuration} object.
16
- def run
17
19
  # start webserver
18
20
  @server = TCPServer.new(@config.webserver_port)
19
21
  @logger.info("Server listening on port #{@config.webserver_port}...")
22
+ @running = true
20
23
 
21
24
  @progress_reporter = Thread.new {}
22
25
 
23
26
  accept_requests_loop
27
+ @running = false
28
+ end
29
+
30
+ # @return True, if webservice is up and running, false otherwise
31
+ def running?
32
+ @running
24
33
  end
25
34
 
26
35
  private
@@ -164,7 +173,8 @@ module GrafanaReporter
164
173
  return http_response(200, 'OK', content, "Content-Type": 'application/pdf') if content.start_with?('%PDF')
165
174
 
166
175
  http_response(200, 'OK', content, "Content-Type": 'application/octet-stream',
167
- "Content-Disposition": "attachment; filename=report_#{attrs['report_id']}.zip")
176
+ "Content-Disposition": 'attachment; '\
177
+ "filename=report_#{attrs['report_id']}.zip")
168
178
  end
169
179
 
170
180
  def render_report(attrs)
@@ -210,7 +220,9 @@ module GrafanaReporter
210
220
  "<td>#{report.start_time}</td>"\
211
221
  "<td>#{report.end_time}</td>"\
212
222
  "<td>#{report.template}</td>"\
213
- "<td>#{report.execution_time.to_i} secs</td><td>#{report.status} (#{(report.progress * 100).to_i}%)</td><td>#{report.error.join('<br>')}</td>"\
223
+ "<td>#{report.execution_time.to_i} secs</td>"\
224
+ "<td>#{report.status} (#{(report.progress * 100).to_i}%)</td>"\
225
+ "<td>#{report.error.join('<br>')}</td>"\
214
226
  "<td>#{!report.done && !report.cancel ? "<a href=\"/cancel_report?report_id=#{report.object_id}\">Cancel</a>&nbsp;" : ''}"\
215
227
  "#{(report.status == 'finished') || (report.status == 'cancelled') ? "<a href=\"/view_report?report_id=#{report.object_id}\">View</a>&nbsp;" : '&nbsp;'}"\
216
228
  "<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 {QueryMixin#format_columns}
35
+ #
36
+ # +replace_values+ - see {QueryMixin#replace_values}
37
+ #
38
+ # +filter_columns+ - see {QueryMixin#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
+ query.set_defaults_from_dashboard(@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
+ query.merge_hash_variables(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 {QueryMixin#format_columns}
35
+ #
36
+ # +replace_values+ - see {QueryMixin#replace_values}
37
+ #
38
+ # +filter_columns+ - see {QueryMixin#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
+ query.set_defaults_from_dashboard(@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
+ query.merge_hash_variables(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,76 @@
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
+ query.merge_hash_variables(parent.document.attributes, attrs)
51
+ @report.logger.debug("from: #{query.from}, to: #{query.to}")
52
+
53
+ image = query.execute
54
+ image_path = @report.save_image_file(image)
55
+ rescue GrafanaReporterError => e
56
+ @report.logger.error(e.message)
57
+ return create_paragraph(parent, e.message, attrs)
58
+ rescue StandardError => e
59
+ @report.logger.fatal(e.message)
60
+ return create_paragraph(parent, e.message, attrs)
61
+ end
62
+
63
+ attrs['target'] = image_path
64
+ create_image_block(parent, attrs)
65
+ end
66
+
67
+ # @see ProcessorMixin#build_demo_entry
68
+ def build_demo_entry(panel)
69
+ return nil unless panel
70
+ return nil unless panel.model['type'] == 'graph'
71
+
72
+ "grafana_panel_image::#{panel.id}[dashboard=\"#{panel.dashboard.id}\",width=\"50%\"]"
73
+ end
74
+ end
75
+ end
76
+ end