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.
@@ -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 # rubocop:disable Metrics/ClassLength
9
- class_attribute :performance_history_class
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
- @current_summary = current_summary
32
- @current_failure_data = current_failure_data
33
- @historical_summary_data = historical_summary_data
34
- @performance_data = performance_data
35
- end
36
-
37
- # @return [String] date of last test run
38
- def last_updated
39
- @current_summary.run_dt_stamp.in_time_zone("Eastern Time (US & Canada)").strftime("%m/%d/%y - %I:%M %p")
40
- end
41
-
42
- # @return [String] date of first recorded test run
43
- def first_updated
44
- QaServer::ScenarioRunRegistry.first.dt_stamp.in_time_zone("Eastern Time (US & Canada)").strftime("%m/%d/%y - %I:%M %p")
45
- end
46
-
47
- # @return [Integer] number of loaded authorities
48
- def authorities_count
49
- @current_summary.authority_count
50
- end
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
- combined_time_ms: Full Request Time (ms)
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 = [