ruby-grafana-reporter 0.4.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +185 -180
  3. data/lib/VERSION.rb +2 -2
  4. data/lib/grafana/abstract_datasource.rb +32 -12
  5. data/lib/grafana/errors.rb +1 -9
  6. data/lib/grafana/grafana.rb +3 -7
  7. data/lib/grafana/graphite_datasource.rb +6 -0
  8. data/lib/grafana/prometheus_datasource.rb +6 -0
  9. data/lib/grafana/sql_datasource.rb +6 -0
  10. data/lib/grafana/unsupported_datasource.rb +7 -0
  11. data/lib/grafana/webrequest.rb +1 -1
  12. data/lib/grafana_reporter/abstract_query.rb +20 -62
  13. data/lib/grafana_reporter/abstract_report.rb +66 -15
  14. data/lib/grafana_reporter/alerts_table_query.rb +5 -5
  15. data/lib/grafana_reporter/annotations_table_query.rb +4 -4
  16. data/lib/grafana_reporter/application/application.rb +10 -16
  17. data/lib/grafana_reporter/application/webservice.rb +34 -10
  18. data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +5 -5
  19. data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +5 -5
  20. data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +2 -1
  21. data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +7 -5
  22. data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +2 -1
  23. data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +6 -5
  24. data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +5 -5
  25. data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +43 -2
  26. data/lib/grafana_reporter/asciidoctor/report.rb +17 -41
  27. data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +4 -4
  28. data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +4 -4
  29. data/lib/grafana_reporter/configuration.rb +14 -2
  30. data/lib/grafana_reporter/console_configuration_wizard.rb +2 -10
  31. data/lib/grafana_reporter/demo_report_wizard.rb +16 -2
  32. data/lib/grafana_reporter/erb/report.rb +43 -0
  33. data/lib/grafana_reporter/errors.rb +9 -1
  34. data/lib/grafana_reporter/help.rb +1 -5
  35. data/lib/grafana_reporter/logger/{two_way_logger.rb → two_way_delegate_logger.rb} +0 -0
  36. data/lib/grafana_reporter/panel_image_query.rb +2 -2
  37. data/lib/grafana_reporter/query_value_query.rb +4 -4
  38. data/lib/ruby_grafana_extension.rb +8 -0
  39. data/lib/ruby_grafana_reporter.rb +13 -0
  40. metadata +9 -6
@@ -13,6 +13,10 @@ module GrafanaReporter
13
13
  class Configuration
14
14
  # @return [AbstractReport] specific report class, which should be used.
15
15
  attr_accessor :report_class
16
+ attr_accessor :logger
17
+
18
+ # Default file name for grafana reporter configuration file
19
+ DEFAULT_CONFIG_FILE_NAME = 'grafana_reporter.config'
16
20
 
17
21
  # Returned by {#mode} if only a connection test shall be executed.
18
22
  MODE_CONNECTION_TEST = 'test'
@@ -30,7 +34,15 @@ module GrafanaReporter
30
34
  @logger = ::Logger.new($stderr, level: :info)
31
35
  end
32
36
 
33
- attr_accessor :logger
37
+ # Reads a given configuration file.
38
+ # @param config_file [String] path to configuration file, defaults to DEFAULT_CONFIG_FILE_NAME
39
+ # @return [Hash] configuration hash to be set as {Configuration#config}
40
+ def load_config_from_file(config_file = nil)
41
+ config_file ||= DEFAULT_CONFIG_FILE_NAME
42
+ self.config = YAML.load_file(config_file)
43
+ rescue StandardError => e
44
+ raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})"
45
+ end
34
46
 
35
47
  # Used to overwrite the current configuration.
36
48
  def config=(new_config)
@@ -53,7 +65,7 @@ module GrafanaReporter
53
65
  def template
54
66
  return nil if get_config('default-document-attributes:var-template').nil?
55
67
 
56
- "#{templates_folder}#{get_config('default-document-attributes:var-template')}.adoc"
68
+ "#{templates_folder}#{get_config('default-document-attributes:var-template')}"
57
69
  end
58
70
 
59
71
  # @return [String] destination filename for the report in {MODE_SINGLE_RENDER}.
@@ -31,7 +31,7 @@ module GrafanaReporter
31
31
  demo_report = create_demo_report(config)
32
32
 
33
33
  demo_report ||= '<<your_report_name>>'
