qa_server 2.2.0 → 2.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/CHANGELOG.md +5 -0
- data/app/models/qa_server/performance_history.rb +164 -60
- data/app/models/qa_server/term_scenario.rb +1 -1
- data/app/prepends/prepended_linked_data/find_term.rb +2 -1
- data/app/prepends/prepended_linked_data/search_query.rb +1 -0
- data/app/presenters/concerns/qa_server/monitor_status/gruff_graph.rb +21 -0
- data/app/presenters/qa_server/monitor_status/current_status_presenter.rb +76 -0
- data/app/presenters/qa_server/monitor_status/history_presenter.rb +138 -0
- data/app/presenters/qa_server/monitor_status/performance_presenter.rb +253 -0
- data/app/presenters/qa_server/monitor_status_presenter.rb +23 -310
- data/app/views/qa_server/monitor_status/index.html.erb +38 -1
- data/config/locales/qa_server.en.yml +8 -1
- data/lib/generators/qa_server/templates/config/initializers/qa_server.rb +8 -0
- data/lib/qa_server/configuration.rb +20 -0
- data/lib/qa_server/version.rb +1 -1
- metadata +6 -2
@@ -0,0 +1,253 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This presenter class provides performance data needed by the view that monitors status of authorities.
|
3
|
+
module QaServer::MonitorStatus
|
4
|
+
class PerformancePresenter # rubocop:disable Metrics/ClassLength
|
5
|
+
class_attribute :performance_history_class
|
6
|
+
self.performance_history_class = QaServer::PerformanceHistory
|
7
|
+
|
8
|
+
include QaServer::MonitorStatus::GruffGraph
|
9
|
+
|
10
|
+
ALL_AUTHS = performance_history_class::PERFORMANCE_ALL_KEY
|
11
|
+
STATS = performance_history_class::PERFORMANCE_STATS_KEY
|
12
|
+
|
13
|
+
FOR_LIFETIME = performance_history_class::PERFORMANCE_FOR_LIFETIME_KEY
|
14
|
+
FOR_DAY = performance_history_class::PERFORMANCE_FOR_DAY_KEY
|
15
|
+
BY_HOUR = performance_history_class::PERFORMANCE_BY_HOUR_KEY
|
16
|
+
FOR_MONTH = performance_history_class::PERFORMANCE_FOR_MONTH_KEY
|
17
|
+
BY_DAY = performance_history_class::PERFORMANCE_BY_DAY_KEY
|
18
|
+
FOR_YEAR = performance_history_class::PERFORMANCE_FOR_YEAR_KEY
|
19
|
+
BY_MONTH = performance_history_class::PERFORMANCE_BY_MONTH_KEY
|
20
|
+
|
21
|
+
SUM_LOAD = performance_history_class::SUM_LOAD_TIME_KEY
|
22
|
+
SUM_NORMALIZATION = performance_history_class::SUM_NORMALIZATION_TIME_KEY
|
23
|
+
SUM_FULL_REQUEST = performance_history_class::SUM_FULL_REQUEST_TIME_KEY
|
24
|
+
MIN_LOAD = performance_history_class::MIN_LOAD_TIME_KEY
|
25
|
+
MIN_NORMALIZATION = performance_history_class::MIN_NORMALIZATION_TIME_KEY
|
26
|
+
MIN_FULL_REQUEST = performance_history_class::MIN_FULL_REQUEST_TIME_KEY
|
27
|
+
MAX_LOAD = performance_history_class::MAX_LOAD_TIME_KEY
|
28
|
+
MAX_NORMALIZATION = performance_history_class::MAX_NORMALIZATION_TIME_KEY
|
29
|
+
MAX_FULL_REQUEST = performance_history_class::MAX_FULL_REQUEST_TIME_KEY
|
30
|
+
AVG_LOAD = performance_history_class::AVG_LOAD_TIME_KEY
|
31
|
+
AVG_NORMALIZATION = performance_history_class::AVG_NORMALIZATION_TIME_KEY
|
32
|
+
AVG_FULL_REQUEST = performance_history_class::AVG_FULL_REQUEST_TIME_KEY
|
33
|
+
|
34
|
+
# @param performance_data [Hash<Hash>] performance data
|
35
|
+
def initialize(performance_data:)
|
36
|
+
@performance_data = performance_data
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_reader :performance_data
|
40
|
+
|
41
|
+
def performance_data?
|
42
|
+
performance_data.present?
|
43
|
+
end
|
44
|
+
|
45
|
+
def display_performance?
|
46
|
+
display_performance_graph? || display_performance_datatable?
|
47
|
+
end
|
48
|
+
|
49
|
+
def display_performance_graph?
|
50
|
+
QaServer.config.display_performance_graph?
|
51
|
+
end
|
52
|
+
|
53
|
+
def display_performance_datatable?
|
54
|
+
QaServer.config.display_performance_datatable?
|
55
|
+
end
|
56
|
+
|
57
|
+
def performance_data_authority_name(entry)
|
58
|
+
entry.keys.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def performance_for_day_graph
|
62
|
+
performance_graph_file(rework_performance_data_for_gruff(all_authorities_performance_data[FOR_DAY], BY_HOUR),
|
63
|
+
performance_for_day_graph_full_path,
|
64
|
+
performance_for_day_graph_filename,
|
65
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
66
|
+
end
|
67
|
+
|
68
|
+
def performance_for_month_graph
|
69
|
+
performance_graph_file(rework_performance_data_for_gruff(all_authorities_performance_data[FOR_MONTH], BY_DAY),
|
70
|
+
performance_for_month_graph_full_path,
|
71
|
+
performance_for_month_graph_filename,
|
72
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_day'))
|
73
|
+
end
|
74
|
+
|
75
|
+
def performance_for_year_graph
|
76
|
+
performance_graph_file(rework_performance_data_for_gruff(all_authorities_performance_data[FOR_YEAR], BY_MONTH),
|
77
|
+
performance_for_year_graph_full_path,
|
78
|
+
performance_for_year_graph_filename,
|
79
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_month'))
|
80
|
+
end
|
81
|
+
|
82
|
+
def lifetime_stats(authority_data)
|
83
|
+
authority_data[FOR_LIFETIME]
|
84
|
+
end
|
85
|
+
|
86
|
+
def min_load(stats)
|
87
|
+
format_stat stats[MIN_LOAD]
|
88
|
+
end
|
89
|
+
|
90
|
+
def min_normalization(stats)
|
91
|
+
format_stat stats[MIN_NORMALIZATION]
|
92
|
+
end
|
93
|
+
|
94
|
+
def min_full_request(stats)
|
95
|
+
format_stat stats[MIN_FULL_REQUEST]
|
96
|
+
end
|
97
|
+
|
98
|
+
def max_load(stats)
|
99
|
+
format_stat stats[MAX_LOAD]
|
100
|
+
end
|
101
|
+
|
102
|
+
def max_normalization(stats)
|
103
|
+
format_stat stats[MAX_NORMALIZATION]
|
104
|
+
end
|
105
|
+
|
106
|
+
def max_full_request(stats)
|
107
|
+
format_stat stats[MAX_FULL_REQUEST]
|
108
|
+
end
|
109
|
+
|
110
|
+
def avg_load(stats)
|
111
|
+
format_stat stats[AVG_LOAD]
|
112
|
+
end
|
113
|
+
|
114
|
+
def avg_normalization(stats)
|
115
|
+
format_stat stats[AVG_NORMALIZATION]
|
116
|
+
end
|
117
|
+
|
118
|
+
def avg_full_request(stats)
|
119
|
+
format_stat stats[AVG_FULL_REQUEST]
|
120
|
+
end
|
121
|
+
|
122
|
+
def min_load_style(stats)
|
123
|
+
performance_style_class(stats, MIN_LOAD)
|
124
|
+
end
|
125
|
+
|
126
|
+
def min_normalization_style(stats)
|
127
|
+
performance_style_class(stats, MIN_NORMALIZATION)
|
128
|
+
end
|
129
|
+
|
130
|
+
def min_full_request_style(stats)
|
131
|
+
performance_style_class(stats, MIN_FULL_REQUEST)
|
132
|
+
end
|
133
|
+
|
134
|
+
def max_load_style(stats)
|
135
|
+
performance_style_class(stats, MAX_LOAD)
|
136
|
+
end
|
137
|
+
|
138
|
+
def max_normalization_style(stats)
|
139
|
+
performance_style_class(stats, MAX_NORMALIZATION)
|
140
|
+
end
|
141
|
+
|
142
|
+
def max_full_request_style(stats)
|
143
|
+
performance_style_class(stats, MAX_FULL_REQUEST)
|
144
|
+
end
|
145
|
+
|
146
|
+
def avg_load_style(stats)
|
147
|
+
performance_style_class(stats, AVG_LOAD)
|
148
|
+
end
|
149
|
+
|
150
|
+
def avg_normalization_style(stats)
|
151
|
+
performance_style_class(stats, AVG_NORMALIZATION)
|
152
|
+
end
|
153
|
+
|
154
|
+
def avg_full_request_style(stats)
|
155
|
+
performance_style_class(stats, AVG_FULL_REQUEST)
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def all_authorities_performance_data
|
161
|
+
performance_data[ALL_AUTHS]
|
162
|
+
end
|
163
|
+
|
164
|
+
def format_stat(stat)
|
165
|
+
format("%0.1f", stat)
|
166
|
+
end
|
167
|
+
|
168
|
+
def performance_style_class(stats, stat_key)
|
169
|
+
return "status-bad" if max_threshold_exceeded(stats, stat_key)
|
170
|
+
return "status-unknown" if min_threshold_not_met(stats, stat_key)
|
171
|
+
"status-neutral"
|
172
|
+
end
|
173
|
+
|
174
|
+
MAX_THRESHOLD = 1000 # ms
|
175
|
+
def max_threshold_exceeded(stats, stat_key)
|
176
|
+
return true if stats[stat_key] > MAX_THRESHOLD
|
177
|
+
false
|
178
|
+
end
|
179
|
+
|
180
|
+
MIN_THRESHOLD = 500 # ms
|
181
|
+
def min_threshold_not_met(stats, stat_key)
|
182
|
+
return true unless stats[stat_key] < MIN_THRESHOLD
|
183
|
+
false
|
184
|
+
end
|
185
|
+
|
186
|
+
def performance_graph_theme(g, x_axis_label)
|
187
|
+
g.theme_pastel
|
188
|
+
g.colors = ['#81adf4', '#8696b0', '#06578a']
|
189
|
+
g.marker_font_size = 12
|
190
|
+
g.x_axis_increment = 10
|
191
|
+
g.x_axis_label = x_axis_label
|
192
|
+
g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
|
193
|
+
g.dot_radius = 3
|
194
|
+
g.line_width = 2
|
195
|
+
g.minimum_value = 0
|
196
|
+
g.maximum_value = 1000
|
197
|
+
end
|
198
|
+
|
199
|
+
def graph_filename(authority_name, time_period)
|
200
|
+
"performance_of_#{authority_name}_for_#{time_period}_graph.png"
|
201
|
+
end
|
202
|
+
|
203
|
+
def performance_for_day_graph_filename
|
204
|
+
graph_filename(ALL_AUTHS, :day)
|
205
|
+
end
|
206
|
+
|
207
|
+
def performance_for_day_graph_full_path
|
208
|
+
graph_full_path(performance_for_day_graph_filename)
|
209
|
+
end
|
210
|
+
|
211
|
+
def performance_for_month_graph_filename
|
212
|
+
graph_filename(ALL_AUTHS, :month)
|
213
|
+
end
|
214
|
+
|
215
|
+
def performance_for_month_graph_full_path
|
216
|
+
graph_full_path(performance_for_month_graph_filename)
|
217
|
+
end
|
218
|
+
|
219
|
+
def performance_for_year_graph_filename
|
220
|
+
graph_filename(ALL_AUTHS, :year)
|
221
|
+
end
|
222
|
+
|
223
|
+
def performance_for_year_graph_full_path
|
224
|
+
graph_full_path(performance_for_year_graph_filename)
|
225
|
+
end
|
226
|
+
|
227
|
+
def rework_performance_data_for_gruff(performance_data, label_key)
|
228
|
+
labels = {}
|
229
|
+
load_data = []
|
230
|
+
normalization_data = []
|
231
|
+
full_request_data = []
|
232
|
+
performance_data.each do |i, data|
|
233
|
+
labels[i] = data[label_key]
|
234
|
+
load_data << data[STATS][AVG_LOAD]
|
235
|
+
normalization_data << data[STATS][AVG_NORMALIZATION]
|
236
|
+
full_request_data << data[STATS][AVG_FULL_REQUEST]
|
237
|
+
end
|
238
|
+
[labels, load_data, normalization_data, full_request_data]
|
239
|
+
end
|
240
|
+
|
241
|
+
def performance_graph_file(performance_data, performance_graph_full_path, performance_graph_filename, x_axis_label)
|
242
|
+
g = Gruff::Line.new
|
243
|
+
performance_graph_theme(g, x_axis_label)
|
244
|
+
g.title = ''
|
245
|
+
g.labels = performance_data[0]
|
246
|
+
g.data(I18n.t('qa_server.monitor_status.performance.load_time_ms'), performance_data[1])
|
247
|
+
g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[2])
|
248
|
+
g.data(I18n.t('qa_server.monitor_status.performance.full_request_time_ms'), performance_data[3])
|
249
|
+
g.write performance_graph_full_path
|
250
|
+
File.join(graph_relative_path, performance_graph_filename)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -1,321 +1,34 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'fileutils'
|
4
|
-
require 'gruff'
|
5
|
-
|
6
2
|
# This presenter class provides all data needed by the view that monitors status of authorities.
|
7
3
|
module QaServer
|
8
|
-
class MonitorStatusPresenter
|
9
|
-
|
10
|
-
self.performance_history_class = QaServer::PerformanceHistory
|
11
|
-
|
12
|
-
HISTORICAL_AUTHORITY_NAME_IDX = 0
|
13
|
-
HISTORICAL_FAILURE_COUNT_IDX = 1
|
14
|
-
HISTORICAL_PASSING_COUNT_IDX = 2
|
15
|
-
|
16
|
-
PERFORMANCE_FOR_DAY_KEY = performance_history_class::PERFORMANCE_FOR_DAY_KEY
|
17
|
-
PERFORMANCE_BY_HOUR_KEY = performance_history_class::PERFORMANCE_BY_HOUR_KEY
|
18
|
-
PERFORMANCE_FOR_MONTH_KEY = performance_history_class::PERFORMANCE_FOR_MONTH_KEY
|
19
|
-
PERFORMANCE_BY_DAY_KEY = performance_history_class::PERFORMANCE_BY_DAY_KEY
|
20
|
-
PERFORMANCE_FOR_YEAR_KEY = performance_history_class::PERFORMANCE_FOR_YEAR_KEY
|
21
|
-
PERFORMANCE_BY_MONTH_KEY = performance_history_class::PERFORMANCE_BY_MONTH_KEY
|
22
|
-
LOAD_TIME_KEY = performance_history_class::LOAD_TIME_KEY
|
23
|
-
NORMALIZATION_TIME_KEY = performance_history_class::NORMALIZATION_TIME_KEY
|
24
|
-
COMBINED_TIME_KEY = performance_history_class::COMBINED_TIME_KEY
|
4
|
+
class MonitorStatusPresenter
|
5
|
+
extend Forwardable
|
25
6
|
|
26
7
|
# @param current_summary [ScenarioRunSummary] summary status of the latest run of test scenarios
|
27
8
|
# @param current_data [Array<Hash>] current set of failures for the latest test run, if any
|
28
9
|
# @param historical_summary_data [Array<Hash>] summary of past failuring runs per authority to drive chart
|
29
10
|
# @param performance_data [Hash<Hash>] performance data
|
30
11
|
def initialize(current_summary:, current_failure_data:, historical_summary_data:, performance_data:)
|
31
|
-
@
|
32
|
-
@
|
33
|
-
@
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
# @return [Integer] number of authorities with failing tests in the latest test run
|
53
|
-
def failing_authorities_count
|
54
|
-
@current_failure_data.map { |f| f[:authority_name] }.uniq.count
|
55
|
-
end
|
56
|
-
|
57
|
-
# @return [String] css style class representing whether all tests passed or any failed
|
58
|
-
def authorities_count_style
|
59
|
-
failures? ? 'status-bad' : 'status-good'
|
60
|
-
end
|
61
|
-
|
62
|
-
# @return [Integer] number of tests in the latest test run
|
63
|
-
def tests_count
|
64
|
-
@current_summary.total_scenario_count
|
65
|
-
end
|
66
|
-
|
67
|
-
# @return [Integer] number of passing tests in the latest test run
|
68
|
-
def passing_tests_count
|
69
|
-
@current_summary.passing_scenario_count
|
70
|
-
end
|
71
|
-
|
72
|
-
# @return [Integer] number of failing tests in the latest test run
|
73
|
-
def failing_tests_count
|
74
|
-
@current_summary.failing_scenario_count
|
75
|
-
end
|
76
|
-
|
77
|
-
# @return [String] css style class representing whether all tests passed or any failed
|
78
|
-
def failing_tests_style
|
79
|
-
failures? ? 'summary-status-bad' : 'status-good'
|
80
|
-
end
|
81
|
-
|
82
|
-
# @return [Array<Hash>] A list of failures data in the latest test run, if any
|
83
|
-
# @example
|
84
|
-
# [ { status: :FAIL,
|
85
|
-
# status_label: 'X',
|
86
|
-
# authority_name: 'LOCNAMES_LD4L_CACHE',
|
87
|
-
# subauthority_name: 'person',
|
88
|
-
# service: 'ld4l_cache',
|
89
|
-
# action: 'search',
|
90
|
-
# url: '/qa/search/linked_data/locnames_ld4l_cache/person?q=mark twain&maxRecords=4',
|
91
|
-
# err_message: 'Exception: Something went wrong.' }, ... ]
|
92
|
-
def failures
|
93
|
-
@current_failure_data
|
94
|
-
end
|
95
|
-
|
96
|
-
# @return [Boolean] true if failure data exists for the latest test run; otherwise false
|
97
|
-
def failures?
|
98
|
-
failing_tests_count.positive?
|
99
|
-
end
|
100
|
-
|
101
|
-
# @return [Array<Hash>] historical test data to be displayed (authname, failing, passing)
|
102
|
-
# @example
|
103
|
-
# [ [ 'agrovoc', 0, 24 ],
|
104
|
-
# [ 'geonames_ld4l_cache', 2, 22 ] ... ]
|
105
|
-
def historical_summary
|
106
|
-
@historical_summary_data
|
107
|
-
end
|
108
|
-
|
109
|
-
# @return [Boolean] true if historical test data exists; otherwise false
|
110
|
-
def history?
|
111
|
-
return true if @historical_summary_data.present?
|
112
|
-
false
|
113
|
-
end
|
114
|
-
|
115
|
-
def historical_graph
|
116
|
-
# g = Gruff::SideStackedBar.new('800x400')
|
117
|
-
g = Gruff::SideStackedBar.new
|
118
|
-
historical_graph_theme(g)
|
119
|
-
g.title = ''
|
120
|
-
historical_data = rework_historical_data_for_gruff
|
121
|
-
g.labels = historical_data[0]
|
122
|
-
g.data('Fail', historical_data[1])
|
123
|
-
g.data('Pass', historical_data[2])
|
124
|
-
g.write historical_graph_full_path
|
125
|
-
File.join(graph_relative_path, historical_graph_filename)
|
126
|
-
end
|
127
|
-
|
128
|
-
# @return [String] the name of the css style class to use for the status cell based on the status of the scenario test.
|
129
|
-
def status_style_class(status)
|
130
|
-
"status-#{status[:status]}"
|
131
|
-
end
|
132
|
-
|
133
|
-
# @return [String] the name of the css style class to use for the status cell based on the status of the scenario test.
|
134
|
-
def status_label(status)
|
135
|
-
case status[:status]
|
136
|
-
when :good
|
137
|
-
QaServer::ScenarioRunHistory::GOOD_MARKER
|
138
|
-
when :bad
|
139
|
-
QaServer::ScenarioRunHistory::BAD_MARKER
|
140
|
-
when :unknown
|
141
|
-
QaServer::ScenarioRunHistory::UNKNOWN_MARKER
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def historical_data_authority_name(historical_entry)
|
146
|
-
historical_entry[QaServer::MonitorStatusPresenter::HISTORICAL_AUTHORITY_NAME_IDX]
|
147
|
-
end
|
148
|
-
|
149
|
-
def days_authority_passing(historical_entry)
|
150
|
-
historical_entry[QaServer::MonitorStatusPresenter::HISTORICAL_PASSING_COUNT_IDX]
|
151
|
-
end
|
152
|
-
|
153
|
-
def days_authority_failing(historical_entry)
|
154
|
-
historical_entry[QaServer::MonitorStatusPresenter::HISTORICAL_FAILURE_COUNT_IDX]
|
155
|
-
end
|
156
|
-
|
157
|
-
def days_authority_tested(historical_entry)
|
158
|
-
days_authority_passing(historical_entry) + days_authority_failing(historical_entry)
|
159
|
-
end
|
160
|
-
|
161
|
-
def percent_authority_failing(historical_entry)
|
162
|
-
days_authority_failing(historical_entry).to_f / days_authority_tested(historical_entry)
|
163
|
-
end
|
164
|
-
|
165
|
-
def percent_authority_failing_str(historical_entry)
|
166
|
-
"#{percent_authority_failing(historical_entry) * 100}%"
|
167
|
-
end
|
168
|
-
|
169
|
-
def failure_style_class(historical_entry)
|
170
|
-
return "status-neutral" if days_authority_failing(historical_entry) <= 0
|
171
|
-
return "status-unknown" if percent_authority_failing(historical_entry) < 0.1
|
172
|
-
"status-bad"
|
173
|
-
end
|
174
|
-
|
175
|
-
def passing_style_class(historical_entry)
|
176
|
-
return "status-bad" if days_authority_passing(historical_entry) <= 0
|
177
|
-
"status-good"
|
178
|
-
end
|
179
|
-
|
180
|
-
def display_history_details?
|
181
|
-
display_historical_graph? || display_historical_datatable?
|
182
|
-
end
|
183
|
-
|
184
|
-
def display_historical_graph?
|
185
|
-
QaServer.config.display_historical_graph?
|
186
|
-
end
|
187
|
-
|
188
|
-
def display_historical_datatable?
|
189
|
-
QaServer.config.display_historical_datatable?
|
190
|
-
end
|
191
|
-
|
192
|
-
def performance_data?
|
193
|
-
@performance_data.present?
|
194
|
-
end
|
195
|
-
|
196
|
-
def performance_for_day_graph
|
197
|
-
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_DAY_KEY], :hour),
|
198
|
-
performance_for_day_graph_full_path,
|
199
|
-
performance_for_day_graph_filename,
|
200
|
-
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
201
|
-
end
|
202
|
-
|
203
|
-
def performance_for_month_graph
|
204
|
-
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_MONTH_KEY], :day),
|
205
|
-
performance_for_month_graph_full_path,
|
206
|
-
performance_for_month_graph_filename,
|
207
|
-
I18n.t('qa_server.monitor_status.performance.x_axis_day'))
|
208
|
-
end
|
209
|
-
|
210
|
-
def performance_for_year_graph
|
211
|
-
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_YEAR_KEY], :month),
|
212
|
-
performance_for_year_graph_full_path,
|
213
|
-
performance_for_year_graph_filename,
|
214
|
-
I18n.t('qa_server.monitor_status.performance.x_axis_month'))
|
215
|
-
end
|
216
|
-
|
217
|
-
private
|
218
|
-
|
219
|
-
def historical_graph_theme(g)
|
220
|
-
g.theme_pastel
|
221
|
-
g.colors = ['#ffcccc', '#ccffcc']
|
222
|
-
g.marker_font_size = 12
|
223
|
-
g.x_axis_increment = 10
|
224
|
-
end
|
225
|
-
|
226
|
-
def graph_relative_path
|
227
|
-
File.join('qa_server', 'charts')
|
228
|
-
end
|
229
|
-
|
230
|
-
def graph_full_path(graph_filename)
|
231
|
-
path = Rails.root.join('app', 'assets', 'images', graph_relative_path)
|
232
|
-
FileUtils.mkdir_p path
|
233
|
-
File.join(path, graph_filename)
|
234
|
-
end
|
235
|
-
|
236
|
-
def historical_graph_full_path
|
237
|
-
graph_full_path(historical_graph_filename)
|
238
|
-
end
|
239
|
-
|
240
|
-
def historical_graph_filename
|
241
|
-
'historical_side_stacked_bar.png'
|
242
|
-
end
|
243
|
-
|
244
|
-
def rework_historical_data_for_gruff
|
245
|
-
labels = {}
|
246
|
-
pass_data = []
|
247
|
-
fail_data = []
|
248
|
-
i = 0
|
249
|
-
historical_summary.each do |data|
|
250
|
-
labels[i] = data[0]
|
251
|
-
i += 1
|
252
|
-
fail_data << data[1]
|
253
|
-
pass_data << data[2]
|
254
|
-
end
|
255
|
-
[labels, fail_data, pass_data]
|
256
|
-
end
|
257
|
-
|
258
|
-
def performance_graph_theme(g, x_axis_label)
|
259
|
-
g.theme_pastel
|
260
|
-
g.colors = ['#81adf4', '#8696b0', '#06578a']
|
261
|
-
g.marker_font_size = 12
|
262
|
-
g.x_axis_increment = 10
|
263
|
-
g.x_axis_label = x_axis_label
|
264
|
-
g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
|
265
|
-
g.dot_radius = 3
|
266
|
-
g.line_width = 2
|
267
|
-
g.minimum_value = 0
|
268
|
-
g.maximum_value = 1000
|
269
|
-
end
|
270
|
-
|
271
|
-
def performance_for_day_graph_filename
|
272
|
-
'performance_for_day_graph.png'
|
273
|
-
end
|
274
|
-
|
275
|
-
def performance_for_day_graph_full_path
|
276
|
-
graph_full_path(performance_for_day_graph_filename)
|
277
|
-
end
|
278
|
-
|
279
|
-
def performance_for_month_graph_filename
|
280
|
-
'performance_for_month_graph.png'
|
281
|
-
end
|
282
|
-
|
283
|
-
def performance_for_month_graph_full_path
|
284
|
-
graph_full_path(performance_for_month_graph_filename)
|
285
|
-
end
|
286
|
-
|
287
|
-
def performance_for_year_graph_filename
|
288
|
-
'performance_for_year_graph.png'
|
289
|
-
end
|
290
|
-
|
291
|
-
def performance_for_year_graph_full_path
|
292
|
-
graph_full_path(performance_for_year_graph_filename)
|
293
|
-
end
|
294
|
-
|
295
|
-
def rework_performance_data_for_gruff(performance_data, label_key)
|
296
|
-
labels = {}
|
297
|
-
load_data = []
|
298
|
-
normalization_data = []
|
299
|
-
combined_data = []
|
300
|
-
performance_data.each do |i, data|
|
301
|
-
labels[i] = data[label_key]
|
302
|
-
load_data << data[LOAD_TIME_KEY]
|
303
|
-
normalization_data << data[NORMALIZATION_TIME_KEY]
|
304
|
-
combined_data << data[COMBINED_TIME_KEY]
|
305
|
-
end
|
306
|
-
[labels, load_data, normalization_data, combined_data]
|
307
|
-
end
|
308
|
-
|
309
|
-
def performance_graph_file(performance_data, performance_graph_full_path, performance_graph_filename, x_axis_label)
|
310
|
-
g = Gruff::Line.new
|
311
|
-
performance_graph_theme(g, x_axis_label)
|
312
|
-
g.title = ''
|
313
|
-
g.labels = performance_data[0]
|
314
|
-
g.data(I18n.t('qa_server.monitor_status.performance.load_time_ms'), performance_data[1])
|
315
|
-
g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[2])
|
316
|
-
g.data(I18n.t('qa_server.monitor_status.performance.combined_time_ms'), performance_data[3])
|
317
|
-
g.write performance_graph_full_path
|
318
|
-
File.join(graph_relative_path, performance_graph_filename)
|
319
|
-
end
|
12
|
+
@current_status_presenter = QaServer::MonitorStatus::CurrentStatusPresenter.new(current_summary: current_summary, current_failure_data: current_failure_data)
|
13
|
+
@history_presenter = QaServer::MonitorStatus::HistoryPresenter.new(historical_summary_data: historical_summary_data)
|
14
|
+
@performance_presenter = QaServer::MonitorStatus::PerformancePresenter.new(performance_data: performance_data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def_delegators :@current_status_presenter, :last_updated, :first_updated, :authorities_count, :failing_authorities_count,
|
18
|
+
:authorities_count_style, :tests_count, :passing_tests_count, :failing_tests_count, :failing_tests_style,
|
19
|
+
:failures, :failures?
|
20
|
+
|
21
|
+
def_delegators :@history_presenter, :historical_summary, :history?, :historical_graph, :status_style_class, :status_label,
|
22
|
+
:historical_data_authority_name, :days_authority_passing, :days_authority_failing, :days_authority_tested,
|
23
|
+
:percent_authority_failing, :percent_authority_failing_str, :failure_style_class, :passing_style_class,
|
24
|
+
:display_history_details?, :display_historical_graph?, :display_historical_datatable?
|
25
|
+
|
26
|
+
def_delegators :@performance_presenter, :performance_data, :performance_data?, :display_performance?, :display_performance_graph?,
|
27
|
+
:display_performance_datatable?, :performance_data_authority_name, :performance_for_day_graph, :performance_for_month_graph,
|
28
|
+
:performance_for_year_graph, :lifetime_stats, :min_load, :min_normalization, :min_full_request, :max_load,
|
29
|
+
:max_normalization, :max_full_request, :avg_load, :avg_normalization, :avg_full_request, :min_load_style,
|
30
|
+
:min_normalization_style, :min_full_request_style, :max_load_style, :max_normalization_style, :max_full_request_style,
|
31
|
+
:avg_load_style, :avg_normalization_style, :avg_full_request_style, :performance_style_class, :max_threshold_exceeded,
|
32
|
+
:min_threshold_not_met
|
320
33
|
end
|
321
34
|
end
|
@@ -91,10 +91,11 @@
|
|
91
91
|
</div>
|
92
92
|
<% end %>
|
93
93
|
|
94
|
-
<% if @presenter.performance_data? %>
|
94
|
+
<% if @presenter.display_performance? && @presenter.performance_data? %>
|
95
95
|
<div id="performance-data" class="status-section">
|
96
96
|
<h3><%= t('qa_server.monitor_status.performance.title') %></h3>
|
97
97
|
|
98
|
+
<% if @presenter.display_performance_graph? %>
|
98
99
|
<script>
|
99
100
|
function switch_performance_view(id) {
|
100
101
|
document.getElementById('performance-by-the-hour').style.display = 'none';
|
@@ -149,5 +150,41 @@
|
|
149
150
|
</div>
|
150
151
|
</div>
|
151
152
|
</div>
|
153
|
+
<% end %>
|
154
|
+
|
155
|
+
<% if @presenter.display_performance_datatable? %>
|
156
|
+
<table class="status">
|
157
|
+
<tr>
|
158
|
+
<th></th>
|
159
|
+
<th><%= t('qa_server.monitor_status.performance.slowest_times') %></th>
|
160
|
+
<th><%= t('qa_server.monitor_status.performance.average_times') %></th>
|
161
|
+
<th><%= t('qa_server.monitor_status.performance.fastest_times') %></th>
|
162
|
+
</tr>
|
163
|
+
<% @presenter.performance_data.each do |authority_name, data| %>
|
164
|
+
<% stats = @presenter.lifetime_stats(data) %>
|
165
|
+
<tr>
|
166
|
+
<td class="table_subheading" colspan="4"><%= authority_name %></td>
|
167
|
+
</tr>
|
168
|
+
<tr>
|
169
|
+
<th><%= t('qa_server.monitor_status.performance.load_times') %></th>
|
170
|
+
<td class="<%= @presenter.max_load_style(stats) %>"><%= @presenter.max_load(stats) %></td>
|
171
|
+
<td class="<%= @presenter.avg_load_style(stats) %>"><%= @presenter.avg_load(stats) %></td>
|
172
|
+
<td class="<%= @presenter.min_load_style(stats) %>"><%= @presenter.min_load(stats) %></td>
|
173
|
+
</tr>
|
174
|
+
<tr>
|
175
|
+
<th><%= t('qa_server.monitor_status.performance.normalization_times') %></th>
|
176
|
+
<td class="<%= @presenter.max_normalization_style(stats) %>"><%= @presenter.max_normalization(stats) %></td>
|
177
|
+
<td class="<%= @presenter.avg_normalization_style(stats) %>"><%= @presenter.avg_normalization(stats) %></td>
|
178
|
+
<td class="<%= @presenter.min_normalization_style(stats) %>"><%= @presenter.min_normalization(stats) %></td>
|
179
|
+
</tr>
|
180
|
+
<tr>
|
181
|
+
<th><%= t('qa_server.monitor_status.performance.full_request_times') %></th>
|
182
|
+
<td class="<%= @presenter.max_full_request_style(stats) %>"><%= @presenter.max_full_request(stats) %></td>
|
183
|
+
<td class="<%= @presenter.avg_full_request_style(stats) %>"><%= @presenter.avg_full_request(stats) %></td>
|
184
|
+
<td class="<%= @presenter.min_full_request_style(stats) %>"><%= @presenter.min_full_request(stats) %></td>
|
185
|
+
</tr>
|
186
|
+
<% end %>
|
187
|
+
</table>
|
188
|
+
<% end %>
|
152
189
|
<% end %>
|
153
190
|
</div>
|
@@ -81,12 +81,19 @@ en:
|
|
81
81
|
menu_year: Year
|
82
82
|
load_time_ms: Load Time (ms)
|
83
83
|
normalization_time_ms: Normalization Time (ms)
|
84
|
-
|
84
|
+
full_request_time_ms: Full Request Time (ms)
|
85
85
|
x_axis_hour: Hour
|
86
86
|
x_axis_day: Day
|
87
87
|
x_axis_month: Month
|
88
88
|
y_axis_ms: Milliseconds (ms)
|
89
89
|
now: NOW
|
90
90
|
today: TODAY
|
91
|
+
authority: Authority
|
92
|
+
average_times: Average (ms)
|
93
|
+
fastest_times: Fastest (ms)
|
94
|
+
slowest_times: Slowest (ms)
|
95
|
+
load_times: Load
|
96
|
+
normalization_times: Normalization
|
97
|
+
full_request_times: Total
|
91
98
|
usage:
|
92
99
|
title: Usage
|
@@ -8,6 +8,14 @@ QaServer.config do |config|
|
|
8
8
|
# @param [Boolean] display history datatable when true
|
9
9
|
# config.display_historical_datatable = true
|
10
10
|
|
11
|
+
# Displays a graph of performance test data when true
|
12
|
+
# @param [Boolean] display performance graph when true
|
13
|
+
# config.display_performance_graph = false
|
14
|
+
|
15
|
+
# Displays a datatable of performance test data when true
|
16
|
+
# @param [Boolean] display performance datatable when true
|
17
|
+
# config.display_performance_datatable = true
|
18
|
+
|
11
19
|
# Additional menu items to add to the main navigation menu's set of left justified menu items
|
12
20
|
# @param [Array<Hash<String,String>>] array of menu items to append with hash label: is menu item label to display and hash url: is URL for the menu item link
|
13
21
|
# config.navmenu_extra_leftitems = [
|