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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +105 -86
  3. data/bin/ruby-grafana-reporter +5 -5
  4. data/lib/VERSION.rb +3 -2
  5. data/lib/grafana/abstract_datasource.rb +136 -0
  6. data/lib/grafana/dashboard.rb +21 -23
  7. data/lib/grafana/errors.rb +8 -1
  8. data/lib/grafana/grafana.rb +61 -65
  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 +50 -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 +45 -0
  16. data/lib/grafana/sql_datasource.rb +71 -0
  17. data/lib/grafana/unsupported_datasource.rb +7 -0
  18. data/lib/grafana/variable.rb +3 -2
  19. data/lib/grafana/webrequest.rb +71 -0
  20. data/lib/grafana_reporter/abstract_query.rb +359 -0
  21. data/lib/grafana_reporter/abstract_report.rb +119 -17
  22. data/lib/grafana_reporter/alerts_table_query.rb +44 -0
  23. data/lib/grafana_reporter/annotations_table_query.rb +43 -0
  24. data/lib/grafana_reporter/application/application.rb +49 -297
  25. data/lib/grafana_reporter/application/webservice.rb +49 -14
  26. data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +90 -0
  27. data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +89 -0
  28. data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +77 -0
  29. data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +79 -0
  30. data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +73 -0
  31. data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +99 -0
  32. data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +93 -0
  33. data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +64 -0
  34. data/lib/grafana_reporter/asciidoctor/report.rb +47 -76
  35. data/lib/grafana_reporter/asciidoctor/show_environment_include_processor.rb +46 -0
  36. data/lib/grafana_reporter/asciidoctor/show_help_include_processor.rb +35 -0
  37. data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +92 -0
  38. data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +88 -0
  39. data/lib/grafana_reporter/asciidoctor/value_as_variable_include_processor.rb +90 -0
  40. data/lib/grafana_reporter/configuration.rb +108 -43
  41. data/lib/grafana_reporter/console_configuration_wizard.rb +311 -0
  42. data/lib/grafana_reporter/demo_report_wizard.rb +101 -0
  43. data/lib/grafana_reporter/erb/report.rb +43 -0
  44. data/lib/grafana_reporter/errors.rb +41 -0
  45. data/lib/grafana_reporter/help.rb +443 -0
  46. data/lib/grafana_reporter/logger/{two_way_logger.rb → two_way_delegate_logger.rb} +1 -1
  47. data/lib/grafana_reporter/panel_image_query.rb +29 -0
  48. data/lib/grafana_reporter/panel_property_query.rb +22 -0
  49. data/lib/grafana_reporter/query_value_query.rb +79 -0
  50. data/lib/grafana_reporter/report_webhook.rb +35 -0
  51. data/lib/ruby_grafana_extension.rb +8 -0
  52. data/lib/{ruby-grafana-reporter.rb → ruby_grafana_reporter.rb} +13 -0
  53. metadata +47 -43
  54. data/lib/grafana/abstract_panel_query.rb +0 -22
  55. data/lib/grafana/abstract_query.rb +0 -132
  56. data/lib/grafana/abstract_sql_query.rb +0 -51
  57. data/lib/grafana/panel_image_query.rb +0 -52
  58. data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +0 -104
  59. data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +0 -99
  60. data/lib/grafana_reporter/asciidoctor/errors.rb +0 -40
  61. data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +0 -92
  62. data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +0 -91
  63. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +0 -69
  64. data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +0 -68
  65. data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +0 -61
  66. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +0 -78
  67. data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +0 -73
  68. data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +0 -20
  69. data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +0 -43
  70. data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +0 -202
  71. data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +0 -70
  72. data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +0 -66
  73. data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +0 -61
  74. data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +0 -34
  75. data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +0 -25
  76. data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +0 -44
  77. data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +0 -38
  78. data/lib/grafana_reporter/asciidoctor/query_mixin.rb +0 -310
  79. data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -37
  80. data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -39
