ruby-grafana-reporter 0.3.0 → 0.4.4

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +337 -170
  3. data/bin/ruby-grafana-reporter +5 -5
  4. data/lib/VERSION.rb +3 -2
  5. data/lib/grafana/abstract_datasource.rb +149 -0
  6. data/lib/grafana/dashboard.rb +1 -3
  7. data/lib/grafana/errors.rb +20 -5
  8. data/lib/grafana/grafana.rb +52 -57
  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 +37 -0
  12. data/lib/grafana/graphite_datasource.rb +72 -0
  13. data/lib/grafana/image_rendering_datasource.rb +44 -0
  14. data/lib/grafana/influxdb_datasource.rb +70 -0
  15. data/lib/grafana/panel.rb +10 -4
  16. data/lib/grafana/prometheus_datasource.rb +67 -0
  17. data/lib/grafana/sql_datasource.rb +70 -0
  18. data/lib/grafana/unsupported_datasource.rb +7 -0
  19. data/lib/grafana/variable.rb +27 -21
  20. data/lib/grafana/webrequest.rb +71 -0
  21. data/lib/grafana_reporter/abstract_query.rb +478 -0
  22. data/lib/grafana_reporter/abstract_report.rb +152 -18
  23. data/lib/grafana_reporter/abstract_table_format_strategy.rb +34 -0
  24. data/lib/grafana_reporter/alerts_table_query.rb +43 -0
  25. data/lib/grafana_reporter/annotations_table_query.rb +42 -0
  26. data/lib/grafana_reporter/application/application.rb +28 -25
  27. data/lib/grafana_reporter/application/webservice.rb +80 -39
  28. data/lib/grafana_reporter/asciidoctor/adoc_plain_table_format_strategy.rb +25 -0
  29. data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +92 -0
  30. data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +91 -0
  31. data/lib/grafana_reporter/asciidoctor/help.rb +336 -313
  32. data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +78 -0
  33. data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +80 -0
  34. data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +74 -0
  35. data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +99 -0
  36. data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +93 -0
  37. data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +50 -0
  38. data/lib/grafana_reporter/asciidoctor/report.rb +41 -82
  39. data/lib/grafana_reporter/asciidoctor/show_environment_include_processor.rb +46 -0
  40. data/lib/grafana_reporter/asciidoctor/show_help_include_processor.rb +35 -0
  41. data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +94 -0
  42. data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +90 -0
  43. data/lib/grafana_reporter/asciidoctor/value_as_variable_include_processor.rb +90 -0
  44. data/lib/grafana_reporter/configuration.rb +26 -8
  45. data/lib/grafana_reporter/console_configuration_wizard.rb +109 -67
  46. data/lib/grafana_reporter/csv_table_format_strategy.rb +23 -0
  47. data/lib/grafana_reporter/demo_report_wizard.rb +104 -0
  48. data/lib/grafana_reporter/erb/demo_report_builder.rb +46 -0
  49. data/lib/grafana_reporter/erb/report.rb +36 -0
  50. data/lib/grafana_reporter/erb/report_jail.rb +21 -0
  51. data/lib/grafana_reporter/errors.rb +57 -0
  52. data/lib/grafana_reporter/logger/{two_way_logger.rb → two_way_delegate_logger.rb} +1 -1
  53. data/lib/grafana_reporter/panel_image_query.rb +25 -0
  54. data/lib/grafana_reporter/panel_property_query.rb +22 -0
  55. data/lib/grafana_reporter/query_value_query.rb +61 -0
  56. data/lib/grafana_reporter/report_webhook.rb +39 -0
  57. data/lib/ruby_grafana_extension.rb +8 -0
  58. data/lib/{ruby-grafana-reporter.rb → ruby_grafana_reporter.rb} +1 -3
  59. metadata +49 -38
  60. data/lib/grafana/abstract_panel_query.rb +0 -22
  61. data/lib/grafana/abstract_query.rb +0 -132
  62. data/lib/grafana/abstract_sql_query.rb +0 -51
  63. data/lib/grafana/panel_image_query.rb +0 -52
  64. data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +0 -101
  65. data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +0 -96
  66. data/lib/grafana_reporter/asciidoctor/errors.rb +0 -40
  67. data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +0 -92
  68. data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +0 -91
  69. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +0 -69
  70. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +0 -68
  71. data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +0 -61
  72. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +0 -78
  73. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +0 -73
  74. data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +0 -20
  75. data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +0 -43
  76. data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +0 -30
  77. data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +0 -70
  78. data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +0 -66
  79. data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +0 -88
  80. data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +0 -36
  81. data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +0 -28
  82. data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +0 -44
  83. data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +0 -40
  84. data/lib/grafana_reporter/asciidoctor/query_mixin.rb +0 -312
  85. data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -42
  86. data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -44
