qa_server 2.2.1 → 2.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/app/assets/stylesheets/qa_server/_monitor-status.scss +8 -0
  4. data/app/controllers/qa_server/check_status_controller.rb +1 -1
  5. data/app/controllers/qa_server/monitor_status_controller.rb +71 -13
  6. data/app/models/concerns/qa_server/performance_history_data_keys.rb +29 -0
  7. data/app/models/qa_server/performance_history.rb +75 -179
  8. data/app/prepends/prepended_linked_data/find_term.rb +1 -1
  9. data/app/prepends/prepended_linked_data/search_query.rb +1 -1
  10. data/app/presenters/concerns/qa_server/monitor_status/gruff_graph.rb +0 -1
  11. data/app/presenters/concerns/qa_server/monitor_status/performance_datatable_behavior.rb +101 -0
  12. data/app/presenters/concerns/qa_server/monitor_status/performance_graph_behavior.rb +109 -0
  13. data/app/presenters/qa_server/monitor_status/performance_presenter.rb +4 -220
  14. data/app/presenters/qa_server/monitor_status_presenter.rb +8 -5
  15. data/app/services/qa_server/performance_calculator_service.rb +103 -0
  16. data/app/services/qa_server/performance_graph_data_service.rb +113 -0
  17. data/app/services/qa_server/performance_graphing_service.rb +113 -0
  18. data/app/views/qa_server/monitor_status/_performance.html.erb +90 -0
  19. data/app/views/qa_server/monitor_status/_test_history.html.erb +32 -0
  20. data/app/views/qa_server/monitor_status/_test_summary.html.erb +54 -0
  21. data/app/views/qa_server/monitor_status/index.html.erb +3 -182
  22. data/config/locales/qa_server.en.yml +11 -7
  23. data/lib/generators/qa_server/templates/config/initializers/qa_server.rb +26 -0
  24. data/lib/qa_server/configuration.rb +42 -0
  25. data/lib/qa_server/version.rb +1 -1
  26. metadata +11 -2
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+ # This module provides methods for creating and accessing performance graphs.
3
+ module QaServer::MonitorStatus
4
+ module PerformanceGraphBehavior
5
+ include QaServer::PerformanceHistoryDataKeys
6
+ include QaServer::MonitorStatus::GruffGraph
7
+
8
+ def performance_graphs
9
+ auth_list = QaServer::AuthorityListerService.authorities_list
10
+ graphs = []
11
+ performance_graphs_for_authority(graphs, ALL_AUTH)
12
+ auth_list.each { |auth_name| performance_graphs_for_authority(graphs, auth_name) }
13
+ graphs
14
+ end
15
+
16
+ def performance_graph(graph_info)
17
+ graph_info[:graph]
18
+ end
19
+
20
+ def performance_graph_authority(graph_info)
21
+ graph_info[:authority_name]
22
+ end
23
+
24
+ def performance_graph_label(graph_info)
25
+ graph_info[:label]
26
+ end
27
+
28
+ def performance_default_graph_id
29
+ "performance-for-day-#{ALL_AUTH}"
30
+ end
31
+
32
+ def performance_graph_id(graph_info)
33
+ "#{graph_info[:base_id]}-during-#{graph_info[:time_period]}-chart"
34
+ end
35
+
36
+ def performance_graph_data_section_id(graph_info)
37
+ "#{graph_info[:base_id]}-during-#{graph_info[:time_period]}"
38
+ end
39
+
40
+ def performance_graph_data_section_base_id(graph_info)
41
+ graph_info[:base_id]
42
+ end
43
+
44
+ def performance_data_section_class(graph_info)
45
+ return 'performance-data-section-visible' if default_graph?(graph_info)
46
+ 'performance-data-section-hidden'
47
+ end
48
+
49
+ def performance_day_graph_selected?(graph_info)
50
+ return true if graph_info[:time_period] == :day
51
+ false
52
+ end
53
+
54
+ def performance_month_graph_selected?(graph_info)
55
+ return true if graph_info[:time_period] == :month
56
+ false
57
+ end
58
+
59
+ def performance_year_graph_selected?(graph_info)
60
+ return true if graph_info[:time_period] == :year
61
+ false
62
+ end
63
+
64
+ private
65
+
66
+ def default_graph?(graph_info) # rubocop:disable Metrics/CyclomaticComplexity
67
+ return true if QaServer.config.performance_graph_default_time_period == :day && performance_day_graph_selected?(graph_info)
68
+ return true if QaServer.config.performance_graph_default_time_period == :month && performance_month_graph_selected?(graph_info)
69
+ return true if QaServer.config.performance_graph_default_time_period == :year && performance_year_graph_selected?(graph_info)
70
+ false
71
+ end
72
+
73
+ def performance_graphs_for_authority(graphs, auth_name)
74
+ graphs << performance_for_day_graph(auth_name)
75
+ graphs << performance_for_month_graph(auth_name)
76
+ graphs << performance_for_year_graph(auth_name)
77
+ end
78
+
79
+ def performance_for_day_graph(auth_name)
80
+ {
81
+ time_period: :day,
82
+ graph: QaServer::PerformanceGraphingService.performance_graph_file(authority_name: auth_name, time_period: :day),
83
+ label: "Performance data for the last 24 hours.",
84
+ authority_name: auth_name,
85
+ base_id: "performance-for-#{auth_name}"
86
+ }
87
+ end
88
+
89
+ def performance_for_month_graph(auth_name)
90
+ {
91
+ time_period: :month,
92
+ graph: QaServer::PerformanceGraphingService.performance_graph_file(authority_name: auth_name, time_period: :month),
93
+ label: "Performance data for the last 30 days.",
94
+ authority_name: auth_name,
95
+ base_id: "performance-for-#{auth_name}"
96
+ }
97
+ end
98
+
99
+ def performance_for_year_graph(auth_name)
100
+ {
101
+ time_period: :year,
102
+ graph: QaServer::PerformanceGraphingService.performance_graph_file(authority_name: auth_name, time_period: :year),
103
+ label: "Performance data for the last 12 months.",
104
+ authority_name: auth_name,
105
+ base_id: "performance-for-#{auth_name}"
106
+ }
107
+ end
108
+ end
109
+ end
@@ -1,35 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  # This presenter class provides performance data needed by the view that monitors status of authorities.
3
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
-
4
+ class PerformancePresenter
8
5
  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