@@ -0,0 +1,73 @@
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_property:<panel_id>[<options>]
9
+ #
10
+ # Returns the requested panel property.
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
+ # == Supported options
18
+ # +field+ - property to query for, e.g. +description+ or +title+ (*mandatory*)
19
+ #
20
+ # +instance+ - name of grafana instance, 'default' if not specified
21
+ #
22
+ # +dashboard+ - uid of grafana dashboard to use
23
+ class PanelPropertyInlineMacro < ::Asciidoctor::Extensions::InlineMacroProcessor
24
+ include ProcessorMixin
25
+ use_dsl
26
+
27
+ named :grafana_panel_property
28
+ name_positional_attributes :field
29
+
30
+ # :nodoc:
31
+ def process(parent, target, attrs)
32
+ return if @report.cancel
33
+
34
+ @report.next_step
35
+ instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
36
+ dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
37
+ @report.logger.debug("Processing PanelPropertyInlineMacro (instance: #{instance}, dashboard: #{dashboard},"\
38
+ " panel: #{target}, property: #{attrs[:field]})")
39
+
40
+ begin
41
+ query = PanelPropertyQuery.new(@report.grafana(instance).dashboard(dashboard).panel(target))
42
+ query.raw_query = { property_name: attrs[:field] }
43
+ assign_dashboard_defaults(query, @report.grafana(instance).dashboard(dashboard))
44
+ assign_doc_and_item_variables(query, parent.document.attributes, attrs)
45
+ @report.logger.debug("from: #{query.from}, to: #{query.to}")
46
+
47
+ description = query.execute
48
+ rescue GrafanaReporterError => e
49
+ @report.logger.error(e.message)
50
+ return create_inline(parent, :quoted, e.message)
51
+ rescue StandardError => e
52
+ @report.logger.fatal(e.message)
53
+ return create_inline(parent, :quoted, e.message)
54
+ end
55
+
56
+ # translate linebreaks to asciidoctor syntax
57
+ # and HTML encode to make sure, that HTML formattings are respected
58
+ create_inline(parent, :quoted, CGI.escapeHTML(description.gsub(%r{//[^\n]*(?:\n)?}, '').gsub(/\n/, " +\n")))
59
+ end
60
+
61
+ # @see ProcessorMixin#build_demo_entry
62
+ def build_demo_entry(panel)
63
+ return nil unless panel
64
+ return nil unless panel.model['title']
65
+ return nil if panel.model['title'].strip == ''
66
+ return nil if panel.model['title'].strip == 'Panel Title'
67
+
68
+ "this text includes the panel with title grafana_panel_property:#{panel.id}[\"title\","\
69
+ "dashboard=\"#{panel.dashboard.id}\"]"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,99 @@
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_panel_query_table:<panel_id>[<options>]
9
+ #
10
+ # Returns the results of the SQL 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
+ # All other variables starting with +var-+ will be used to replace grafana templating strings
22
+ # in the given SQL query.
23
+ #
24
+ # == Supported options
25
+ # +query+ - query letter, which shall be used, e.g. +C+ (*mandatory*)
26
+ #
27
+ # +instance+ - name of grafana instance, 'default' if not specified
28
+ #
29
+ # +dashboard+ - uid of grafana dashboard to use
30
+ #
31
+ # +from+ - 'from' time for the sql query
32
+ #
33
+ # +to+ - 'to' time for the sql query
34
+ #
35
+ # +format+ - see {AbstractQuery#format_columns}
36
+ #
37
+ # +replace_values+ - see {AbstractQuery#replace_values}
38
+ #
39
+ # +filter_columns+ - see {AbstractQuery#filter_columns}
40
+ class PanelQueryTableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
41
+ include ProcessorMixin
42
+
43
+ # :nodoc:
44
+ def handles?(target)
45
+ target.start_with? 'grafana_panel_query_table:'
46
+ end
47
+
48
+ # :nodoc:
49
+ def process(doc, reader, target, attrs)
50
+ return if @report.cancel
51
+
52
+ @report.next_step
53
+ panel_id = target.split(':')[1]
54
+ # TODO: check if instance and dashboard shouldn't be set in assign_doc_and_item_variables method
55
+ instance = attrs['instance'] || doc.attr('grafana_default_instance') || 'default'
56
+ dashboard = attrs['dashboard'] || doc.attr('grafana_default_dashboard')
57
+ attrs['result_type'] = 'panel_table'
58
+ @report.logger.debug("Processing PanelQueryTableIncludeProcessor (instance: #{instance}, "\
59
+ "dashboard: #{dashboard}, panel: #{panel_id}, query: #{attrs['query']})")
60
+
61
+ begin
62
+ panel = @report.grafana(instance).dashboard(dashboard).panel(panel_id)
63
+ query = QueryValueQuery.new(panel)
64
+ assign_dashboard_defaults(query, panel.dashboard)
65
+ assign_doc_and_item_variables(query, doc.attributes, attrs)
66
+ @report.logger.debug("from: #{query.from}, to: #{query.to}")
67
+
68
+ reader.unshift_lines query.execute
69
+ rescue GrafanaReporterError => e
70
+ @report.logger.error(e.message)
71
+ reader.unshift_line "|#{e.message}"
72
+ rescue StandardError => e
73
+ @report.logger.fatal(e.message)
74
+ reader.unshift_line "|#{e.message}"
75
+ end
76
+
77
+ reader
78
+ end
79
+
80
+ # @see ProcessorMixin#build_demo_entry
81
+ def build_demo_entry(panel)
82
+ return nil unless panel
83
+ return nil unless panel.model['type'].include?('table')
84
+
85
+ ref_id = nil
86
+ panel.model['targets'].each do |item|
87
+ if !item['hide'] && !panel.query(item['refId']).to_s.empty?
88
+ ref_id = item['refId']
89
+ break
90
+ end
91
+ end
92
+ return nil unless ref_id
93
+
94
+ "|===\ninclude::grafana_panel_query_table:#{panel.id}[query=\"#{ref_id}\",filter_columns=\"time\","\
95
+ "dashboard=\"#{panel.dashboard.id}\"]\n|==="
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,93 @@
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_query_value:<panel_id>[<options>]
9
+ #
10
+ # Returns the first value of the resulting SQL query.
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
+ # All other variables starting with +var-+ will be used to replace grafana templating strings
22
+ # in the given SQL query.
23
+ #
24
+ # == Supported options
25
+ # +query+ - query letter, which shall be used, e.g. +C+ (*mandatory*)
26
+ #
27
+ # +instance+ - name of grafana instance, 'default' if not specified
28
+ #
29
+ # +dashboard+ - uid of grafana dashboard to use
30
+ #
31
+ # +from+ - 'from' time for the sql query
32
+ #
33
+ # +to+ - 'to' time for the sql query
34
+ #
35
+ # +format+ - see {AbstractQuery#format_columns}
36
+ #
37
+ # +replace_values+ - see {AbstractQuery#replace_values}
38
+ #
39
+ # +filter_columns+ - see {AbstractQuery#filter_columns}
40
+ class PanelQueryValueInlineMacro < ::Asciidoctor::Extensions::InlineMacroProcessor
41
+ include ProcessorMixin
42
+ use_dsl
43
+
44
+ named :grafana_panel_query_value
45
+
46
+ # :nodoc:
47
+ def process(parent, target, attrs)
48
+ return if @report.cancel
49
+
50
+ @report.next_step
51
+ instance = attrs['instance'] || parent.document.attr('grafana_default_instance') || 'default'
52
+ dashboard = attrs['dashboard'] || parent.document.attr('grafana_default_dashboard')
53
+ attrs['result_type'] = 'panel_value'
54
+ @report.logger.debug("Processing PanelQueryValueInlineMacro (instance: #{instance}, dashboard: #{dashboard},"\
55
+ " panel: #{target}, query: #{attrs['query']})")
56
+
57
+ begin
58
+ panel = @report.grafana(instance).dashboard(dashboard).panel(target)
59
+ query = QueryValueQuery.new(panel)
60
+ assign_dashboard_defaults(query, panel.dashboard)
61
+ assign_doc_and_item_variables(query, parent.document.attributes, attrs)
62
+ @report.logger.debug("from: #{query.from}, to: #{query.to}")
63
+
64
+ create_inline(parent, :quoted, query.execute)
65
+ rescue GrafanaReporterError => e
66
+ @report.logger.error(e.message)
67
+ create_inline(parent, :quoted, e.message)
68
+ rescue StandardError => e
69
+ @report.logger.fatal(e.message)
70
+ create_inline(parent, :quoted, e.message)
71
+ end
72
+ end
73
+
74
+ # @see ProcessorMixin#build_demo_entry
75
+ def build_demo_entry(panel)
76
+ return nil unless panel
77
+ return nil unless panel.model['type'] == 'singlestat'
78
+
79
+ ref_id = nil
80
+ panel.model['targets'].each do |item|
81
+ if !item['hide'] && !panel.query(item['refId']).to_s.empty?
82
+ ref_id = item['refId']
83
+ break
84
+ end
85
+ end
86
+ return nil unless ref_id
87
+
88
+ "it's easily possible to include the query value: grafana_panel_query_value:#{panel.id}[query=\"#{ref_id}\""\
89
+ ",dashboard=\"#{panel.dashboard.id}\"] - just within this text."
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GrafanaReporter
4
+ module Asciidoctor
5
+ # This module contains common methods for all asciidoctor extensions.
6
+ module ProcessorMixin
7
+ # Used when initializing a object instance, to set the report object, which is currently in progress.
8
+ # @param report [GrafanaReporter::Asciidoctor::Report] current report
9
+ # @return [::Asciidoctor::Extensions::Processor] self
10
+ def current_report(report)
11
+ @report = report
12
+ self
13
+ end
14
+
15
+ # This method is called if a demo report shall be built for the given {Grafana::Panel}.
16
+ # @param panel [Grafana::Panel] panel object, for which a demo entry shall be created.
17
+ # @return [String] String containing the entry, or nil if not possible for given panel
18
+ def build_demo_entry(panel)
19
+ raise NotImplementedError
20
+ end
21
+
22
+ # Sets default configurations from the given {Grafana::Dashboard} and store them as settings in the
23
+ # {AbstractQuery}.
24
+ #
25
+ # Following data is extracted:
26
+ # - +from+, by {Grafana::Dashboard#from_time}
27
+ # - +to+, by {Grafana::Dashboard#to_time}
28
+ # - and all variables as {Grafana::Variable}, prefixed with +var-+, as grafana also does it
29
+ # @param query [AbstractQuery] query object, for which the defaults are set
30
+ # @param dashboard [Grafana::Dashboard] dashboard from which the defaults are captured
31
+ # TODO: assign_dashboard_defaults is a common method for all report classes - move it to a public place
32
+ def assign_dashboard_defaults(query, dashboard)
33
+ query.from = dashboard.from_time
34
+ query.to = dashboard.to_time
35
+ dashboard.variables.each { |item| query.assign_variable("var-#{item.name}", item) }
36
+ end
37
+
38
+ # Merges the given hashes to the given query object. It respects the priorities of the hashes and the
39
+ # object and allows only valid variables to be passed.
40
+ # @param query [AbstractQuery] query object, for which the defaults are set
41
+ # @param document_hash [Hash] variables from report template level
42
+ # @param item_hash [Hash] variables from item configuration level, i.e. specific call, which may override document
43
+ # @return [void]
44
+ def assign_doc_and_item_variables(query, document_hash, item_hash)
45
+ sel_doc_items = document_hash.select do |k, _v|
46
+ k =~ /^var-/ || k =~ /grafana_default_(?:from|to)_timezone/
47
+ end
48
+ sel_doc_items.each { |k, v| query.assign_variable(k, ::Grafana::Variable.new(v)) }
49
+ query.assign_variable('grafana_report_timestamp', ::Grafana::Variable.new(document_hash['localdatetime']))
50
+
51
+ sel_items = item_hash.select do |k, _v|
52
+ # TODO: specify accepted options in each class or check if simply all can be allowed with prefix +var-+
53
+ k =~ /^var-/ || k =~ /^render-/ || k =~ /filter_columns|format|replace_values_.*|transpose|column_divider|
54
+ row_divider|from_timezone|to_timezone|result_type|query/x
55
+ end
56
+ sel_items.each { |k, v| query.assign_variable(k, ::Grafana::Variable.new(v)) }
57
+
58
+ query.timeout = item_hash['timeout'] || document_hash['grafana-default-timeout'] || query.timeout
59
+ query.from = item_hash['from'] || document_hash['from'] || query.from
60
+ query.to = item_hash['to'] || document_hash['to'] || query.to
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,27 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GrafanaReporter
4
+ # This module contains all classes, which are necessary to use the reporter in conjunction with asciidoctor.
4
5
  module Asciidoctor
5
6
  # Implementation of a specific {AbstractReport}. It is used to
6
7
  # build reports specifically for asciidoctor results.
7
- class Report < GrafanaReporter::AbstractReport
8
- # (see AbstractReport#initialize)
9
- def initialize(config, template, destination_file_or_path = nil, custom_attributes = {})
8
+ class Report < ::GrafanaReporter::AbstractReport
9
+ # @see AbstractReport#initialize
10
+ def initialize(config)
10
11
  super
11
- @current_pos = 0
12
12
  @image_files = []
13
- @grafana_instances = {}
14
13
  end
15
14
 
16
- # Starts to create an asciidoctor report. It utilizes all {Extensions} to
17
- # realize the conversion.
15
+ # Starts to create an asciidoctor report. It utilizes all extensions in the {GrafanaReporter::Asciidoctor}
16
+ # namespace to realize the conversion.
18
17
  # @see AbstractReport#create_report
19
- # @return [void]
20
- def create_report
21
- @start_time = Time.now
18
+ def create_report(template, destination_file_or_path = nil, custom_attributes = {})
19
+ super
22
20
  attrs = { 'convert-backend' => 'pdf' }.merge(@config.default_document_attributes.merge(@custom_attributes))
23
- attrs['grafana-report-timestamp'] = @start_time.to_s
24
- logger.info("Report started at #{@start_time}")
25
21
  logger.debug("Document attributes: #{attrs}")
26
22
 
27
23
  initialize_step_counter
@@ -30,19 +26,18 @@ module GrafanaReporter
30
26
  ::Asciidoctor::LoggerManager.logger = logger
31
27
 
32
28
  registry = ::Asciidoctor::Extensions::Registry.new
33
- # TODO: dynamically register macros, which is also needed when supporting custom macros
34
- registry.inline_macro Extensions::PanelImageInlineMacro.new.current_report(self)
35
- registry.inline_macro Extensions::PanelQueryValueInlineMacro.new.current_report(self)
36
- registry.inline_macro Extensions::PanelPropertyInlineMacro.new.current_report(self)
37
- registry.inline_macro Extensions::SqlValueInlineMacro.new.current_report(self)
38
- registry.block_macro Extensions::PanelImageBlockMacro.new.current_report(self)
39
- registry.include_processor Extensions::ValueAsVariableIncludeProcessor.new.current_report(self)
40
- registry.include_processor Extensions::PanelQueryTableIncludeProcessor.new.current_report(self)
41
- registry.include_processor Extensions::SqlTableIncludeProcessor.new.current_report(self)
42
- registry.include_processor Extensions::ShowEnvironmentIncludeProcessor.new.current_report(self)
43
- registry.include_processor Extensions::ShowHelpIncludeProcessor.new.current_report(self)
44
- registry.include_processor Extensions::AnnotationsTableIncludeProcessor.new.current_report(self)
45
- registry.include_processor Extensions::AlertsTableIncludeProcessor.new.current_report(self)
29
+ registry.inline_macro PanelImageInlineMacro.new.current_report(self)
30
+ registry.inline_macro PanelQueryValueInlineMacro.new.current_report(self)
31
+ registry.inline_macro PanelPropertyInlineMacro.new.current_report(self)
32
+ registry.inline_macro SqlValueInlineMacro.new.current_report(self)
33
+ registry.block_macro PanelImageBlockMacro.new.current_report(self)
34
+ registry.include_processor ValueAsVariableIncludeProcessor.new.current_report(self)
35
+ registry.include_processor PanelQueryTableIncludeProcessor.new.current_report(self)
36
+ registry.include_processor SqlTableIncludeProcessor.new.current_report(self)
37
+ registry.include_processor ShowEnvironmentIncludeProcessor.new.current_report(self)
38
+ registry.include_processor ShowHelpIncludeProcessor.new.current_report(self)
39
+ registry.include_processor AnnotationsTableIncludeProcessor.new.current_report(self)
40
+ registry.include_processor AlertsTableIncludeProcessor.new.current_report(self)
46
41
 
47
42
  ::Asciidoctor.convert_file(@template, extension_registry: registry, backend: attrs['convert-backend'],
48
43
  to_file: path, attributes: attrs, header_footer: true)
@@ -51,29 +46,28 @@ module GrafanaReporter
51
46
 
52
47
  # store report including als images as ZIP file, if the result is not a PDF
53
48
  if attrs['convert-backend'] != 'pdf'
54
- dest_path = nil
55
- case
56
- when @destination_file_or_path.is_a?(File)
57
- dest_path = @destination_file_or_path.path
58
- when @destination_file_or_path.is_a?(Tempfile)
59
- dest_path = @destination_file_or_path.path
60
- else
61
- dest_path = @destination_file_or_path
62
- end
49
+ dest_path = if @destination_file_or_path.is_a?(File) || @destination_file_or_path.is_a?(Tempfile)
50
+ @destination_file_or_path.path
51
+ else
52
+ @destination_file_or_path
53
+ end
63
54
 
64
55
  # build zip file
65
56
  zip_file = Tempfile.new('gf_zip')
66
- Zip::File.open(zip_file.path, Zip::File::CREATE) do |zipfile|
57
+ buffer = Zip::OutputStream.write_buffer do |zipfile|
67
58
  # add report file
68
- zipfile.get_output_stream("#{dest_path.gsub(@config.reports_folder, '')}.#{attrs['convert-backend']}") do |f|
69
- f.puts File.read(dest_path)
70
- end
59
+ zipfile.put_next_entry("#{dest_path.gsub(@config.reports_folder, '')}.#{attrs['convert-backend']}")
60
+ zipfile.write File.read(dest_path)
71
61
 
72
62
  # add image files
73
63
  @image_files.each do |file|
74
- zipfile.get_output_stream(file.path.gsub(@config.images_folder, '')) { |f| f.puts File.read(file.path) }
64
+ zipfile.put_next_entry(file.path.gsub(@config.images_folder, ''))
65
+ zipfile.write File.read(file.path)
75
66
  end
76
67
  end
68
+ File.open(zip_file, 'wb') do |f|
69
+ f.write buffer.string
70
+ end
77
71
 
78
72
  # replace original file with zip file
79
73
  zip_file.rewind
@@ -89,40 +83,17 @@ module GrafanaReporter
89
83
  end
90
84
 
91
85
  clean_image_files
92
- @end_time = Time.now
93
- logger.info("Report finished after #{@end_time - @start_time} seconds.")
94
- @done = true
86
+ rescue MissingTemplateError => e
87
+ @logger.error(e.message)
88
+ @error = [e.message]
89
+ done!
90
+ raise e
95
91
  rescue StandardError => e
96
92
  # catch all errors during execution
97
93
  died_with_error(e)
98
94
  raise e
99
- end
100
-
101
- # @see AbstractReport#progress
102
- # @return [Float] number between 0 and 1 reflecting the current progress.
103
- def progress
104
- return 0 if @total_steps.to_i.zero?
105
-
106
- @current_pos.to_f / @total_steps
107
- end
108
-
109
- # @param instance [String] requested grafana instance
110
- # @return [Grafana::Grafana] the requested grafana instance.
111
- def grafana(instance)
112
- unless @grafana_instances[instance]
113
- @grafana_instances[instance] = ::Grafana::Grafana.new(@config.grafana_host(instance),
114
- @config.grafana_api_key(instance),
115
- logger: @logger,
116
- datasources: @config.grafana_datasources(instance))
117
- end
118
- @grafana_instances[instance]
119
- end
120
-
121
- # Increments the progress.
122
- # @return [Integer] number of the current progress position.
123
- def next_step
124
- @current_pos += 1
125
- @current_pos
95
+ ensure
96
+ done!
126
97
  end
127
98
 
128
99
  # Called to save a temporary image file. After the final generation of the
@@ -131,6 +102,7 @@ module GrafanaReporter
131
102
  # @return [String] path to the temporary file.
132
103
  def save_image_file(img_data)
133
104
  file = Tempfile.new(['gf_image_', '.png'], @config.images_folder.to_s)
105
+ file.binmode
134
106
  file.write(img_data)
135
107
  path = file.path.gsub(/#{@config.images_folder}/, '')
136
108
 
@@ -140,13 +112,11 @@ module GrafanaReporter
140
112
  path
141
113
  end
142
114
 
143
- # Called, if the report generation has died with an error.
144
- # @param error [StandardError] occured error
145
- # @return [void]
146
- def died_with_error(error)
147
- @error = [error.message] << [error.backtrace]
148
- @end_time = Time.now
149
- @done = true
115
+ # @see AbstractReport#demo_report_classes
116
+ def self.demo_report_classes
117
+ [AlertsTableIncludeProcessor, AnnotationsTableIncludeProcessor, PanelImageBlockMacro, PanelImageInlineMacro,
118
+ PanelPropertyInlineMacro, PanelQueryTableIncludeProcessor, PanelQueryValueInlineMacro,
119
+ SqlTableIncludeProcessor, SqlValueInlineMacro, ShowHelpIncludeProcessor, ShowEnvironmentIncludeProcessor]
150
120
  end
151
121
 
152
122
  private
@@ -160,6 +130,7 @@ module GrafanaReporter
160
130
  @total_steps = 0
161
131
  File.readlines(@template).each do |line|
162
132
  begin
133
+ # TODO: move these calls to the specific processors to ensure all are counted properly
163
134
  @total_steps += line.gsub(%r{//.*}, '').scan(/(?:grafana_panel_image|grafana_panel_query_value|
164
135
  grafana_panel_query_table|grafana_sql_value|
165
136
  grafana_sql_table|grafana_environment|grafana_help|