34
- config_param = config_file == Application::Application::CONFIG_FILE ? '' : " -c #{config_file}"
34
+ config_param = config_file == Configuration::DEFAULT_CONFIG_FILE_NAME ? '' : " -c #{config_file}"
35
35
  program_call = "#{Gem.ruby} #{$PROGRAM_NAME}"
36
36
  program_call = ENV['OCRA_EXECUTABLE'].gsub("#{Dir.pwd}/".gsub('/', '\\'), '') if ENV['OCRA_EXECUTABLE']
37
37
 
@@ -137,16 +137,8 @@ default-document-attributes:
137
137
  end
138
138
  end
139
139
 
140
- # TODO: move this to Asciidoctor::Report class
141
- classes = [Asciidoctor::AlertsTableIncludeProcessor, Asciidoctor::AnnotationsTableIncludeProcessor,
142
- Asciidoctor::PanelImageBlockMacro, Asciidoctor::PanelImageInlineMacro,
143
- Asciidoctor::PanelPropertyInlineMacro, Asciidoctor::PanelQueryTableIncludeProcessor,
144
- Asciidoctor::PanelQueryValueInlineMacro, Asciidoctor::SqlTableIncludeProcessor,
145
- Asciidoctor::SqlValueInlineMacro, Asciidoctor::ShowHelpIncludeProcessor,
146
- Asciidoctor::ShowEnvironmentIncludeProcessor]
147
-
148
140
  grafana = ::Grafana::Grafana.new(config.grafana_host, config.grafana_api_key)
149
- demo_report_content = DemoReportWizard.new(classes).build(grafana)
141
+ demo_report_content = DemoReportWizard.new(config.report_class.demo_report_classes).build(grafana)
150
142
 
151
143
  begin
152
144
  File.write(demo_report_file, demo_report_content, mode: 'w')
@@ -26,8 +26,15 @@ module GrafanaReporter
26
26
  puts "done - #{(@query_classes - results.keys).length} examples to go"
27
27
  break if (@query_classes - results.keys).empty?
28
28
  end
29
- puts 'Aborting evaluating further dashboards after 15 samples.' if grafana.dashboard_ids.length > 15 and !(@query_classes - results.keys).empty?
30
- puts "For #{(@query_classes - results.keys).length} reporter functionalities no appropriate examples could be found in the configured grafana instance." unless (@query_classes - results.keys).empty?
29
+
30
+ if grafana.dashboard_ids.length > 15 && !(@query_classes - results.keys).empty?
31
+ puts 'Aborting evaluating further dashboards after 15 samples.'
32
+ end
33
+
34
+ unless (@query_classes - results.keys).empty?
35
+ puts "For #{(@query_classes - results.keys).length} reporter functionalities no appropriate "\
36
+ 'examples could be found in the configured grafana instance.'
37
+ end
31
38
 
32
39
  format_results(default_result(@query_classes - results.keys).merge(results))
33
40
  end
@@ -48,6 +55,8 @@ module GrafanaReporter
48
55
  results = {}
49
56
 
50
57
  dashboard.panels.shuffle.each do |panel|
58
+ next if panel.datasource.is_a?(Grafana::UnsupportedDatasource)
59
+
51
60
  query_classes.each do |query_class|
52
61
  unless query_class.public_instance_methods.include?(:build_demo_entry)
53
62
  results[query_class] = "Method 'build_demo_entry' not implemented for #{query_class.name}"
@@ -57,6 +66,11 @@ module GrafanaReporter
57
66
  begin
58
67
  result = query_class.new.build_demo_entry(panel)
59
68
  results[query_class] = result if result
69
+ rescue Grafana::DatasourceDoesNotExistError
70
+ # properly catch DatasourceDoesNotExist errors here, as they don't lead to a real issue
71
+ # during demo report creation
72
+ # This may e.g. happen if a panel asks e.g. for datasource '-- Dashboard --' which is
73
+ # currently not allowed
60
74
  rescue StandardError => e
61
75
  puts "#{e.message}\n#{e.backtrace.join("\n")}"