6
+ include QaServer::MonitorStatus::PerformanceDatatableBehavior
7
+ include QaServer::MonitorStatus::PerformanceGraphBehavior
8
+ include QaServer::PerformanceHistoryDataKeys
33
9
 
34
10
  # @param performance_data [Hash<Hash>] performance data
35
11
  def initialize(performance_data:)
@@ -57,197 +33,5 @@ module QaServer::MonitorStatus
57
33
  def performance_data_authority_name(entry)
58
34
  entry.keys.first
59
35
  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
36
  end
253
37
  end
@@ -25,10 +25,13 @@ module QaServer
25
25
 
26
26
  def_delegators :@performance_presenter, :performance_data, :performance_data?, :display_performance?, :display_performance_graph?,
27
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
28
+ :performance_for_year_graph, :datatable_stats, :low_load, :low_normalization, :low_full_request, :high_load,
29
+ :high_normalization, :high_full_request, :avg_load, :avg_normalization, :avg_full_request, :low_load_style,
30
+ :low_normalization_style, :low_full_request_style, :high_load_style, :high_normalization_style, :high_full_request_style,
31
+ :avg_load_style, :avg_normalization_style, :avg_full_request_style, :performance_style_class, :high_threshold_exceeded,
32
+ :low_threshold_not_met, :performance_graphs, :performance_graph, :performance_graph_authority, :performance_graph_label,
33
+ :performance_default_graph_id, :performance_graph_id, :performance_graph_data_section_id, :performance_graph_data_section_base_id,
34
+ :performance_data_section_class, :performance_day_graph_selected?, :performance_month_graph_selected?,
35
+ :performance_year_graph_selected?, :performance_table_description
33
36
  end
