qa_server 2.2.1 → 2.2.2

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.
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