62
76
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'erb'
4
+
5
+ module GrafanaReporter
6
+ module ERB
7
+ # Implementation of a specific {AbstractReport}. It is used to
8
+ # build reports specifically for erb templates.
9
+ class Report < ::GrafanaReporter::AbstractReport
10
+ # Starts to create an asciidoctor report. It utilizes all extensions in the {GrafanaReporter::Asciidoctor}
11
+ # namespace to realize the conversion.
12
+ # @see AbstractReport#create_report
13
+ def create_report(template, destination_file_or_path = nil, custom_attributes = {})
14
+ super
15
+ attrs = @config.default_document_attributes.merge(@custom_attributes)
16
+ logger.debug("Document attributes: #{attrs}")
17
+
18
+ # TODO: if path is true, a default filename has to be generated. check if this should be a general function instead
19
+ @report = self
20
+ File.write(path, ::ERB.new(File.read(template)).result(binding))
21
+
22
+ # TODO: check if closing output file is correct here, or maybe can be moved to AbstractReport.done!
23
+ @destination_file_or_path.close if @destination_file_or_path.is_a?(File)
24
+ rescue MissingTemplateError => e
25
+ @logger.error(e.message)
26
+ @error = [e.message]
27
+ done!
28
+ raise e
29
+ rescue StandardError => e
30
+ # catch all errors during execution
31
+ died_with_error(e)
32
+ raise e
33
+ ensure
34
+ done!
35
+ end
36
+
37
+ # @see AbstractReport#demo_report_classes
38
+ def self.demo_report_classes
39
+ []
40
+ end
41
+ end
42
+ end
43
+ end
@@ -8,6 +8,14 @@ module GrafanaReporter
8
8
  end
9
9
  end
10
10
 
11
+ # Raised if a datasource shall be queried, which is not (yet) supported by the reporter
12
+ class DatasourceNotSupportedError < GrafanaReporterError
13
+ def initialize(ds, query)
14
+ super("The datasource '#{ds.name}' is of type '#{ds.type}' which is currently not supported for "\
15
+ "the query type '#{query}'.")
16
+ end
17
+ end
18
+
11
19
  # Thrown, if the requested grafana instance does not have the mandatory 'host'
12
20
  # setting configured.
13
21
  class GrafanaInstanceWithoutHostError < GrafanaReporterError
@@ -46,7 +54,7 @@ module GrafanaReporter
46
54
  end
47
55
  end
48
56
 
49
- # Thrown, if the value configuration in {QueryMixin#replace_values} is
57
+ # Thrown, if the value configuration in {AbstractQuery#replace_values} is
50
58
  # invalid.
51
59
  class MalformedReplaceValuesStatementError < GrafanaReporterError
52
60
  def initialize(statement)
@@ -18,11 +18,6 @@ module GrafanaReporter
18
18
  "#{toc}\n\n#{help_text(github_options.merge(level: headline_level))}"
19
19
  end
20
20
 
21
- # @see AbstractQuery#self.build_demo_entry
22
- def self.build_demo_entry(_panel)
23
- 'include::grafana_help[]'
24
- end
25
-
26
21
  private
27
22
 
28
23
  def github_options
@@ -134,6 +129,7 @@ end}
134
129
  result
135
130
  end
136
131
 
132
+ # TODO: use same wording/grouping as in README file
137
133
  def raw_help_yaml
138
134
  <<~YAML_HELP
139
135
  global_options:
@@ -5,9 +5,9 @@ module GrafanaReporter
5
5
  class PanelImageQuery < AbstractQuery
6
6
  # Sets the proper render variables.
7
7
  def pre_process
8
- @from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] ||
8
+ @from = translate_date(@from, @variables['grafana_report_timestamp'], false, @variables['from_timezone'] ||
9
9
  @variables['grafana_default_from_timezone'])
10
- @to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] ||
10
+ @to = translate_date(@to, @variables['grafana_report_timestamp'], true, @variables['to_timezone'] ||
11
11
  @variables['grafana_default_to_timezone'])
12
12
  # TODO: ensure that in case of timezones are specified, that they are also forwarded to the image renderer
13
13
  # rename "render-" variables
@@ -8,15 +8,15 @@ module GrafanaReporter
8
8
  def pre_process
9
9
  @datasource = @panel.datasource if @panel
10
10
 
11
- @from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] ||
11
+ @from = translate_date(@from, @variables['grafana_report_timestamp'], false, @variables['from_timezone'] ||
12
12
  @variables['grafana_default_from_timezone'])