34
37
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+ # This class calculates min, max, average stats for load, normalization, and full request times for a given set of performance records.
3
+ require 'matrix'
4
+ module QaServer
5
+ class PerformanceCalculatorService
6
+ include QaServer::PerformanceHistoryDataKeys
7
+
8
+ attr_reader :records
9
+ attr_reader :stats
10
+
11
+ # @param records [Array <Qa::PerformanceHistory>] set of records used to calculate the statistics
12
+ def initialize(records)
13
+ @records = records
14
+ @stats = {}
15
+ end
16
+
17
+ # Calculate performance statistics for a set of PerformanceHistory records. Min is at the 10th percentile. Max is at the 90th percentile.
18
+ # @return [Hash] hash of the statistics
19
+ # @example
20
+ # { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
21
+ # load_min_ms: 12.3, normalization_min_ms: 4.2, full_request_min_ms: 16.5,
22
+ # load_max_ms: 12.3, normalization_max_ms: 4.2, full_request_max_ms: 16.5 }
23
+ def calculate_stats(avg: false, low: false, high: false, load: true, norm: true, full: true) # rubocop:disable Metrics/ParameterLists
24
+ calculate_load_stats(avg, low, high) if load
25
+ calculate_norm_stats(avg, low, high) if norm
26
+ calculate_full_stats(avg, low, high) if full
27
+ stats
28
+ end
29
+
30
+ private
31
+
32
+ def calculate_load_stats(avg, low, high)
33
+ stats[AVG_LOAD] = calculate_average(load_times) if avg
34
+ stats[LOW_LOAD] = calculate_10th_percentile(load_times_sorted) if low
35
+ stats[HIGH_LOAD] = calculate_90th_percentile(load_times_sorted) if high
36
+ end
37
+
38
+ def calculate_norm_stats(avg, low, high)
39
+ stats[AVG_NORM] = calculate_average(norm_times) if avg
40
+ stats[LOW_NORM] = calculate_10th_percentile(norm_times_sorted) if low
41
+ stats[HIGH_NORM] = calculate_90th_percentile(norm_times_sorted) if high
42
+ end
43
+
44
+ def calculate_full_stats(avg, low, high)
45
+ stats[AVG_FULL] = calculate_average(full_times) if avg
46
+ stats[LOW_FULL] = calculate_10th_percentile(full_times_sorted) if low
47
+ stats[HIGH_FULL] = calculate_90th_percentile(full_times_sorted) if high
48
+ end
49
+
50
+ def count
51
+ @count ||= records.count
52
+ end
53
+
54
+ def tenth_percentile_count
55
+ return @tenth_percentile_count if @tenth_percentile_count.present?
56
+ percentile_count = (count * 0.1).round
57
+ percentile_count = 1 if percentile_count.zero? && count > 1
58
+ @tenth_percentile_count = percentile_count
59
+ end
60
+
61
+ def load_times
62
+ @load_times ||= records.pluck(:load_time_ms).to_a
63
+ end
64
+
65
+ def load_times_sorted
66
+ @load_times_sorted ||= load_times.sort
67
+ end
68
+
69
+ def norm_times
70
+ @norm_times ||= records.pluck(:normalization_time_ms).to_a
71
+ end
72
+
73
+ def norm_times_sorted
74
+ @norm_times_sorted ||= norm_times.sort
75
+ end
76
+
77
+ def full_times
78
+ @full_times ||= (Vector.elements(load_times) + Vector.elements(norm_times)).to_a
79
+ end
80
+
81
+ def full_times_sorted
82
+ @full_times_sorted ||= full_times.sort
83
+ end
84
+
85
+ def calculate_average(times)
86
+ return 0 if count.zero?
87
+ return times[0] if count == 1
88
+ times.inject(0.0) { |sum, el| sum + el } / count
89
+ end
90
+
91
+ def calculate_10th_percentile(sorted_times)
92
+ return 0 if count.zero?
93
+ return sorted_times[0] if count == 1
94
+ sorted_times[tenth_percentile_count - 1]
95
+ end
96
+
97
+ def calculate_90th_percentile(sorted_times)
98
+ return 0 if count.zero?
99
+ return sorted_times[0] if count == 1
100
+ sorted_times[count - tenth_percentile_count]
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+ # This class sets performance stats for the last 24 hours, past 30 days, and the past 12 months.
3
+ module QaServer
4
+ class PerformanceGraphDataService
5
+ class << self
6
+ include QaServer::PerformanceHistoryDataKeys
7
+
8
+ class_attribute :stats_calculator_class, :performance_data_class
9
+ self.stats_calculator_class = QaServer::PerformanceCalculatorService
10
+ self.performance_data_class = QaServer::PerformanceHistory
11
+
12
+ # Get hourly average for the past 24 hours.
13
+ # @returns [Hash] performance statistics for the past 24 hours
14
+ # @example
15
+ # { 0: { hour: '1400', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
16
+ # 1: { hour: '1500', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
17
+ # 2: { hour: '1600', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
18
+ # ...,
19
+ # 23: { hour: 'NOW', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
20
+ # }
21
+ def average_last_24_hours(auth_name = nil)
22
+ start_hour = Time.now.getlocal.beginning_of_hour - 23.hours
23
+ avgs = {}
24
+ 0.upto(23).each do |idx|
25
+ where_clause = { dt_stamp: start_hour..start_hour.end_of_hour }
26
+ where_clause[:authority] = auth_name unless auth_name.nil?
27
+ records = performance_data_class.where(where_clause)
28
+ stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
29
+ data = {}
30
+ data[BY_HOUR] = performance_by_hour_label(idx, start_hour)
31
+ data[STATS] = stats
32
+ avgs[idx] = data
33
+ start_hour += 1.hour
34
+ end
35
+ avgs
36
+ end
37
+
38
+ # Get daily average for the past 30 days.
39
+ # @returns [Hash] performance statistics for the past 30 days
40
+ # @example
41
+ # { 0: { day: '07-15-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
42
+ # 1: { day: '07-16-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
43
+ # 2: { day: '07-17-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
44
+ # ...,
45
+ # 29: { day: 'TODAY', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
46
+ # }
47
+ def average_last_30_days(auth_name = nil)
48
+ start_day = Time.now.getlocal.beginning_of_day - 29.days
49
+ avgs = {}
50
+ 0.upto(29).each do |idx|
51
+ where_clause = { dt_stamp: start_day..start_day.end_of_day }
52
+ where_clause[:authority] = auth_name unless auth_name.nil?
53
+ records = performance_data_class.where(where_clause)
54
+ stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
55
+ data = {}
56
+ data[BY_DAY] = performance_by_day_label(idx, start_day)
57
+ data[STATS] = stats
58
+ avgs[idx] = data
59
+ start_day += 1.day
60
+ end
61
+ avgs
62
+ end
63
+
64
+ # Get daily average for the past 12 months.
65
+ # @returns [Hash] performance statistics for the past 12 months
66
+ # @example
67
+ # { 0: { month: '09-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
68
+ # 1: { month: '10-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
69
+ # 2: { month: '11-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
70
+ # ...,
71
+ # 11: { month: '08-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
72
+ # }
73
+ def average_last_12_months(auth_name = nil)
74
+ start_month = Time.now.getlocal.beginning_of_month - 11.months
75
+ avgs = {}
76
+ 0.upto(11).each do |idx|
77
+ where_clause = { dt_stamp: start_month..start_month.end_of_month }
78
+ where_clause[:authority] = auth_name unless auth_name.nil?
79
+ records = performance_data_class.where(where_clause)
80
+ stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
81
+ data = {}
82
+ data[BY_MONTH] = start_month.strftime("%m-%Y")
83
+ data[STATS] = stats
84
+ avgs[idx] = data
85
+ start_month += 1.month
86
+ end
87
+ avgs
88
+ end
89
+
90
+ private
91
+
92
+ def performance_by_hour_label(idx, start_hour)
93
+ if idx == 23
94
+ I18n.t('qa_server.monitor_status.performance.now')
95
+ elsif ((idx + 1) % 2).zero?
96
+ (start_hour.hour * 100).to_s
97
+ else
98
+ ""
99
+ end
100
+ end
101
+
102
+ def performance_by_day_label(idx, start_day)
103
+ if idx == 29
104
+ I18n.t('qa_server.monitor_status.performance.today')
105
+ elsif ((idx + 1) % 5).zero?
106
+ start_day.strftime("%m-%d")
107
+ else
108
+ ""
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end