ruby-grafana-reporter 0.2.0 → 0.2.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 +162 -166
- data/bin/ruby-grafana-reporter +5 -5
- data/lib/VERSION.rb +2 -2
- data/lib/grafana/abstract_query.rb +1 -1
- data/lib/grafana/grafana.rb +1 -1
- data/lib/grafana/variable.rb +2 -2
- data/lib/grafana_reporter/application/application.rb +35 -31
- data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +1 -1
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +1 -1
- data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +47 -21
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +27 -2
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +1 -1
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +4 -20
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -5
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -5
- data/lib/grafana_reporter/configuration.rb +64 -6
- data/lib/ruby-grafana-reporter.rb +2 -0
- metadata +9 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f95b8d5f6221cb369bf0d11671823394683a60299dff0e688da9c5f0eab3246
|
4
|
+
data.tar.gz: 245804ca1843422b29a8bf8866dfaf75ec916a329f2de05739436e580c32b6e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84d7265803d6cfedec4f63b9a2938ed181bfdd9f9865bafbd3953c5a208de129e4029dd1bd8855c38ceefb9b215ea071a69242bb8ba6bfacd3f38c14e5a72e5e
|
7
|
+
data.tar.gz: a28e456174baae970bbe0d2abc76675e6900ce3e821b6e35a215f5ee81ff760a61ccf757bc1c5c5d7b79e8e5ac8488f7edde5d1c7f3d708399a60dade839c9dc
|
data/README.md
CHANGED
@@ -1,166 +1,162 @@
|
|
1
|
-
[](https://github.com/divinity666/ruby-grafana-reporter/blob/master/LICENSE)
|
2
|
-
[](https://travis-ci.org/github/divinity666/ruby-grafana-reporter?branch=master)
|
3
|
-
[](https://coveralls.io/github/divinity666/ruby-grafana-reporter?branch=master)
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
* [
|
12
|
-
|
13
|
-
* [
|
14
|
-
* [
|
15
|
-
* [
|
16
|
-
* [
|
17
|
-
* [
|
18
|
-
* [
|
19
|
-
* [
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
*
|
81
|
-
*
|
82
|
-
*
|
83
|
-
*
|
84
|
-
*
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
template.
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
*
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
##
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
support my work, feel free donate, even a cup of coffee is appreciated :)
|
164
|
-
|
165
|
-
[](https://www.paypal.com/donate?hosted_button_id=35LH6JNLPHPHQ)
|
166
|
-
|
1
|
+
[](https://github.com/divinity666/ruby-grafana-reporter/blob/master/LICENSE)
|
2
|
+
[](https://travis-ci.org/github/divinity666/ruby-grafana-reporter?branch=master)
|
3
|
+
[](https://coveralls.io/github/divinity666/ruby-grafana-reporter?branch=master)
|
4
|
+
[](https://badge.fury.io/rb/ruby-grafana-reporter)
|
5
|
+
|
6
|
+
# Ruby Grafana Reporter
|
7
|
+
Reporting Service for Grafana
|
8
|
+
|
9
|
+
## Table of Contents
|
10
|
+
|
11
|
+
* [About the project](#about-the-project)
|
12
|
+
* [Getting started](#getting-started)
|
13
|
+
* [Grafana integration](#grafana-integration)
|
14
|
+
* [Webservice overview](#webservice-overview)
|
15
|
+
* [Features](#features)
|
16
|
+
* [Roadmap](#roadmap)
|
17
|
+
* [Contributing](#contributing)
|
18
|
+
* [Licensing](#licensing)
|
19
|
+
* [Acknowledgements](#acknowledgements)
|
20
|
+
* [Donations](#donations)
|
21
|
+
|
22
|
+
## About the project
|
23
|
+
|
24
|
+
Did you ever want to create (professional) reports based on Grafana dashboards?
|
25
|
+
I did so in order to being able to automatically get monthly reports of my
|
26
|
+
home's energy usage. That's how it started.
|
27
|
+
|
28
|
+
The reporter provides reporting capabilities for Grafana. It is based on
|
29
|
+
(but not limited to) [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
30
|
+
report templates, which can dynamically integrate Grafana panels, queries,
|
31
|
+
images etc. to create dynamic PDF reports on the fly.
|
32
|
+
|
33
|
+
The report may also be returned in any other format that asciidoctor supports.
|
34
|
+
|
35
|
+
The reporter can run standalone or as a webservice. It is built to
|
36
|
+
integrate without further dependencies with the asciidoctor docker image.
|
37
|
+
|
38
|
+
The complete
|
39
|
+
[API documentation](https://rubydoc.info/gems/ruby-grafana-reporter) can be
|
40
|
+
found here.
|
41
|
+
|
42
|
+
## Getting started
|
43
|
+
|
44
|
+
There exist several ways of installing the reporter. Here I cover the easiest
|
45
|
+
setup by using ruby gems. If you need further installation help, or want to use
|
46
|
+
a "baremetal" ruby setup or a docker integration, please have a look at the more
|
47
|
+
extended [installation documentation](INSTALL.md).
|
48
|
+
|
49
|
+
To install the reporter as a gem, simply run:
|
50
|
+
|
51
|
+
gem install ruby-grafana-reporter
|
52
|
+
|
53
|
+
If no configuration file is in place, you might want to use the configuration
|
54
|
+
wizard, which leads you through all necessary steps:
|
55
|
+
|
56
|
+
ruby-grafana-reporter -w
|
57
|
+
|
58
|
+
It is strongly recommended, to also create the demo PDF file, as stated at the end
|
59
|
+
of the procedure, to get a detailed documentation of all the reporter capabilities.
|
60
|
+
|
61
|
+
To run the reporter as a service, you only need to call it like this:
|
62
|
+
|
63
|
+
ruby-grafana-reporter
|
64
|
+
|
65
|
+
Neat, isn't it?
|
66
|
+
|
67
|
+
### Grafana integration
|
68
|
+
|
69
|
+
The key feature of the report is, that it can easily be integrated with grafana
|
70
|
+
(I've not even been talking about the features it is providing for that, but
|
71
|
+
you'll find them having a look in the example results above).
|
72
|
+
|
73
|
+
For accessing the reporter from grafana, you need to simply add a link to your
|
74
|
+
grafana dashboard:
|
75
|
+
|
76
|
+
* Open the dashboard configuration
|
77
|
+
* Select `Links`
|
78
|
+
* Select `Add`
|
79
|
+
* Fill out as following:
|
80
|
+
* Type: `link`
|
81
|
+
* Url: `http://<<your-server-url>>:<<your-webservice-port>>/render?var-template=myfirsttemplate`
|
82
|
+
* Title: `MyFirstReport`
|
83
|
+
* Select `Time range`
|
84
|
+
* Select `Variable values`
|
85
|
+
* Select `Add`
|
86
|
+
|
87
|
+
Now go back to your dashboard and click the newly generated 'MyFirstReport'
|
88
|
+
link on it. Now the renderer should start it's task and show you the expected
|
89
|
+
results.
|
90
|
+
|
91
|
+
But now the fun just starts! Try out the functions stated in the
|
92
|
+
'MyFirstReport' PDF file, to include the dynamic content in your asciidoctor
|
93
|
+
template.
|
94
|
+
|
95
|
+
Additionally you might want to make the selection of the template variable.
|
96
|
+
Piece of cake: Just add a dashboard variable to your grafana dashboard named
|
97
|
+
`template` and let the user select or enter a template name. To make use of it,
|
98
|
+
you should change the link of the 'MyFirstReport' link to
|
99
|
+
`http://<<your-server-url>>:<<your-webservice-port>>/render?`
|
100
|
+
|
101
|
+
That's it. Let me know your feedback!
|
102
|
+
|
103
|
+
## Webservice overview
|
104
|
+
|
105
|
+
Running the reporter as a webservice provides the following URLs
|
106
|
+
|
107
|
+
/overview - for all running or retained renderings
|
108
|
+
/render - for rendering a template, 'var-template' is the only mandatory GET parameter
|
109
|
+
/view_report - for viewing the status or receving the result of a specific rendering, is automatically called after a successfull /render call
|
110
|
+
/cancel_report - for cancelling the rendering of a specific report, normally not called manually, but on user interaction in the /view_report or /overview URL
|
111
|
+
|
112
|
+
## Features
|
113
|
+
|
114
|
+
* Build report template including all imaginable grafana content:
|
115
|
+
* panels as images
|
116
|
+
* panel table query or custom query results as real document tables (not images!)
|
117
|
+
* single panel value or custom query single value result integrated in texts
|
118
|
+
* Solid as a rock, also in case of template errors (at least it aims to be)
|
119
|
+
* Runs standalone or as a webservice
|
120
|
+
* Seamlessly integrates with asciidoctor docker container
|
121
|
+
* Developed for being able to support other tools than asciidoctor as well
|
122
|
+
|
123
|
+
## Roadmap
|
124
|
+
|
125
|
+
This is just a collection of things, I am heading for in future, without a schedule.
|
126
|
+
|
127
|
+
* Add documentation of possible asciidoctor calls to grafana
|
128
|
+
* Add a simple plugin system to support specific asciidoctor modifications
|
129
|
+
* Solve code TODOs
|
130
|
+
* Become [rubocop](https://rubocop.org/) ready
|
131
|
+
|
132
|
+
## Contributing
|
133
|
+
|
134
|
+
If you'd like to contribute, please fork the repository and use a feature
|
135
|
+
branch. Pull requests are warmly welcome.
|
136
|
+
|
137
|
+
Though not yet valid for my code, I'd like to see the project become
|
138
|
+
[rubocop](https://rubocop.org/) ready :-)
|
139
|
+
|
140
|
+
Definitely open spots from my side are:
|
141
|
+
|
142
|
+
* This README
|
143
|
+
* Clean and properly setup test cases
|
144
|
+
|
145
|
+
## Licensing
|
146
|
+
|
147
|
+
The code in this project is licensed under MIT license.
|
148
|
+
|
149
|
+
## Acknowledgements
|
150
|
+
* [asciidoctor](https://github.com/asciidoctor/asciidoctor)
|
151
|
+
* [asciidoctor-pdf](https://github.com/asciidoctor/asciidoctor-pdf)
|
152
|
+
* [grafana](https://github.com/grafana/grafana)
|
153
|
+
|
154
|
+
Inspired by [Izak Marai's grafana reporter](https://github.com/IzakMarais/reporter)
|
155
|
+
|
156
|
+
## Donations
|
157
|
+
|
158
|
+
If this project saves you as much time as I hope it does, and if you'd like to
|
159
|
+
support my work, feel free donate, even a cup of coffee is appreciated :)
|
160
|
+
|
161
|
+
[](https://www.paypal.com/donate?hosted_button_id=35LH6JNLPHPHQ)
|
162
|
+
|
data/bin/ruby-grafana-reporter
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../lib/ruby-grafana-reporter'
|
5
|
-
GrafanaReporter::Application::Application.new.configure_and_run(ARGV)
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative '../lib/ruby-grafana-reporter'
|
5
|
+
GrafanaReporter::Application::Application.new.configure_and_run(ARGV)
|
data/lib/VERSION.rb
CHANGED
@@ -87,7 +87,7 @@ module Grafana
|
|
87
87
|
# only set ticks if value is string
|
88
88
|
variable = var_name.gsub(/^var-/, '')
|
89
89
|
res = res.gsub(/(?:\$\{#{variable}(?::(?<format>\w+))?\}|(?<!\.)\$#{variable}(?!\.))/) do
|
90
|
-
obj.value_formatted($LAST_MATCH_INFO[:format])
|
90
|
+
obj.value_formatted($LAST_MATCH_INFO ? $LAST_MATCH_INFO[:format] : nil)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
repeat = true if res.include?('$')
|
data/lib/grafana/grafana.rb
CHANGED
@@ -40,7 +40,7 @@ module Grafana
|
|
40
40
|
# check if we have lower rights
|
41
41
|
return 'Failed' unless execute_http_request('/api/dashboards/home').is_a?(Net::HTTPOK)
|
42
42
|
|
43
|
-
@logger.
|
43
|
+
@logger.info('Reporter is running with NON-Admin privileges on grafana. Make sure that necessary '\
|
44
44
|
'datasources are specified in CONFIG_FILE, otherwise operation will fail')
|
45
45
|
'NON-Admin'
|
46
46
|
end
|
data/lib/grafana/variable.rb
CHANGED
@@ -198,10 +198,10 @@ module Grafana
|
|
198
198
|
h{1,2}|k{1,2}|m{1,2}|s{1,2}|S+|X)/x)
|
199
199
|
if tmp.empty?
|
200
200
|
matches << work_string[0]
|
201
|
-
work_string.
|
201
|
+
work_string.sub!(/^#{work_string[0]}/, '')
|
202
202
|
else
|
203
203
|
matches << tmp[0]
|
204
|
-
work_string.
|
204
|
+
work_string.sub!(/^#{tmp[0]}/, '')
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
@@ -16,22 +16,21 @@ module GrafanaReporter
|
|
16
16
|
# Default file name for grafana reporter configuration file
|
17
17
|
CONFIG_FILE = 'grafana_reporter.config'
|
18
18
|
|
19
|
-
def initialize
|
20
|
-
@logger = ::Logger.new($stdout, level: :unknown)
|
21
|
-
end
|
22
|
-
|
23
19
|
# Contains the {Configuration} object of the application.
|
24
20
|
attr_accessor :config
|
25
21
|
|
22
|
+
def initialize
|
23
|
+
@config = Configuration.new
|
24
|
+
end
|
25
|
+
|
26
26
|
# This is the main method, which is called, if the application is
|
27
27
|
# run in standalone mode.
|
28
28
|
# @param params [Array<String>] command line parameters, mainly ARGV can be used.
|
29
29
|
# @return [Integer] 0 if everything is fine, -1 if execution aborted.
|
30
30
|
def configure_and_run(params = [])
|
31
31
|
config_file = CONFIG_FILE
|
32
|
-
|
33
|
-
|
34
|
-
cli_config ['default-document-attributes'] = {}
|
32
|
+
tmp_config = Configuration.new
|
33
|
+
action_wizard = false
|
35
34
|
|
36
35
|
parser = OptionParser.new do |opts|
|
37
36
|
opts.banner = "Usage: ruby #{$PROGRAM_NAME} [options]"
|
@@ -42,32 +41,30 @@ module GrafanaReporter
|
|
42
41
|
end
|
43
42
|
|
44
43
|
opts.on('-d', '--debug LEVEL', 'Specify detail level: FATAL, ERROR, WARN, INFO, DEBUG.') do |level|
|
45
|
-
|
46
|
-
@logger.level = Object.const_get("::Logger::Severity::#{level}")
|
47
|
-
end
|
44
|
+
tmp_config.set_param('grafana-reporter:debug-level', level)
|
48
45
|
end
|
49
46
|
|
50
47
|
opts.on('-o', '--output FILE', 'Output filename if only a single file is rendered') do |file|
|
51
|
-
|
48
|
+
tmp_config.set_param('to_file', file)
|
52
49
|
end
|
53
50
|
|
54
51
|
opts.on('-s', '--set VARIABLE,VALUE', Array, 'Set a variable value, which will be passed to the rendering') do |list|
|
55
52
|
raise ParameterValueError.new(list.length) unless list.length == 2
|
56
|
-
|
53
|
+
tmp_config.set_param("default-document-attributes:#{list[0]}", list[1])
|
57
54
|
end
|
58
55
|
|
59
56
|
opts.on('--test GRAFANA_INSTANCE', 'test current configuration against given GRAFANA_INSTANCE') do |instance|
|
60
|
-
|
61
|
-
|
57
|
+
tmp_config.set_param('grafana-reporter:run-mode', 'test')
|
58
|
+
tmp_config.set_param('grafana-reporter:test-instance', instance)
|
62
59
|
end
|
63
60
|
|
64
61
|
opts.on('-t', '--template TEMPLATE', 'Render a single ASCIIDOC template to PDF and exit') do |template|
|
65
|
-
|
66
|
-
|
62
|
+
tmp_config.set_param('grafana-reporter:run-mode', 'single-render')
|
63
|
+
tmp_config.set_param('default-document-attributes:var-template', template)
|
67
64
|
end
|
68
65
|
|
69
66
|
opts.on('-w', '--wizard', 'Configuration wizard to prepare environment for the reporter.') do
|
70
|
-
|
67
|
+
action_wizard = true
|
71
68
|
end
|
72
69
|
|
73
70
|
opts.on('-v', '--version', 'Version information') do
|
@@ -83,6 +80,7 @@ module GrafanaReporter
|
|
83
80
|
|
84
81
|
begin
|
85
82
|
parser.parse!(params)
|
83
|
+
return config_wizard(config_file) if action_wizard
|
86
84
|
rescue ApplicationError => e
|
87
85
|
puts e.message
|
88
86
|
return -1
|
@@ -96,8 +94,6 @@ module GrafanaReporter
|
|
96
94
|
end
|
97
95
|
|
98
96
|
# read config file
|
99
|
-
@config = GrafanaReporter::Configuration.new
|
100
|
-
config.logger = @logger
|
101
97
|
config_hash = nil
|
102
98
|
begin
|
103
99
|
config_hash = YAML.load_file(config_file)
|
@@ -106,8 +102,8 @@ module GrafanaReporter
|
|
106
102
|
end
|
107
103
|
|
108
104
|
# merge command line configuration with read config file
|
109
|
-
|
110
|
-
config.
|
105
|
+
@config.config = config_hash
|
106
|
+
@config.merge!(tmp_config)
|
111
107
|
|
112
108
|
run
|
113
109
|
end
|
@@ -147,11 +143,11 @@ module GrafanaReporter
|
|
147
143
|
|
148
144
|
# Provides a command line configuration wizard for setting up the necessary configuration
|
149
145
|
# file.
|
150
|
-
def config_wizard
|
151
|
-
if File.exist?(
|
146
|
+
def config_wizard(config_file)
|
147
|
+
if File.exist?(config_file)
|
152
148
|
input = nil
|
153
149
|
until input
|
154
|
-
input = user_input("Configuration file '#{
|
150
|
+
input = user_input("Configuration file '#{config_file}' already exists. Do you want to overwrite it?", 'yN')
|
155
151
|
return if input =~ /^(?:n|N|yN)$/
|
156
152
|
end
|
157
153
|
end
|
@@ -161,6 +157,8 @@ module GrafanaReporter
|
|
161
157
|
' in the current folder. Please make sure to specify necessary paths'\
|
162
158
|
' either with a relative or an absolute path properly.'
|
163
159
|
puts
|
160
|
+
puts "Wizard is creating configuration file '#{config_file}'."
|
161
|
+
puts
|
164
162
|
port = ui_config_port
|
165
163
|
grafana = ui_config_grafana
|
166
164
|
templates = ui_config_templates_folder
|
@@ -173,6 +171,7 @@ module GrafanaReporter
|
|
173
171
|
#{grafana}
|
174
172
|
|
175
173
|
grafana-reporter:
|
174
|
+
report-class: GrafanaReporter::Asciidoctor::Report
|
176
175
|
templates-folder: #{templates}
|
177
176
|
reports-folder: #{reports}
|
178
177
|
report-retention: #{retention}
|
@@ -184,7 +183,7 @@ default-document-attributes:
|
|
184
183
|
)
|
185
184
|
|
186
185
|
begin
|
187
|
-
File.write(
|
186
|
+
File.write(config_file, config_yaml, mode: 'w')
|
188
187
|
puts 'Configuration file successfully created.'
|
189
188
|
rescue StandardError => e
|
190
189
|
raise e
|
@@ -192,11 +191,11 @@ default-document-attributes:
|
|
192
191
|
|
193
192
|
config = Configuration.new
|
194
193
|
begin
|
195
|
-
config.config = YAML.load_file(
|
194
|
+
config.config = YAML.load_file(config_file)
|
196
195
|
puts 'Configuration file validated successfully.'
|
197
196
|
rescue StandardError => e
|
198
|
-
raise ConfigurationError, "Could not read config file '#{
|
199
|
-
"Source:\n#{File.read(
|
197
|
+
raise ConfigurationError, "Could not read config file '#{config_file}' (Error: #{e.message})\n"\
|
198
|
+
"Source:\n#{File.read(config_file)}"
|
200
199
|
end
|
201
200
|
|
202
201
|
# create a demo report
|
@@ -223,9 +222,14 @@ include::grafana_environment[])
|
|
223
222
|
end
|
224
223
|
|
225
224
|
puts
|
226
|
-
puts 'Now everything is setup properly.
|
225
|
+
puts 'Now everything is setup properly. To create an initial report including a manual of all reporter '\
|
226
|
+
'capabilities with the newly created configuration, call the following command:'
|
227
|
+
puts
|
228
|
+
puts " ruby-grafana-reporter -c #{config_file} -t #{demo_report_file} -o demo_report_with_help.pdf"
|
229
|
+
puts
|
230
|
+
puts 'To start the reporter as a service, call the following command:'
|
227
231
|
puts
|
228
|
-
puts
|
232
|
+
puts " ruby-grafana-reporter -c #{config_file}"
|
229
233
|
puts
|
230
234
|
puts "Open 'http://localhost:#{config.webserver_port}/render?var-template=demo_report' in a webbrowser to"
|
231
235
|
puts 'verify your configuration.'
|
@@ -242,7 +246,7 @@ include::grafana_environment[])
|
|
242
246
|
begin
|
243
247
|
res = Grafana::Grafana.new(url,
|
244
248
|
api_key,
|
245
|
-
logger:
|
249
|
+
logger: config.logger).test_connection
|
246
250
|
rescue StandardError => e
|
247
251
|
puts
|
248
252
|
puts e.message
|
@@ -71,7 +71,7 @@ module GrafanaReporter
|
|
71
71
|
selected_attrs = attrs.select do |k, _v|
|
72
72
|
k =~ /(?:columns|limit|folderId|dashboardId|panelId|dahboardTag|dashboardQuery|state|query)/x
|
73
73
|
end
|
74
|
-
query.merge_variables(selected_attrs.
|
74
|
+
query.merge_variables(selected_attrs.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
|
75
75
|
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
76
76
|
|
77
77
|
begin
|
@@ -70,7 +70,7 @@ module GrafanaReporter
|
|
70
70
|
selected_attrs = attrs.select do |k, _v|
|
71
71
|
k =~ /(?:columns|limit|alertId|dashboardId|panelId|userId|type|tags)/
|
72
72
|
end
|
73
|
-
query.merge_variables(selected_attrs.
|
73
|
+
query.merge_variables(selected_attrs.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
|
74
74
|
@report.logger.debug("from: #{query.from}, to: #{query.to}")
|
75
75
|
|
76
76
|
begin
|
@@ -26,14 +26,20 @@ module GrafanaReporter
|
|
26
26
|
# return if @report.cancel
|
27
27
|
@report.next_step
|
28
28
|
@report.logger.debug('Processing ShowHelpIncludeProcessor')
|
29
|
+
exec_order = 'Execution is applied in the following order: `format`, `replace_values`, `filter_columns`, `transpose`.'
|
29
30
|
|
30
31
|
param_instance = '| `instance="<instance_name>"` | can be used to override global grafana instance, set in the report with `grafana_default_instance`. If nothing is set, the configured grafana instance with name `default` will be used.'
|
31
32
|
param_dashboard = '| `dashboard="<dashboard_uid>"` | Specifies the dashboard to be used. If `grafana_default_dashboard` is specified in the report template, this value can be overridden with this option.'
|
32
33
|
param_from = '| `from="<from_timestamp>"` | can be used to override default `from` time'
|
33
34
|
param_to = '| `to="<to_timestamp>"` | can be used to override default `to` time'
|
34
|
-
|
35
|
-
|
36
|
-
|
35
|
+
|
36
|
+
param_format = '| `format="<format_col1>,<format_col2>,..."` | Specify format in which the results shall be returned, e.g. `%.2f` for only two digit decimals of a float. Several columns are separated by `,`. For details see https://ruby-doc.org/core-2.4.0/Kernel.html#method-i-sprintf[Ruby documentation].'
|
37
|
+
param_replace_values = "| `replace_values=\"<replace_1>:<with_1>,<replace_2>:<with_2>,...\"` | Specify result values which shall be replaced, e.g. `2:OK` will replace query values `2` with value `OK`. Replacing several values is possible by separating by `,`. Matches with regular expressions are also supported, but must be full matches, i.e. have to start with `^` and end with `$`, e.g. `^[012]$:OK`. For details see https://ruby-doc.org/core-2.7.1/Regexp.html#class-Regexp-label-Character+Classes[Ruby Regexp class]. Number replacements can also be performed, e.g. `<8.2` or `<>3`. #{exec_order}"
|
38
|
+
param_filter_columns = '| `filter_columns="<column_name_1>,<column_name_2>,..."` | Removes specified columns from result.'
|
39
|
+
param_transpose = '| `transpose="true"` | Transposes the query result, i.e. columns become rows and rows become columnns.'
|
40
|
+
param_column_divider = '| `column_divider="<divider>"` | Replace the default column divider with another one. Defaults to ` | ` for being interpreted as a asciidoctor column.'
|
41
|
+
param_row_divider = '| `row_divider="<divider>"` | Replace the default row divider with another one. Defaults to `| ` for being interpreted as a asciidoctor row.'
|
42
|
+
param_timeout = '| `timeout="<timeout_in_seconds>" | Set a timeout for the current query. If not overridden with `grafana-default-timeout` in the report template, this defaults to 60 seconds.'
|
37
43
|
|
38
44
|
help = "
|
39
45
|
== Grafana Reporter Functions
|
@@ -60,14 +66,18 @@ module GrafanaReporter
|
|
60
66
|
[%autowidth.stretch, options=\"header\"]
|
61
67
|
|===
|
62
68
|
| Option | Description
|
69
|
+
#{param_column_divider}
|
63
70
|
#{param_dashboard} If this option, or the global option `grafana_default_dashboard` is set, the resulting alerts will be limited to this dashboard. To show all alerts in this case, specify `dashboard=\"\"` as option.
|
64
|
-
#{param_filter_columns}
|
65
|
-
#{param_format}
|
71
|
+
#{param_filter_columns} #{exec_order}
|
72
|
+
#{param_format} #{exec_order}
|
66
73
|
#{param_from}
|
67
74
|
#{param_instance}
|
68
75
|
| `panel=\"<panel_id>\"` | If specified, the resulting alerts are filtered for this panel. This option will only work, if a `dashboard` or `grafana_default_dashboard` is set.
|
69
|
-
#{param_replace_values}
|
76
|
+
#{param_replace_values} #{exec_order}
|
77
|
+
#{param_row_divider}
|
78
|
+
#{param_timeout}
|
70
79
|
#{param_to}
|
80
|
+
#{param_transpose} #{exec_order}
|
71
81
|
|===
|
72
82
|
Additionally all query parameters from the https://grafana.com/docs/grafana/latest/http_api/alerting/#get-alerts[Grafana Alerting API], such as `query`, `state`, `limit`, `folderId` and others are supported.
|
73
83
|
|
@@ -80,14 +90,18 @@ Additionally all query parameters from the https://grafana.com/docs/grafana/late
|
|
80
90
|
[%autowidth.stretch, options=\"header\"]
|
81
91
|
|===
|
82
92
|
| Option | Description
|
93
|
+
#{param_column_divider}
|
83
94
|
#{param_dashboard} If this option, or the global option `grafana_default_dashboard` is set, the resulting annotations will be limited to this dashboard. To show all annotations in this case, specify `dashboard=\"\"` as option.
|
84
|
-
#{param_filter_columns}
|
85
|
-
#{param_format}
|
95
|
+
#{param_filter_columns} #{exec_order}
|
96
|
+
#{param_format} #{exec_order}
|
86
97
|
#{param_from}
|
87
98
|
#{param_instance}
|
88
99
|
| `panel=\"<panel_id>\"` | If specified, the resulting annotations are filtered for this panel. This option will only work, if a `dashboard` or `grafana_default_dashboard` is set.
|
89
|
-
#{param_replace_values}
|
100
|
+
#{param_replace_values} #{exec_order}
|
101
|
+
#{param_row_divider}
|
102
|
+
#{param_timeout}
|
90
103
|
#{param_to}
|
104
|
+
#{param_transpose} #{exec_order}
|
91
105
|
|===
|
92
106
|
Additionally all quer parameters from the https://grafana.com/docs/grafana/latest/http_api/annotations/#find_annotations[Grafana Alerting API], such as `limit`, `alertId`, `panelId` and others are supported.
|
93
107
|
|
@@ -117,6 +131,7 @@ Additionally all quer parameters from the https://grafana.com/docs/grafana/lates
|
|
117
131
|
#{param_dashboard}
|
118
132
|
#{param_from}
|
119
133
|
#{param_instance}
|
134
|
+
#{param_timeout}
|
120
135
|
#{param_to}
|
121
136
|
| `render-height=\"<height>\"` | can be used to override default `height` in which the panel shall be rendered
|
122
137
|
| `render-width=\"<width>\"` | can be used to override default `width` in which the panel shall be rendered
|
@@ -133,13 +148,17 @@ Additionally all quer parameters from the https://grafana.com/docs/grafana/lates
|
|
133
148
|
[%autowidth.stretch, options=\"header\"]
|
134
149
|
|===
|
135
150
|
| Option | Description
|
151
|
+
#{param_column_divider}
|
136
152
|
#{param_dashboard}
|
137
|
-
#{param_filter_columns}
|
138
|
-
#{param_format}
|
153
|
+
#{param_filter_columns} #{exec_order}
|
154
|
+
#{param_format} #{exec_order}
|
139
155
|
#{param_from}
|
140
156
|
#{param_instance}
|
141
|
-
#{param_replace_values}
|
157
|
+
#{param_replace_values} #{exec_order}
|
158
|
+
#{param_row_divider}
|
159
|
+
#{param_timeout}
|
142
160
|
#{param_to}
|
161
|
+
#{param_transpose} #{exec_order}
|
143
162
|
|===
|
144
163
|
|
145
164
|
=== `grafana_panel_query_value`
|
@@ -152,11 +171,13 @@ Additionally all quer parameters from the https://grafana.com/docs/grafana/lates
|
|
152
171
|
|===
|
153
172
|
| Option | Description
|
154
173
|
#{param_dashboard}
|
155
|
-
#{param_filter_columns}
|
156
|
-
#{param_format}
|
174
|
+
#{param_filter_columns} #{exec_order}
|
175
|
+
#{param_format} #{exec_order}
|
157
176
|
#{param_from}
|
158
177
|
#{param_instance}
|
159
|
-
#{param_replace_values}
|
178
|
+
#{param_replace_values} #{exec_order}
|
179
|
+
#{param_row_divider}
|
180
|
+
#{param_timeout}
|
160
181
|
#{param_to}
|
161
182
|
|===
|
162
183
|
|
@@ -169,12 +190,16 @@ Additionally all quer parameters from the https://grafana.com/docs/grafana/lates
|
|
169
190
|
[%autowidth.stretch, options=\"header\"]
|
170
191
|
|===
|
171
192
|
| Option | Description
|
172
|
-
#{
|
173
|
-
#{
|
193
|
+
#{param_column_divider}
|
194
|
+
#{param_filter_columns} #{exec_order}
|
195
|
+
#{param_format} #{exec_order}
|
174
196
|
#{param_from}
|
175
197
|
#{param_instance}
|
176
|
-
#{param_replace_values}
|
198
|
+
#{param_replace_values} #{exec_order}
|
199
|
+
#{param_row_divider}
|
200
|
+
#{param_timeout}
|
177
201
|
#{param_to}
|
202
|
+
#{param_transpose} #{exec_order}
|
178
203
|
|===
|
179
204
|
|
180
205
|
=== `grafana_sql_value`
|
@@ -186,11 +211,12 @@ Additionally all quer parameters from the https://grafana.com/docs/grafana/lates
|
|
186
211
|
[%autowidth.stretch, options=\"header\"]
|
187
212
|
|===
|
188
213
|
| Option | Description
|
189
|
-
#{param_filter_columns}
|
190
|
-
#{param_format}
|
214
|
+
#{param_filter_columns} #{exec_order}
|
215
|
+
#{param_format} #{exec_order}
|
191
216
|
#{param_from}
|
192
217
|
#{param_instance}
|
193
|
-
#{param_replace_values}
|
218
|
+
#{param_replace_values} #{exec_order}
|
219
|
+
#{param_timeout}
|
194
220
|
#{param_to}
|
195
221
|
|==="
|
196
222
|
|
@@ -5,8 +5,33 @@ require_relative 'processor_mixin'
|
|
5
5
|
module GrafanaReporter
|
6
6
|
module Asciidoctor
|
7
7
|
module Extensions
|
8
|
-
#
|
9
|
-
|
8
|
+
# Implements the hook
|
9
|
+
# include::grafana_value_as_variable[<options>]
|
10
|
+
#
|
11
|
+
# Returns an attribute definition in asciidoctor format. This is needed if you want to refer to values of
|
12
|
+
# a grafana query within a variable in asciidoctor. As this works without this function for the
|
13
|
+
# `IncludeProcessor`s values, it will not work for all the other processors.
|
14
|
+
#
|
15
|
+
# This method is just a proxy for all other hooks and will forward parameters accordingly.
|
16
|
+
#
|
17
|
+
# Example:
|
18
|
+
#
|
19
|
+
# include:grafana_value_as_variable[call="grafana_sql_value:1",variable_name="my_variable",sql="SELECT 'looks good'",<any_other_option>]
|
20
|
+
#
|
21
|
+
# This will call the {SqlValueInlineMacro} with `datasource_id` set to `1` and store the result in the
|
22
|
+
# variable. The resulting asciidoctor variable definition will be created as:
|
23
|
+
#
|
24
|
+
# :my_variable: looks good
|
25
|
+
#
|
26
|
+
# and can be refered to in your document easily as
|
27
|
+
#
|
28
|
+
# {my_variable}
|
29
|
+
#
|
30
|
+
# == Supported options
|
31
|
+
# +call+ - regular call to the reporter hook (*mandatory*)
|
32
|
+
#
|
33
|
+
# +variable_name+ - name of the variable, to which the result shall be assigned (*mandatory*)
|
34
|
+
class ValueAsVariableIncludeProcessor < ::Asciidoctor::Extensions::IncludeProcessor
|
10
35
|
include ProcessorMixin
|
11
36
|
|
12
37
|
# :nodoc:
|
@@ -12,7 +12,7 @@ module GrafanaReporter
|
|
12
12
|
@from = translate_date(@from, @variables['grafana-report-timestamp'], false)
|
13
13
|
@to = translate_date(@to, @variables['grafana-report-timestamp'], true)
|
14
14
|
# rename "render-" variables
|
15
|
-
@variables.
|
15
|
+
@variables = @variables.each_with_object({}) { |(k,v), h| h[k.gsub(/^render-/, '')] = v }
|
16
16
|
end
|
17
17
|
|
18
18
|
# Returns the body of the http query, which contains the raw image.
|
@@ -8,10 +8,8 @@ module GrafanaReporter
|
|
8
8
|
# @param item_hash [Hash] variables from item configuration level, i.e. specific call, which may override document
|
9
9
|
# @return [void]
|
10
10
|
def merge_hash_variables(document_hash, item_hash)
|
11
|
-
merge_variables(document_hash.select { |k, _v| k =~ /^var-/ || k == 'grafana-report-timestamp' }.
|
12
|
-
|
13
|
-
merge_variables(item_hash.select { |k, _v| k =~ /^var-/ || k =~ /^render-/ || k =~ /filter_columns|format|replace_values_.*|transpose|column_divider|row_divider/ }.transform_values { |item| ::Grafana::Variable.new(item) })
|
14
|
-
# TODO: add documentation for timeout and grafana-default-timeout
|
11
|
+
merge_variables(document_hash.select { |k, _v| k =~ /^var-/ || k == 'grafana-report-timestamp' }.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
|
12
|
+
merge_variables(item_hash.select { |k, _v| k =~ /^var-/ || k =~ /^render-/ || k =~ /filter_columns|format|replace_values_.*|transpose|column_divider|row_divider/ }.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
|
15
13
|
self.timeout = item_hash['timeout'] || document_hash['grafana-default-timeout'] || timeout
|
16
14
|
self.from = item_hash['from'] || document_hash['from'] || from
|
17
15
|
self.to = item_hash['to'] || document_hash['to'] || to
|
@@ -30,7 +28,6 @@ module GrafanaReporter
|
|
30
28
|
# }
|
31
29
|
# @param raw_result [Hash] query result hash from grafana
|
32
30
|
# @return [Hash] sql result formatted as stated above
|
33
|
-
# TODO: support series query results properly
|
34
31
|
def preformat_sql_result(raw_result)
|
35
32
|
results = {}
|
36
33
|
results.default = []
|
@@ -39,26 +36,13 @@ module GrafanaReporter
|
|
39
36
|
if query_result.key?('error')
|
40
37
|
results[:header] = results[:header] << ['SQL Error']
|
41
38
|
results[:content] = [[query_result['error']]]
|
39
|
+
|
42
40
|
elsif query_result['tables']
|
43
41
|
query_result['tables'].each do |table|
|
44
42
|
results[:header] = results[:header] << table['columns'].map { |header| header['text'] }
|
45
43
|
results[:content] = table['rows']
|
46
44
|
end
|
47
|
-
|
48
|
-
# TODO: add test for series results
|
49
|
-
results[:header] = 'time'
|
50
|
-
query_result['series'].each do |table|
|
51
|
-
results[:header] << table[:name]
|
52
|
-
results[:content] = []
|
53
|
-
content_position = results[:header].length - 1
|
54
|
-
table[:points].each do |point|
|
55
|
-
result = []
|
56
|
-
result << point[1]
|
57
|
-
(content_position - 1).times { result << nil }
|
58
|
-
result << point[0]
|
59
|
-
results[:content][0] << result
|
60
|
-
end
|
61
|
-
end
|
45
|
+
|
62
46
|
end
|
63
47
|
end
|
64
48
|
|
@@ -18,11 +18,6 @@ module GrafanaReporter
|
|
18
18
|
results = format_columns(results, @variables['format'])
|
19
19
|
results = replace_values(results, @variables.select { |k, _v| k =~ /^replace_values_\d+/ })
|
20
20
|
results = filter_columns(results, @variables['filter_columns'])
|
21
|
-
if @variables['filter_column']
|
22
|
-
@report.logger.warn("DEPRECATED: Call of no longer supported function 'filter_column' has been found."\
|
23
|
-
" Rename to 'filter_columns'")
|
24
|
-
results = filter_columns(results, @variables['filter_column'])
|
25
|
-
end
|
26
21
|
|
27
22
|
unless results[:content].empty?
|
28
23
|
unless results[:content][0].empty?
|
@@ -17,11 +17,6 @@ module GrafanaReporter
|
|
17
17
|
results = format_columns(results, @variables['format'])
|
18
18
|
results = replace_values(results, @variables.select { |k, _v| k =~ /^replace_values_\d+/ })
|
19
19
|
results = filter_columns(results, @variables['filter_columns'])
|
20
|
-
if @variables['filter_column']
|
21
|
-
@report.logger.warn("DEPRECATED: Call of no longer supported function 'filter_column' has been found."\
|
22
|
-
" Rename to 'filter_columns'")
|
23
|
-
results = filter_columns(results, @variables['filter_column'])
|
24
|
-
end
|
25
20
|
results = transpose(results, @variables['transpose'])
|
26
21
|
row_divider = '| '
|
27
22
|
row_divider = @variables['row_divider'].raw_value if @variables['row_divider'].is_a?(Grafana::Variable)
|
@@ -23,19 +23,21 @@ module GrafanaReporter
|
|
23
23
|
|
24
24
|
# Used to access the configuration hash. To make sure, that the configuration is
|
25
25
|
# valid, call {#validate}.
|
26
|
-
|
27
|
-
# NOTE: This function overwrites all existing configurations
|
28
|
-
attr_accessor :config
|
26
|
+
attr_reader :config
|
29
27
|
|
30
28
|
def initialize
|
31
29
|
@config = {}
|
32
30
|
@logger = ::Logger.new($stderr, level: :unknown)
|
33
|
-
# TODO: set report class somewhere else, but make it known here
|
34
|
-
self.report_class = Asciidoctor::Report
|
35
31
|
end
|
36
32
|
|
37
33
|
attr_accessor :logger
|
38
34
|
|
35
|
+
# Used to overwrite the current configuration.
|
36
|
+
def config=(new_config)
|
37
|
+
@config = new_config
|
38
|
+
update_configuration
|
39
|
+
end
|
40
|
+
|
39
41
|
# @return [String] mode, in which the reporting shall be executed. One of {MODE_CONNECTION_TEST},
|
40
42
|
# {MODE_SINGLE_RENDER} and {MODE_SERVICE}.
|
41
43
|
def mode
|
@@ -50,6 +52,7 @@ module GrafanaReporter
|
|
50
52
|
# @return [String] full path of configured report template. Only needed in {MODE_SINGLE_RENDER}.
|
51
53
|
def template
|
52
54
|
return nil if get_config('default-document-attributes:var-template').nil?
|
55
|
+
|
53
56
|
"#{templates_folder}#{get_config('default-document-attributes:var-template')}.adoc"
|
54
57
|
end
|
55
58
|
|
@@ -152,6 +155,7 @@ module GrafanaReporter
|
|
152
155
|
# and all necessary folders exist. Appropriate errors are raised in case of errors.
|
153
156
|
# @return [void]
|
154
157
|
def validate
|
158
|
+
check_deprecation
|
155
159
|
validate_schema(schema, @config)
|
156
160
|
|
157
161
|
# check if set folders exist
|
@@ -160,8 +164,60 @@ module GrafanaReporter
|
|
160
164
|
raise FolderDoesNotExistError.new(images_folder, 'images-folder') unless File.directory?(images_folder)
|
161
165
|
end
|
162
166
|
|
167
|
+
# Can be used to configure or overwrite single parameters.
|
168
|
+
#
|
169
|
+
# @param path [String] path of the paramter to set, e.g. +grafana-reporter:webservice-port+
|
170
|
+
# @param value [Object] value to set
|
171
|
+
def set_param(path, value)
|
172
|
+
return if path.nil?
|
173
|
+
|
174
|
+
levels = path.split(':')
|
175
|
+
last_level = levels.pop
|
176
|
+
|
177
|
+
cur_pos = @config
|
178
|
+
levels.each do |subpath|
|
179
|
+
if cur_pos[subpath]
|
180
|
+
cur_pos = cur_pos[subpath]
|
181
|
+
else
|
182
|
+
cur_pos[subpath] = {}
|
183
|
+
cur_pos = cur_pos[subpath]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
cur_pos[last_level] = value
|
188
|
+
update_configuration
|
189
|
+
end
|
190
|
+
|
191
|
+
# Merge the given configuration object settings with the current config, i.e. overwrite and add all
|
192
|
+
# settings from the given config, but keep the not specified configs from the current object.
|
193
|
+
#
|
194
|
+
# param other_config [Configuration] other configuration object
|
195
|
+
def merge!(other_config)
|
196
|
+
self.config.merge!(other_config.config) { |_key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2) : v2 }
|
197
|
+
update_configuration
|
198
|
+
end
|
199
|
+
|
163
200
|
private
|
164
201
|
|
202
|
+
def check_deprecation
|
203
|
+
return if report_class
|
204
|
+
|
205
|
+
logger.warn('DEPRECATION WARNING: Your configuration explicitly needs to specify the \'grafana-reporter:report-class\' value. '\
|
206
|
+
'Currently this defaults to \'GrafanaReporter::Asciidoctor::Report\'. You can get rid of this warning, if you explicitly '\
|
207
|
+
'set this configuration in your configuration file. Setting this default will be removed in a future version.')
|
208
|
+
set_param('grafana-reporter:report-class', 'GrafanaReporter::Asciidoctor::Report')
|
209
|
+
end
|
210
|
+
|
211
|
+
def update_configuration
|
212
|
+
if get_config('grafana-reporter:debug-level') =~ /DEBUG|INFO|WARN|ERROR|FATAL|UNKNOWN/
|
213
|
+
@logger.level = Object.const_get("::Logger::Severity::#{get_config('grafana-reporter:debug-level')}")
|
214
|
+
end
|
215
|
+
|
216
|
+
if get_config('grafana-reporter:report-class')
|
217
|
+
self.report_class = Object.const_get(get_config('grafana-reporter:report-class'))
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
165
221
|
def get_config(path)
|
166
222
|
return if path.nil?
|
167
223
|
|
@@ -241,11 +297,13 @@ module GrafanaReporter
|
|
241
297
|
'default-document-attributes' => [Hash, 0],
|
242
298
|
'grafana-reporter' =>
|
243
299
|
[
|
244
|
-
Hash,
|
300
|
+
Hash, 1,
|
245
301
|
{
|
302
|
+
'debug-level' => [String, 0],
|
246
303
|
'run-mode' => [String, 0],
|
247
304
|
'test-instance' => [String, 0],
|
248
305
|
'templates-folder' => [String, 0],
|
306
|
+
'report-class' => [String, 1],
|
249
307
|
'reports-folder' => [String, 0],
|
250
308
|
'report-retention' => [Integer, 0],
|
251
309
|
'webservice-port' => [Integer, 0]
|
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.2.
|
4
|
+
version: 0.2.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: 2020-
|
11
|
+
date: 2020-12-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: asciidoctor
|
@@ -47,7 +47,7 @@ dependencies:
|
|
47
47
|
version: 1.1.1
|
48
48
|
- - "<"
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: '2.
|
50
|
+
version: '2.4'
|
51
51
|
type: :runtime
|
52
52
|
prerelease: false
|
53
53
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -57,7 +57,7 @@ dependencies:
|
|
57
57
|
version: 1.1.1
|
58
58
|
- - "<"
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: '2.
|
60
|
+
version: '2.4'
|
61
61
|
- !ruby/object:Gem::Dependency
|
62
62
|
name: rspec
|
63
63
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,13 +100,10 @@ dependencies:
|
|
100
100
|
- - "~>"
|
101
101
|
- !ruby/object:Gem::Version
|
102
102
|
version: '3.9'
|
103
|
-
description:
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
By default the reports will be converted to PDF documents, whereas other
|
109
|
-
target formats can be used as well.
|
103
|
+
description: Provides a standalone and a webservice frontend for creating reportsbased
|
104
|
+
on asciidoctor, including interfaces to integrate dynamic contentcaptured from grafana.By
|
105
|
+
default the reports will be converted to PDF documents, whereas othertarget formats
|
106
|
+
can be used as well.
|
110
107
|
email: kohly@gmx.de
|
111
108
|
executables:
|
112
109
|
- ruby-grafana-reporter
|
@@ -174,7 +171,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
174
171
|
requirements:
|
175
172
|
- - ">="
|
176
173
|
- !ruby/object:Gem::Version
|
177
|
-
version:
|
174
|
+
version: 2.3.3
|
178
175
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
176
|
requirements:
|
180
177
|
- - ">="
|