13
- @to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] ||
13
+ @to = translate_date(@to, @variables['grafana_report_timestamp'], true, @variables['to_timezone'] ||
14
14
  @variables['grafana_default_to_timezone'])
15
15
  @variables['result_type'] ||= Variable.new('')
16
16
  end
17
17
 
18
- # Executes {QueryMixin#format_columns}, {QueryMixin#replace_values} and
19
- # {QueryMixin#filter_columns} on the query results.
18
+ # Executes {AbstractQuery#format_columns}, {AbstractQuery#replace_values} and
19
+ # {AbstractQuery#filter_columns} on the query results.
20
20
  #
21
21
  # Finally the results are formatted as a asciidoctor table.
22
22
  # @see Grafana::AbstractQuery#post_process
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ruby_grafana_reporter'
4
+
5
+ config = GrafanaReporter::Configuration.new
6
+ config.config = GrafanaReporter::Application::Application.load_config
7
+
8
+ GrafanaReporter::Asciidoctor::Report.new(config).register
@@ -18,12 +18,25 @@ require 'asciidoctor-pdf'
18
18
  require 'zip'
19
19
  require_relative 'VERSION'
20
20
 
21
+ # TODO: show error in document, if grafana could not be accessed
22
+ # TODO: show backtrace in extension error rescues
23
+ # TODO: improve ERB calls
24
+ # TODO: add test case for proper image generation
25
+ # TODO: allow to choose report-class during execution, not mandatory by config file
26
+ # TODO: add docu for ERB reports
27
+ # TODO: add docu for custom plugins
28
+ # TODO: add docu for webhook
29
+
30
+ # TODO: enable as asciidoctor extension
31
+ # TODO: build ADOC template as a result with resolved grafana content for further editing
32
+
21
33
  folders = [
22
34
  %w[grafana],
23
35
  %w[grafana_reporter logger],
24
36
  %w[grafana_reporter],
25
37
  %w[grafana_reporter asciidoctor extensions],
26
38
  %w[grafana_reporter asciidoctor],
39
+ %w[grafana_reporter erb],
27
40
  %w[grafana_reporter application]
28
41
  ]
29
42
  folders.each { |folder| Dir[File.join(__dir__, *folder, '*.rb')].sort.each { |file| require_relative file } }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-grafana-reporter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christian Kohlmeyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-14 00:00:00.000000000 Z
11
+ date: 2021-05-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: asciidoctor
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.5'
33
+ version: '1.6'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '1.5'
40
+ version: '1.6'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubyzip
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -124,6 +124,7 @@ files:
124
124
  - "./lib/grafana/panel.rb"
125
125
  - "./lib/grafana/prometheus_datasource.rb"
126
126
  - "./lib/grafana/sql_datasource.rb"
127
+ - "./lib/grafana/unsupported_datasource.rb"
127
128
  - "./lib/grafana/variable.rb"
128
129
  - "./lib/grafana/webrequest.rb"
129
130
  - "./lib/grafana_reporter/abstract_query.rb"
@@ -150,13 +151,15 @@ files:
150
151
  - "./lib/grafana_reporter/configuration.rb"
151
152
  - "./lib/grafana_reporter/console_configuration_wizard.rb"
152
153
  - "./lib/grafana_reporter/demo_report_wizard.rb"
154
+ - "./lib/grafana_reporter/erb/report.rb"
153
155
  - "./lib/grafana_reporter/errors.rb"
154
156
  - "./lib/grafana_reporter/help.rb"
155
- - "./lib/grafana_reporter/logger/two_way_logger.rb"
157
+ - "./lib/grafana_reporter/logger/two_way_delegate_logger.rb"
156
158
  - "./lib/grafana_reporter/panel_image_query.rb"
157
159
  - "./lib/grafana_reporter/panel_property_query.rb"
158
160
  - "./lib/grafana_reporter/query_value_query.rb"
159
161
  - "./lib/grafana_reporter/report_webhook.rb"
162
+ - "./lib/ruby_grafana_extension.rb"
160
163
  - "./lib/ruby_grafana_reporter.rb"
161
164
  - LICENSE
162
165
  - README.md
@@ -175,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
175
178
  requirements:
176
179
  - - ">="
177
180
  - !ruby/object:Gem::Version
178
- version: 2.3.3
181
+ version: '2.5'
179
182
  required_rubygems_version: !ruby/object:Gem::Requirement
180
183
  requirements:
181
184
  - - ">="