ruby-grafana-reporter 0.2.2 → 0.4.3
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 +126 -88
- data/bin/ruby-grafana-reporter +2 -2
- data/lib/VERSION.rb +3 -2
- data/lib/grafana/abstract_datasource.rb +146 -0
- data/lib/grafana/dashboard.rb +1 -3
- data/lib/grafana/errors.rb +18 -3
- data/lib/grafana/grafana.rb +64 -66
- data/lib/grafana/grafana_alerts_datasource.rb +57 -0
- data/lib/grafana/grafana_annotations_datasource.rb +56 -0
- data/lib/grafana/grafana_property_datasource.rb +30 -0
- data/lib/grafana/graphite_datasource.rb +72 -0
- data/lib/grafana/image_rendering_datasource.rb +44 -0
- data/lib/grafana/influxdb_datasource.rb +70 -0
- data/lib/grafana/panel.rb +9 -3
- data/lib/grafana/prometheus_datasource.rb +67 -0
- data/lib/grafana/sql_datasource.rb +78 -0
- data/lib/grafana/unsupported_datasource.rb +7 -0
- data/lib/grafana/variable.rb +1 -1
- data/lib/grafana/webrequest.rb +71 -0
- data/lib/grafana_reporter/abstract_query.rb +460 -0
- data/lib/grafana_reporter/abstract_report.rb +139 -18
- data/lib/grafana_reporter/alerts_table_query.rb +39 -0
- data/lib/grafana_reporter/annotations_table_query.rb +38 -0
- data/lib/grafana_reporter/application/application.rb +34 -286
- data/lib/grafana_reporter/application/webservice.rb +50 -15
- data/lib/grafana_reporter/asciidoctor/alerts_table_include_processor.rb +91 -0
- data/lib/grafana_reporter/asciidoctor/annotations_table_include_processor.rb +90 -0
- data/lib/grafana_reporter/asciidoctor/panel_image_block_macro.rb +74 -0
- data/lib/grafana_reporter/asciidoctor/panel_image_inline_macro.rb +76 -0
- data/lib/grafana_reporter/asciidoctor/panel_property_inline_macro.rb +70 -0
- data/lib/grafana_reporter/asciidoctor/panel_query_table_include_processor.rb +95 -0
- data/lib/grafana_reporter/asciidoctor/panel_query_value_inline_macro.rb +90 -0
- data/lib/grafana_reporter/asciidoctor/processor_mixin.rb +49 -0
- data/lib/grafana_reporter/asciidoctor/report.rb +32 -76
- data/lib/grafana_reporter/asciidoctor/show_environment_include_processor.rb +46 -0
- data/lib/grafana_reporter/asciidoctor/show_help_include_processor.rb +35 -0
- data/lib/grafana_reporter/asciidoctor/sql_table_include_processor.rb +90 -0
- data/lib/grafana_reporter/asciidoctor/sql_value_inline_macro.rb +86 -0
- data/lib/grafana_reporter/asciidoctor/value_as_variable_include_processor.rb +90 -0
- data/lib/grafana_reporter/configuration.rb +59 -52
- data/lib/grafana_reporter/console_configuration_wizard.rb +311 -0
- data/lib/grafana_reporter/demo_report_wizard.rb +105 -0
- data/lib/grafana_reporter/erb/report.rb +30 -0
- data/lib/grafana_reporter/erb/report_jail.rb +21 -0
- data/lib/grafana_reporter/errors.rb +55 -0
- data/lib/grafana_reporter/help.rb +443 -0
- data/lib/grafana_reporter/logger/{two_way_logger.rb → two_way_delegate_logger.rb} +1 -1
- data/lib/grafana_reporter/panel_image_query.rb +25 -0
- data/lib/grafana_reporter/panel_property_query.rb +22 -0
- data/lib/grafana_reporter/query_value_query.rb +61 -0
- data/lib/grafana_reporter/report_webhook.rb +35 -0
- data/lib/ruby_grafana_extension.rb +8 -0
- data/lib/{ruby-grafana-reporter.rb → ruby_grafana_reporter.rb} +1 -0
- metadata +47 -39
- data/lib/grafana/abstract_panel_query.rb +0 -22
- data/lib/grafana/abstract_query.rb +0 -132
- data/lib/grafana/abstract_sql_query.rb +0 -51
- data/lib/grafana/panel_image_query.rb +0 -52
- data/lib/grafana_reporter/asciidoctor/alerts_table_query.rb +0 -104
- data/lib/grafana_reporter/asciidoctor/annotations_table_query.rb +0 -99
- data/lib/grafana_reporter/asciidoctor/errors.rb +0 -40
- data/lib/grafana_reporter/asciidoctor/extensions/alerts_table_include_processor.rb +0 -92
- data/lib/grafana_reporter/asciidoctor/extensions/annotations_table_include_processor.rb +0 -91
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_block_macro.rb +0 -69
- data/lib/grafana_reporter/asciidoctor/extensions/panel_image_inline_macro.rb +0 -68
- data/lib/grafana_reporter/asciidoctor/extensions/panel_property_inline_macro.rb +0 -61
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_table_include_processor.rb +0 -78
- data/lib/grafana_reporter/asciidoctor/extensions/panel_query_value_inline_macro.rb +0 -73
- data/lib/grafana_reporter/asciidoctor/extensions/processor_mixin.rb +0 -20
- data/lib/grafana_reporter/asciidoctor/extensions/show_environment_include_processor.rb +0 -43
- data/lib/grafana_reporter/asciidoctor/extensions/show_help_include_processor.rb +0 -30
- data/lib/grafana_reporter/asciidoctor/extensions/sql_table_include_processor.rb +0 -70
- data/lib/grafana_reporter/asciidoctor/extensions/sql_value_inline_macro.rb +0 -66
- data/lib/grafana_reporter/asciidoctor/extensions/value_as_variable_include_processor.rb +0 -86
- data/lib/grafana_reporter/asciidoctor/help.rb +0 -435
- data/lib/grafana_reporter/asciidoctor/panel_first_value_query.rb +0 -34
- data/lib/grafana_reporter/asciidoctor/panel_image_query.rb +0 -26
- data/lib/grafana_reporter/asciidoctor/panel_property_query.rb +0 -44
- data/lib/grafana_reporter/asciidoctor/panel_table_query.rb +0 -38
- data/lib/grafana_reporter/asciidoctor/query_mixin.rb +0 -301
- data/lib/grafana_reporter/asciidoctor/sql_first_value_query.rb +0 -42
- data/lib/grafana_reporter/asciidoctor/sql_table_query.rb +0 -44
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'sql_first_value_query'
|
4
|
-
|
5
|
-
module GrafanaReporter
|
6
|
-
module Asciidoctor
|
7
|
-
# (see SqlFirstValueQuery)
|
8
|
-
#
|
9
|
-
# The SQL query as well as the datasource configuration are thereby captured from a
|
10
|
-
# {Grafana::Panel}.
|
11
|
-
class PanelFirstValueQuery < SqlFirstValueQuery
|
12
|
-
include QueryMixin
|
13
|
-
|
14
|
-
# (see PanelTableQuery#initialize)
|
15
|
-
def initialize(panel, query_letter)
|
16
|
-
super(nil, nil)
|
17
|
-
@panel = panel
|
18
|
-
@query_letter = query_letter
|
19
|
-
extract_dashboard_variables(@panel.dashboard)
|
20
|
-
end
|
21
|
-
|
22
|
-
# (see PanelTableQuery#pre_process)
|
23
|
-
def pre_process(grafana)
|
24
|
-
@sql = @panel.query(@query_letter)
|
25
|
-
# resolve datasource name
|
26
|
-
@datasource = @panel.field('datasource')
|
27
|
-
@datasource_id = grafana.datasource_id(@datasource)
|
28
|
-
super(grafana)
|
29
|
-
@from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] || @variables['grafana_default_from_timezone'])
|
30
|
-
@to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] || @variables['grafana_default_to_timezone'])
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GrafanaReporter
|
4
|
-
module Asciidoctor
|
5
|
-
# This class is used to create an image out of a {Grafana::Panel}.
|
6
|
-
class PanelImageQuery < Grafana::PanelImageQuery
|
7
|
-
include QueryMixin
|
8
|
-
|
9
|
-
# Sets the proper render variables.
|
10
|
-
def pre_process(grafana)
|
11
|
-
super
|
12
|
-
@from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] || @variables['grafana_default_from_timezone'])
|
13
|
-
@to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] || @variables['grafana_default_to_timezone'])
|
14
|
-
# TODO: ensure that in case of timezones are specified, that they are also forwarded to the image renderer as URL parameter
|
15
|
-
# rename "render-" variables
|
16
|
-
@variables = @variables.each_with_object({}) { |(k,v), h| h[k.gsub(/^render-/, '')] = v }
|
17
|
-
end
|
18
|
-
|
19
|
-
# Returns the body of the http query, which contains the raw image.
|
20
|
-
def post_process
|
21
|
-
super
|
22
|
-
@result = @result.body
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module GrafanaReporter
|
4
|
-
module Asciidoctor
|
5
|
-
# This class is used to query properties from a {Grafana::Panel}, such as +description+,
|
6
|
-
# +title+ etc.
|
7
|
-
class PanelPropertyQuery < ::Grafana::AbstractPanelQuery
|
8
|
-
include QueryMixin
|
9
|
-
|
10
|
-
# @param panel [Grafana::Panel] panel object, for which the property shall be retrieved
|
11
|
-
# @param property [String] queried property, e.g. +title+
|
12
|
-
def initialize(panel, property)
|
13
|
-
super(panel)
|
14
|
-
@property = property
|
15
|
-
end
|
16
|
-
|
17
|
-
# Overrides the default method, as the query does not have to run against a SQL table,
|
18
|
-
# but rather against the panel model.
|
19
|
-
# @param grafana [Grafana::Grafana] grafana instance against which the panel property is queried
|
20
|
-
# @return [String] fetched property
|
21
|
-
def execute(grafana)
|
22
|
-
return @result unless @result.nil?
|
23
|
-
|
24
|
-
pre_process(grafana)
|
25
|
-
@result = panel.field(@property)
|
26
|
-
post_process
|
27
|
-
@result
|
28
|
-
|
29
|
-
# TODO: handle text (markdown and similar) properly
|
30
|
-
end
|
31
|
-
|
32
|
-
# Prepare query. Mainly here nothing special has to take place.
|
33
|
-
def pre_process(_grafana)
|
34
|
-
@from = nil
|
35
|
-
@to = nil
|
36
|
-
end
|
37
|
-
|
38
|
-
# Replaces variables in the property field, if any are available.
|
39
|
-
def post_process
|
40
|
-
@result = replace_variables(@result, grafana_variables)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'sql_table_query'
|
4
|
-
|
5
|
-
module GrafanaReporter
|
6
|
-
module Asciidoctor
|
7
|
-
# (see SqlTableQuery)
|
8
|
-
#
|
9
|
-
# The SQL query as well as the datasource configuration are thereby captured from a
|
10
|
-
# {Grafana::Panel}.
|
11
|
-
class PanelTableQuery < SqlTableQuery
|
12
|
-
include QueryMixin
|
13
|
-
|
14
|
-
# @param panel [Grafana::Panel] panel which contains the query
|
15
|
-
# @param query_letter [String] letter of the query within the panel, which shall be used, e.g. +C+
|
16
|
-
def initialize(panel, query_letter)
|
17
|
-
super(nil, nil)
|
18
|
-
@panel = panel
|
19
|
-
@query_letter = query_letter
|
20
|
-
extract_dashboard_variables(@panel.dashboard)
|
21
|
-
end
|
22
|
-
|
23
|
-
# Retrieves the SQL query and the configured datasource from the panel.
|
24
|
-
# @see Grafana::AbstractSqlQuery#pre_process
|
25
|
-
# @param grafana [Grafana::Grafana] grafana instance against which the query shall be executed
|
26
|
-
# @return [void]
|
27
|
-
def pre_process(grafana)
|
28
|
-
@sql = @panel.query(@query_letter)
|
29
|
-
# resolve datasource name
|
30
|
-
@datasource = @panel.field('datasource')
|
31
|
-
@datasource_id = grafana.datasource_id(@datasource)
|
32
|
-
super(grafana)
|
33
|
-
@from = translate_date(@from, @variables['grafana-report-timestamp'], false, @variables['from_timezone'] || @variables['grafana_default_from_timezone'])
|
34
|
-
@to = translate_date(@to, @variables['grafana-report-timestamp'], true, @variables['to_timezone'] || @variables['grafana_default_to_timezone'])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
@@ -1,301 +0,0 @@
|
|
1
|
-
module GrafanaReporter
|
2
|
-
module Asciidoctor
|
3
|
-
# This mixin contains several common methods, which can be used within the queries.
|
4
|
-
module QueryMixin
|
5
|
-
# Merges the given hashes to the current object by using the {Grafana::AbstractQuery#merge_variables} method.
|
6
|
-
# It respects the priorities of the hashes and the object and allows only valid variables to be passed.
|
7
|
-
# @param document_hash [Hash] variables from report template level
|
8
|
-
# @param item_hash [Hash] variables from item configuration level, i.e. specific call, which may override document
|
9
|
-
# @return [void]
|
10
|
-
def merge_hash_variables(document_hash, item_hash)
|
11
|
-
merge_variables(document_hash.select { |k, _v| k =~ /^var-/ || k == 'grafana-report-timestamp' || k =~ /grafana_default_(?:from|to)_timezone/ }.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|from_timezone|to_timezone/ }.each_with_object({}) { |(k,v), h| h[k] = ::Grafana::Variable.new(v) })
|
13
|
-
self.timeout = item_hash['timeout'] || document_hash['grafana-default-timeout'] || timeout
|
14
|
-
self.from = item_hash['from'] || document_hash['from'] || from
|
15
|
-
self.to = item_hash['to'] || document_hash['to'] || to
|
16
|
-
end
|
17
|
-
|
18
|
-
# Formats the SQL results returned from grafana to an easier to use format.
|
19
|
-
#
|
20
|
-
# The result is being formatted as stated below:
|
21
|
-
#
|
22
|
-
# {
|
23
|
-
# :header => [column_title_1, column_title_2],
|
24
|
-
# :content => [
|
25
|
-
# [row_1_column_1, row_1_column_2],
|
26
|
-
# [row_2_column_1, row_2_column_2]
|
27
|
-
# ]
|
28
|
-
# }
|
29
|
-
# @param raw_result [Hash] query result hash from grafana
|
30
|
-
# @return [Hash] sql result formatted as stated above
|
31
|
-
def preformat_sql_result(raw_result)
|
32
|
-
results = {}
|
33
|
-
results.default = []
|
34
|
-
|
35
|
-
JSON.parse(raw_result)['results'].each_value do |query_result|
|
36
|
-
if query_result.key?('error')
|
37
|
-
results[:header] = results[:header] << ['SQL Error']
|
38
|
-
results[:content] = [[query_result['error']]]
|
39
|
-
|
40
|
-
elsif query_result['tables']
|
41
|
-
query_result['tables'].each do |table|
|
42
|
-
results[:header] = results[:header] << table['columns'].map { |header| header['text'] }
|
43
|
-
results[:content] = table['rows']
|
44
|
-
end
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
results
|
50
|
-
end
|
51
|
-
|
52
|
-
# Transposes the given result.
|
53
|
-
#
|
54
|
-
# NOTE: Only the +:content+ of the given result hash is transposed. The +:header+ is ignored.
|
55
|
-
#
|
56
|
-
# @param result [Hash] preformatted sql hash, (see {#preformat_sql_result})
|
57
|
-
# @param transpose_variable [Grafana::Variable] true, if the result hash shall be transposed
|
58
|
-
# @return [Hash] transposed query result
|
59
|
-
def transpose(result, transpose_variable)
|
60
|
-
return result unless transpose_variable
|
61
|
-
return result unless transpose_variable.raw_value == 'true'
|
62
|
-
|
63
|
-
result[:content] = result[:content].transpose
|
64
|
-
|
65
|
-
result
|
66
|
-
end
|
67
|
-
|
68
|
-
# Filters columns out of the query result.
|
69
|
-
#
|
70
|
-
# Multiple columns may be filtered. Therefore the column titles have to be named in the
|
71
|
-
# {Grafana::Variable#raw_value} and have to be separated by +,+ (comma).
|
72
|
-
# @param result [Hash] preformatted sql hash, (see {#preformat_sql_result})
|
73
|
-
# @param filter_columns_variable [Grafana::Variable] column names, which shall be removed in the query result
|
74
|
-
# @return [Hash] filtered query result
|
75
|
-
def filter_columns(result, filter_columns_variable)
|
76
|
-
return result unless filter_columns_variable
|
77
|
-
|
78
|
-
filter_columns = filter_columns_variable.raw_value
|
79
|
-
filter_columns.split(',').each do |filter_column|
|
80
|
-
pos = result[:header][0].index(filter_column)
|
81
|
-
|
82
|
-
unless pos.nil?
|
83
|
-
result[:header][0].delete_at(pos)
|
84
|
-
result[:content].each { |row| row.delete_at(pos) }
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
result
|
89
|
-
end
|
90
|
-
|
91
|
-
# Uses the {Kernel#format} method to format values in the query results.
|
92
|
-
#
|
93
|
-
# The formatting will be applied separately for every column. Therefore the column formats have to be named
|
94
|
-
# in the {Grafana::Variable#raw_value} and have to be separated by +,+ (comma). If no value is specified for
|
95
|
-
# a column, no change will happen.
|
96
|
-
# @param result [Hash] preformatted sql hash, (see {#preformat_sql_result})
|
97
|
-
# @param formats [Grafana::Variable] formats, which shall be applied to the columns in the query result
|
98
|
-
# @return [Hash] formatted query result
|
99
|
-
# TODO: make sure that caught errors are also visible in logger
|
100
|
-
def format_columns(result, formats)
|
101
|
-
return result unless formats
|
102
|
-
|
103
|
-
formats.text.split(',').each_index do |i|
|
104
|
-
format = formats.text.split(',')[i]
|
105
|
-
next if format.empty?
|
106
|
-
|
107
|
-
result[:content].map do |row|
|
108
|
-
next unless row.length > i
|
109
|
-
|
110
|
-
begin
|
111
|
-
row[i] = format % row[i] if row[i]
|
112
|
-
rescue StandardError => e
|
113
|
-
row[i] = e.message
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
result
|
118
|
-
end
|
119
|
-
|
120
|
-
# Used to replace values in a query result according given configurations.
|
121
|
-
#
|
122
|
-
# The given variables will be applied to an appropriate column, depending
|
123
|
-
# on the naming of the variable. The variable name ending specifies the column,
|
124
|
-
# e.g. a variable named +replace_values_2+ will be applied to the second column.
|
125
|
-
#
|
126
|
-
# The {Grafana::Variable#text} needs to contain the replace specification.
|
127
|
-
# Multiple replacements can be specified by separating them with +,+. If a
|
128
|
-
# literal comma is needed, it can be escaped with a backslash: +\\,+.
|
129
|
-
#
|
130
|
-
# The rule will be separated from the replacement text with a colon +:+.
|
131
|
-
# If a literal colon is wanted, it can be escaped with a backslash: +\\:+.
|
132
|
-
#
|
133
|
-
# Examples:
|
134
|
-
# - Basic string replacement
|
135
|
-
# MyTest:ThisValue
|
136
|
-
# will replace all occurences of the text 'MyTest' with 'ThisValue'.
|
137
|
-
# - Number comparison
|
138
|
-
# <=10:OK
|
139
|
-
# will replace all values smaller or equal to 10 with 'OK'.
|
140
|
-
# - Regular expression
|
141
|
-
# ^[^ ]\\+ (\d+)$:\1 is the answer
|
142
|
-
# will replace all values matching the pattern, e.g. 'answerToAllQuestions 42' to
|
143
|
-
# '42 is the answer'. Important to know: the regular expressions always have to start
|
144
|
-
# with +^+ and end with +$+, i.e. the expression itself always has to match
|
145
|
-
# the whole content in one field.
|
146
|
-
# @param result [Hash] preformatted query result (see {#preformat_sql_result}.
|
147
|
-
# @param configs [Array<Grafana::Variable>] one variable for replacing values in one column
|
148
|
-
# @return [Hash] query result with replaced values
|
149
|
-
# TODO: make sure that caught errors are also visible in logger
|
150
|
-
def replace_values(result, configs)
|
151
|
-
return result if configs.empty?
|
152
|
-
|
153
|
-
configs.each do |key, formats|
|
154
|
-
cols = key.split('_')[2..-1].map(&:to_i)
|
155
|
-
|
156
|
-
formats.text.split(/(?<!\\),/).each_index do |j|
|
157
|
-
format = formats.text.split(/(?<!\\),/)[j]
|
158
|
-
|
159
|
-
arr = format.split(/(?<!\\):/)
|
160
|
-
raise MalformedReplaceValuesStatementError, format if arr.length != 2
|
161
|
-
|
162
|
-
k = arr[0]
|
163
|
-
v = arr[1]
|
164
|
-
k.gsub!(/\\([:,])/, '\1')
|
165
|
-
v.gsub!(/\\([:,])/, '\1')
|
166
|
-
result[:content].map do |row|
|
167
|
-
(row.length - 1).downto 0 do |i|
|
168
|
-
if cols.include?(i + 1) || cols.empty?
|
169
|
-
|
170
|
-
# handle regular expressions
|
171
|
-
if k.start_with?('^') && k.end_with?('$')
|
172
|
-
begin
|
173
|
-
row[i] = row[i].to_s.gsub(/#{k}/, v) if row[i].to_s =~ /#{k}/
|
174
|
-
rescue StandardError => e
|
175
|
-
row[i] = e.message
|
176
|
-
end
|
177
|
-
|
178
|
-
# handle value comparisons
|
179
|
-
elsif (match = k.match(/^ *(?<operator>[<>]=?|<>|=) *(?<number>[+-]?\d+(?:\.\d+)?)$/))
|
180
|
-
skip = false
|
181
|
-
begin
|
182
|
-
val = Float(row[i])
|
183
|
-
rescue StandardError
|
184
|
-
# value cannot be converted to number, simply ignore it as the comparison does not fit here
|
185
|
-
skip = true
|
186
|
-
end
|
187
|
-
|
188
|
-
unless skip
|
189
|
-
begin
|
190
|
-
op = match[:operator].gsub(/^=$/, '==').gsub(/^<>$/, '!=')
|
191
|
-
if val.public_send(op.to_sym, Float(match[:number]))
|
192
|
-
row[i] = if v.include?('\\1')
|
193
|
-
v.gsub(/\\1/, row[i].to_s)
|
194
|
-
else
|
195
|
-
v
|
196
|
-
end
|
197
|
-
end
|
198
|
-
rescue StandardError => e
|
199
|
-
row[i] = e.message
|
200
|
-
end
|
201
|
-
end
|
202
|
-
|
203
|
-
# handle as normal comparison
|
204
|
-
elsif row[i].to_s == k
|
205
|
-
row[i] = v
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
end
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
result
|
214
|
-
end
|
215
|
-
|
216
|
-
# Used to translate the relative date strings used by grafana, e.g. +now-5d/w+ to the
|
217
|
-
# correct timestamp. Reason is that grafana does this in the frontend, which we have
|
218
|
-
# to emulate here for the reporter.
|
219
|
-
#
|
220
|
-
# Additionally providing this function the +report_time+ assures that all queries
|
221
|
-
# rendered within one report will use _exactly_ the same timestamp in those relative
|
222
|
-
# times, i.e. there shouldn't appear any time differences, no matter how long the
|
223
|
-
# report is running.
|
224
|
-
# @param orig_date [String] time string provided by grafana, usually +from+ or +to+.
|
225
|
-
# @param report_time [Grafana::Variable] report start time
|
226
|
-
# @param is_to_time [Boolean] true, if the time should be calculated for +to+, false if it shall be
|
227
|
-
# calculated for +from+
|
228
|
-
# @param timezone [Grafana::Variable] timezone to use, if not system timezone
|
229
|
-
# @return [String] translated date as timestamp string
|
230
|
-
def translate_date(orig_date, report_time, is_to_time, timezone=nil)
|
231
|
-
report_time ||= Variable.new(Time.now.to_s)
|
232
|
-
return (DateTime.parse(report_time.raw_value).to_time.to_i * 1000).to_s unless orig_date
|
233
|
-
return orig_date if orig_date =~ /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
|
234
|
-
return orig_date if orig_date =~ /^\d+$/
|
235
|
-
|
236
|
-
# replace grafana from and to values using now, now-2d etc.
|
237
|
-
date_splitted = orig_date.match(%r{^(?<now>now)(?:-(?<sub_count>\d+)?(?<sub_unit>[smhdwMy]?))?(?:/(?<fit>[smhdwMy]))?$})
|
238
|
-
raise TimeRangeUnknownError, orig_date unless date_splitted
|
239
|
-
|
240
|
-
date = DateTime.parse(report_time.raw_value)
|
241
|
-
# TODO: allow from_translated or similar in ADOC template
|
242
|
-
date = date.new_offset(timezone.raw_value) if timezone
|
243
|
-
|
244
|
-
# substract specified time
|
245
|
-
count = 1
|
246
|
-
count = date_splitted[:sub_count].to_i if date_splitted[:sub_count]
|
247
|
-
case date_splitted[:sub_unit]
|
248
|
-
when 's'
|
249
|
-
date = (date.to_time - (count * 1)).to_datetime
|
250
|
-
when 'm'
|
251
|
-
date = (date.to_time - (count * 60)).to_datetime
|
252
|
-
when 'h'
|
253
|
-
date = (date.to_time - (count * 60 * 60)).to_datetime
|
254
|
-
when 'd'
|
255
|
-
date = date.prev_day(count)
|
256
|
-
when 'w'
|
257
|
-
date = date.prev_day(count * 7)
|
258
|
-
when 'M'
|
259
|
-
date = date.prev_month(count)
|
260
|
-
when 'y'
|
261
|
-
date = date.prev_year(count)
|
262
|
-
end
|
263
|
-
|
264
|
-
# fit to specified time frame
|
265
|
-
case date_splitted[:fit]
|
266
|
-
when 's'
|
267
|
-
date = DateTime.new(date.year, date.month, date.day, date.hour, date.min, date.sec, date.zone)
|
268
|
-
date = (date.to_time + 1).to_datetime if is_to_time
|
269
|
-
when 'm'
|
270
|
-
date = DateTime.new(date.year, date.month, date.day, date.hour, date.min, 0, date.zone)
|
271
|
-
date = (date.to_time + 60).to_datetime if is_to_time
|
272
|
-
when 'h'
|
273
|
-
date = DateTime.new(date.year, date.month, date.day, date.hour, 0, 0, date.zone)
|
274
|
-
date = (date.to_time + 60 * 60).to_datetime if is_to_time
|
275
|
-
when 'd'
|
276
|
-
date = DateTime.new(date.year, date.month, date.day, 0, 0, 0, date.zone)
|
277
|
-
date = date.next_day(1) if is_to_time
|
278
|
-
when 'w'
|
279
|
-
date = DateTime.new(date.year, date.month, date.day, 0, 0, 0, date.zone)
|
280
|
-
date = if date.wday.zero?
|
281
|
-
date.prev_day(7)
|
282
|
-
else
|
283
|
-
date.prev_day(date.wday - 1)
|
284
|
-
end
|
285
|
-
date = date.next_day(7) if is_to_time
|
286
|
-
when 'M'
|
287
|
-
date = DateTime.new(date.year, date.month, 1, 0, 0, 0, date.zone)
|
288
|
-
date = date.next_month if is_to_time
|
289
|
-
when 'y'
|
290
|
-
date = DateTime.new(date.year, 1, 1, 0, 0, 0, date.zone)
|
291
|
-
date = date.next_year if is_to_time
|
292
|
-
end
|
293
|
-
|
294
|
-
# step back one second, if this is the 'to' time
|
295
|
-
date = (date.to_time - 1).to_datetime if is_to_time
|
296
|
-
|
297
|
-
(Time.at(date.to_time.to_i).to_i * 1000).to_s
|
298
|
-
end
|
299
|
-
end
|
300
|
-
end
|
301
|
-
end
|