@@ -1,96 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GrafanaReporter
4
- module Asciidoctor
5
- # This class is used to query annotations from grafana.
6
- class AnnotationsTableQuery < Grafana::AbstractQuery
7
- include QueryMixin
8
-
9
- # @option opts [Grafana::Dashboard] :dashboard dashboard, if annotations shall be filtered for a dashboard
10
- # @option opts [Grafana::Panel] :panel panel, if annotations shall be filtered for a panel
11
- def initialize(opts = {})
12
- super()
13
-
14
- @dashboard = opts[:dashboard]
15
- @panel = opts[:panel]
16
- @dashboard = @panel.dashboard if @panel
17
-
18
- extract_dashboard_variables(@dashboard) if @dashboard
19
- end
20
-
21
- # @return [String] URL for querying annotations
22
- def url
23
- "/api/annotations#{url_parameters}"
24
- end
25
-
26
- # @return [Hash] empty hash object
27
- def request
28
- {}
29
- end
30
-
31
- # Check if mandatory {Grafana::Variable} +columns+ is specified in variables.
32
- #
33
- # The value of the +columns+ variable has to be a comma separated list of column titles, which
34
- # need to be included in the following list:
35
- # - limit
36
- # - alertId
37
- # - userId
38
- # - type
39
- # - tags
40
- # - dashboardId
41
- # - panelId
42
- # @return [void]
43
- def pre_process(_grafana)
44
- raise MissingMandatoryAttributeError, 'columns' unless @variables['columns']
45
-
46
- @from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] ||
47
- @variables['grafana_default_from_timezone'])
48
- @to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] ||
49
- @variables['grafana_default_to_timezone'])
50
- end
51
-
52
- # Filters the query result for the given columns and sets the result
53
- # in the preformatted SQL result style.
54
- #
55
- # Additionally it applies {QueryMixin#format_columns}, {QueryMixin#replace_values} and
56
- # {QueryMixin#filter_columns}.
57
- # @return [void]
58
- def post_process
59
- # extract data from returned json
60
- result = JSON.parse(@result.body)
61
- content = []
62
- begin
63
- result.each { |item| content << item.fetch_values(*@variables['columns'].raw_value.split(',')) }
64
- rescue KeyError => e
65
- raise MalformedAttributeContentError.new(e.message, 'columns', @variables['columns'])
66
- end
67
-
68
- result = {}
69
- result[:header] = [@variables['columns'].raw_value.split(',')]
70
- result[:content] = content
71
-
72
- result = format_columns(result, @variables['format'])
73
- result = replace_values(result, @variables.select { |k, _v| k =~ /^replace_values_\d+/ })
74
- result = filter_columns(result, @variables['filter_columns'])
75
-
76
- @result = result[:content].map { |row| "| #{row.map { |item| item.to_s.gsub('|', '\\|') }.join(' | ')}" }
77
- end
78
-
79
- private
80
-
81
- def url_parameters
82
- url_vars = {}
83
- url_vars['dashboardId'] = ::Grafana::Variable.new(@dashboard.id) if @dashboard
84
- url_vars['panelId'] = ::Grafana::Variable.new(@panel.id) if @panel
85
-
86
- url_vars.merge!(variables.select { |k, _v| k =~ /^(?:limit|alertId|dashboardId|panelId|userId|type|tags)/ })
87
- url_vars['from'] = ::Grafana::Variable.new(@from) if @from
88
- url_vars['to'] = ::Grafana::Variable.new(@to) if @to
89
- url_params = URI.encode_www_form(url_vars.map { |k, v| [k, v.raw_value.to_s] })
90
- return '' if url_params.empty?
91
-
92
- "?#{url_params}"
93
- end
94
- end
95
- end
96
- end
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module GrafanaReporter
4
- # This module contains all classes, which are necessary to use the grafana
5
- # reporter to be used in conjunction with asciidoctor.
6
- module Asciidoctor
7
- # Thrown, if the value configuration in {QueryMixin#replace_values} is
8
- # invalid.
9
- class MalformedReplaceValuesStatementError < GrafanaReporterError
10
- def initialize(statement)
11
- super("The specified replace_values statement '#{statement}' is invalid. Make sure it contains"\
12
- " exactly one not escaped ':' symbol.")
13
- end
14
- end
15
-
16
- # Thrown, if a configured parameter is malformed.
17
- class MalformedAttributeContentError < GrafanaReporterError
18
- def initialize(message, attribute, content)
19
- super("The content '#{content}' in attribute '#{attribute}' is malformed: #{message}")
20
- end
21
- end
22
-
23
- # Thrown, if a configured time range is not supported by the reporter.
24
- #
25
- # If this happens, most likely the reporter has to implement the new
26
- # time range definition.
27
- class TimeRangeUnknownError < GrafanaReporterError
28
- def initialize(time_range)
29
- super("The specified time range '#{time_range}' is unknown.")
30
- end
31
- end
32
-
33
- # Thrown, if a mandatory attribute is not set.
34
- class MissingMandatoryAttributeError < GrafanaReporterError
35
- def initialize(attribute)
36
- super("Missing mandatory attribute '#{attribute}'.")
37
- end
38
- end
39
- end
40
- end
@@ -1,92 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'processor_mixin'
4
-
5
- module GrafanaReporter
6
- module Asciidoctor
7
- module Extensions
8
- # Implements the hook
9
- # include::grafana_alerts[<options>]
10
- #
11
- # Returns the results of alerts query as a asciidoctor table.
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
- # +columns+ - see {AlertsTableQuery#pre_process} (*mandatory*)
24
- #
25
- # +instance+ - name of grafana instance, 'default' if not specified
26
- #
27
- # +dashboard+ - uid of grafana dashboard to query for, empty string if no filter is wanted
28
- #
29
- # +panel+ - id of the panel to query for
30
- #
31
- # +from+ - 'from' time for the sql query
32
- #
33
- # +to+ - 'to' time for the sql query
34
- #
35
- # +format+ - see {QueryMixin#format_columns}
36
- #
37
- # +replace_values+ - see {QueryMixin#replace_values}
38
- #
39
- # +filter_columns+ - see {QueryMixin#filter_columns}
40
- class AlertsTableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
41
- include ProcessorMixin
42
-
43
- # :nodoc:
44
- def handles?(target)
45
- target.start_with? 'grafana_alerts'
46
- end
47
-
48
- # :nodoc:
49
- def process(doc, reader, _target, attrs)
50
- return if @report.cancel
51
-
52
- @report.next_step
53
- instance = attrs['instance'] || doc.attr('grafana_default_instance') || 'default'
54
- dashboard_id = attrs['dashboard'] || doc.attr('grafana_default_dashboard')
55
- panel_id = attrs['panel']
56
- @report.logger.debug("Processing AlertsTableIncludeProcessor (instance: #{instance},"\
57
- " dashboard: #{dashboard_id}, panel: #{panel_id})")
58
-
59
- query = if dashboard_id.to_s.empty?
60
- # no dashboard shall be used, so also the panel will be omitted
61
- AlertsTableQuery.new
62
- elsif panel_id.to_s.empty?
63
- # a dashboard is given, but no panel, so set filter for dashboard only
64
- AlertsTableQuery.new(dashboard: @report.grafana(instance).dashboard(dashboard_id))
65
- else
66
- # dashboard and panel is given, so set filter for panel
67
- AlertsTableQuery.new(panel: @report.grafana(instance).dashboard(dashboard_id).panel(panel_id))
68
- end
69
-
70
- query.merge_hash_variables(doc.attributes, attrs)
71
- selected_attrs = attrs.select do |k, _v|
72
- k =~ /(?:columns|limit|folderId|dashboardId|panelId|dahboardTag|dashboardQuery|state|query)/x
73
- end
74
- query.merge_variables(selected_attrs.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
75
- @report.logger.debug("from: #{query.from}, to: #{query.to}")
76
-
77
- begin
78
- reader.unshift_lines query.execute(@report.grafana(instance))
79
- rescue GrafanaReporterError => e
80
- @report.logger.error(e.message)
81
- reader.unshift_line "|#{e.message}"
82
- rescue StandardError => e
83
- @report.logger.fatal(e.message)
84
- reader.unshift_line "|#{e.message}"
85
- end
86
-
87
- reader
88
- end
89
- end
90
- end
91
- end
92
- end
@@ -1,91 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'processor_mixin'
4
-
5
- module GrafanaReporter
6
- module Asciidoctor
7
- module Extensions
8
- # Implements the hook
9
- # include::grafana_annotations[<options>]
10
- #
11
- # Returns the results of alerts query as a asciidoctor table.
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
- # +columns+ - see {AnnotationsTableQuery#pre_process} (*mandatory*)
24
- #
25
- # +instance+ - name of grafana instance, 'default' if not specified
26
- #
27
- # +dashboard+ - uid of grafana dashboard to query for, empty string if no filter is wanted
28
- #
29
- # +panel+ - id of the panel to query for
30
- #
31
- # +from+ - 'from' time for the sql query
32
- #
33
- # +to+ - 'to' time for the sql query
34
- #
35
- # +format+ - see {QueryMixin#format_columns}
36
- #
37
- # +replace_values+ - see {QueryMixin#replace_values}
38
- #
39
- # +filter_columns+ - see {QueryMixin#filter_columns}
40
- class AnnotationsTableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
41
- include ProcessorMixin
42
-
43
- # :nodoc:
44
- def handles?(target)
45
- target.start_with? 'grafana_annotations'
46
- end
47
-
48
- # :nodoc:
49
- def process(doc, reader, _target, attrs)
50
- return if @report.cancel
51
-
52
- @report.next_step
53
- instance = attrs['instance'] || doc.attr('grafana_default_instance') || 'default'
54
- dashboard_id = attrs['dashboard'] || doc.attr('grafana_default_dashboard')
55
- panel_id = attrs['panel']
56
- @report.logger.debug("Processing AnnotationsTableIncludeProcessor (instance: #{instance})")
57
-
58
- query = if dashboard_id.to_s.empty?
59
- # no dashboard shall be used, so also the panel will be omitted
60
- AnnotationsTableQuery.new
61
- elsif panel_id.to_s.empty?
62
- # a dashboard is given, but no panel, so set filter for dashboard only
63
- AnnotationsTableQuery.new(dashboard: @report.grafana(instance).dashboard(dashboard_id))
64
- else
65
- # dashboard and panel is given, so set filter for panel
66
- AnnotationsTableQuery.new(panel: @report.grafana(instance).dashboard(dashboard_id).panel(panel_id))
67
- end
68
-
69
- query.merge_hash_variables(doc.attributes, attrs)
70
- selected_attrs = attrs.select do |k, _v|
71
- k =~ /(?:columns|limit|alertId|dashboardId|panelId|userId|type|tags)/
72
- end
73
- query.merge_variables(selected_attrs.each_with_object({}) { |(k, v), h| h[k] = ::Grafana::Variable.new(v) })
74
- @report.logger.debug("from: #{query.from}, to: #{query.to}")
75
-
76
- begin
77
- reader.unshift_lines query.execute(@report.grafana(instance))
78
- rescue GrafanaReporterError => e
79
- @report.logger.error(e.message)
80
- reader.unshift_line "|#{e.message}"
81
- rescue StandardError => e
82
- @report.logger.fatal(e.message)
83
- reader.unshift_line "|#{e.message}"
84
- end
85
-
86
- reader
87
- end
88
- end
89
- end
90
- end
91
- end
@@ -1,69 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'processor_mixin'
4
-
5
- module GrafanaReporter
6
- module Asciidoctor
7
- module Extensions
8
- # Implements the hook
9
- # grafana_panel_image::<panel_id>[<options>]
10
- #
11
- # Stores the queried panel as a temporary image file and returns an asciidoctor link
12
- # to be included in the report.
13
- #
14
- # == Used document parameters
15
- # +grafana_default_instance+ - name of grafana instance, 'default' if not specified
16
- #
17
- # +grafana_default_dashboard+ - uid of grafana default dashboard to use
18
- #
19
- # +from+ - 'from' time for the sql query
20
- #
21
- # +to+ - 'to' time for the sql query
22
- #
23
- # == Supported options
24
- # +field+ - property to query for, e.g. +description+ or +title+ (*mandatory*)
25
- #
26
- # +instance+ - name of grafana instance, 'default' if not specified
27
- #
28
- # +dashboard+ - uid of grafana dashboard to use
29
- #
30
- # +from+ - 'from' time for the sql query
31
- #
32
- # +to+ - 'to' time for the sql query
33
- class PanelImageBlockMacro < ::Asciidoctor::Extensions::BlockMacroProcessor
34
- include ProcessorMixin
35
- use_dsl
36
-
37
- named :grafana_panel_image
38
-
39
- # :nodoc:
40
- def process(parent, target, attrs)
41
- return if @report.cancel
42
-
43
- @report.next_step
44
- instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
45
- dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
46
- @report.logger.debug("Processing PanelImageBlockMacro (instance: #{instance}, dashboard: #{dashboard},"\
47
- " panel: #{target})")
48
- query = PanelImageQuery.new(@report.grafana(instance).dashboard(dashboard).panel(target))
49
- query.merge_hash_variables(parent.document.attributes, attrs)
50
- @report.logger.debug("from: #{query.from}, to: #{query.to}")
51
-
52
- begin
53
- image = query.execute(@report.grafana(instance))
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
- end
67
- end
68
- end
69
- end
@@ -1,68 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative 'processor_mixin'
4
-
5
- module GrafanaReporter
6
- module Asciidoctor
7
- module Extensions
8
- # Implements the hook
9
- # grafana_panel_image:<panel_id>[<options>]
10
- #
11
- # Stores the queried panel as a temporary image file and returns an asciidoctor link
12
- # to be included in the report.
13
- #
14
- # == Used document parameters
15
- # +grafana_default_instance+ - name of grafana instance, 'default' if not specified
16
- #
17
- # +grafana_default_dashboard+ - uid of grafana default dashboard to use
18
- #
19
- # +from+ - 'from' time for the sql query
20
- #
21
- # +to+ - 'to' time for the sql query
22
- #
23
- # == Supported options
24
- # +field+ - property to query for, e.g. +description+ or +title+ (*mandatory*)
25
- #
26
- # +instance+ - name of grafana instance, 'default' if not specified
27
- #
28
- # +dashboard+ - uid of grafana dashboard to use
29
- #
30
- # +from+ - 'from' time for the sql query
31
- #
32
- # +to+ - 'to' time for the sql query
33
- class PanelImageInlineMacro < ::Asciidoctor::Extensions::InlineMacroProcessor
34
- include ProcessorMixin
35
- use_dsl
36
-
37
- named :grafana_panel_image
38
-
39
- # :nodoc:
40
- def process(parent, target, attrs)
41
- return if @report.cancel
42
-
43
- @report.next_step
44
- instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
45
- dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
46
- @report.logger.debug("Processing PanelImageInlineMacro (instance: #{instance}, dashboard: #{dashboard},"\
47
- " panel: #{target})")
48
- query = PanelImageQuery.new(@report.grafana(instance).dashboard(dashboard).panel(target))
49
- query.merge_hash_variables(parent.document.attributes, attrs)
50
- @report.logger.debug("from: #{query.from}, to: #{query.to}")
51
-
52
- begin
53
- image = query.execute(@report.grafana(instance))
54
- image_path = @report.save_image_file(image)
55
- rescue GrafanaReporterError => e
56
- @report.logger.error(e.message)
57
- return create_inline(parent, :quoted, e.message)
58
- rescue StandardError => e
59
- @report.logger.fatal(e.message)
60
- return create_inline(parent, :quoted, e.message)
61
- end
62
-
63
- create_inline(parent, :image, nil, { target: image_path, attributes: attrs })
64
- end
65
- end
66
- end
67
- end
68
- end