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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a9a28076a2932c11c2dcfa1d833665d623ab3969
4
- data.tar.gz: 0e5eeb1c0c5535029f60c8a5f1a4bead059e4bbc
3
+ metadata.gz: fcedba0845e78467d54d898c86ad03498dbc1754
4
+ data.tar.gz: f00bc15be82518d374575eca094c418aa48cb78a
5
5
  SHA512:
6
- metadata.gz: f891059ddd3ef9453bf857dbd7e5cc0ce5cab4beead2897b02efac28803f82a06fb00fb94ce3de487e30bb00f085049e14c80052a8c80565ae4931401c962f7b
7
- data.tar.gz: e4c733a195568694b0bd9ed8fe7704aa62a3ab07c90c6ed2d3876869be33e439c68f28dc081c631182cb9b2dcba42a392b45420a5392a9079eb73c0e25c73040
6
+ metadata.gz: 4bd795410ea1f40b60595933d220a800bfeef12ca2bf7c9210cb3f8b6ff9ca3e77d085447ecea99b50d5f14f85ba359ec5a76533a51bce621dfc05120e465f43
7
+ data.tar.gz: 9f164a65faac0b9f73918b242a5d8eafbc1f769b492be648abf08a050e64b6df0e740962cdbd73777fc0f4f73d4f9f6cf896a7312d2135e0028335b593efaff8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ### 2.2.2 (2019-09-10)
2
+
3
+ * handle stat calculation and formatting when 0 records or missing stats
4
+ * switch performance graph to stacked_bar
5
+ * Use 10th and 90th percentiles for datatable
6
+ * display day graph for every authority for default time period
7
+ * cache performance graphs
8
+ * include authority data for performance graphs
9
+ * move some of the performance data construction code to services
10
+
1
11
  ### 2.2.1 (2019-09-04)
2
12
 
3
13
  * config to optionally display of the performance graph/datatable
@@ -12,6 +12,14 @@ p.status-update-dtstamp {
12
12
  font-style: italic;
13
13
  }
14
14
 
15
+ div.performance-data-section-hidden {
16
+ display: none;
17
+ }
18
+
19
+ div.performance-data-section-visible {
20
+ display: block;
21
+ }
22
+
15
23
  div.right-menu-section {
16
24
  padding-top: 50px;
17
25
  }
@@ -32,7 +32,7 @@ module QaServer
32
32
 
33
33
  def authority_name
34
34
  return @authority_name if @authority_name.present?
35
- @authority_name = (params.key? :authority) ? params[:authority].downcase : nil # rubocop:disable Style/TernaryParentheses
35
+ @authority_name = params.key?(:authority) ? params[:authority].downcase : nil
36
36
  end
37
37
  end
38
38
  end
@@ -6,7 +6,6 @@ module QaServer
6
6
  :scenario_run_registry_class,
7
7
  :scenario_history_class,
8
8
  :performance_history_class
9
-
10
9
  self.presenter_class = QaServer::MonitorStatusPresenter
11
10
  self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
12
11
  self.scenario_history_class = QaServer::ScenarioRunHistory
@@ -14,15 +13,13 @@ module QaServer
14
13
 
15
14
  # Sets up presenter with data to display in the UI
16
15
  def index
17
- if refresh? || expired?
18
- validate(authorities_list)
19
- update_summary_and_data
20
- end
21
- # TODO: Include historical data and performance data too
16
+ refresh_tests
17
+ historical_data = refresh_history
18
+ performance_data = refresh_performance
22
19
  @presenter = presenter_class.new(current_summary: latest_summary,
23
20
  current_failure_data: latest_failures,
24
- historical_summary_data: historical_summary_data,
25
- performance_data: performance_history_class.performance_data)
21
+ historical_summary_data: historical_data,
22
+ performance_data: performance_data)
26
23
  render 'index', status: :internal_server_error if latest_summary.failing_authority_count.positive?
27
24
  end
28
25
 
@@ -46,20 +43,81 @@ module QaServer
46
43
  @latest_failures = nil # reset so next request recalculates
47
44
  end
48
45
 
49
- def historical_summary_data
50
- @historical_summary_data ||= scenario_history_class.historical_summary
51
- end
52
-
53
46
  def expired?
54
- latest_summary.blank? || latest_summary.run_dt_stamp < yesterday_midnight_et
47
+ @expired ||= latest_summary.blank? || latest_summary.run_dt_stamp < yesterday_midnight_et
55
48
  end
56
49
 
57
50
  def yesterday_midnight_et
58
51
  (DateTime.yesterday.midnight.to_time + 4.hours).to_datetime.in_time_zone("Eastern Time (US & Canada)")
59
52
  end
60
53
 
54
+ def historical_summary_data(refresh: false)
55
+ # TODO: Make this refresh the same way performance data refreshes.
56
+ # Requires historical graph to move out of presenter so it can be created here only with refresh.
57
+ if refresh
58
+ @historical_summary_data = scenario_history_class.historical_summary
59
+ # TODO: Need to recreate graph here. And need to only read the graph in presenter.
60
+ end
61
+ @historical_summary_data ||= scenario_history_class.historical_summary
62
+ end
63
+
64
+ def performance_data(refresh: false)
65
+ datatype = performance_datatype(refresh)
66
+ return if datatype == :none
67
+ @performance_data = nil if refresh
68
+ @performance_data ||= performance_history_class.performance_data(datatype: datatype)
69
+ end
70
+
71
+ def performance_datatype(refresh) # rubocop:disable Metrics/CyclomaticComplexity
72
+ return :all if display_performance_datatable? && display_performance_graph? && refresh
73
+ return :datatable if display_performance_datatable?
74
+ return :graph if display_performance_graph? && refresh
75
+ :none
76
+ end
77
+
78
+ def display_performance_datatable?
79
+ @display_performance_datatable ||= QaServer.config.display_performance_datatable?
80
+ end
81
+
82
+ def display_performance_graph?
83
+ @display_performance_graph ||= QaServer.config.display_performance_graph?
84
+ end
85
+
86
+ def refresh_tests
87
+ return unless refresh_tests?
88
+ validate(authorities_list)
89
+ update_summary_and_data
90
+ end
91
+
92
+ def refresh_history
93
+ historical_summary_data(refresh: refresh_history?)
94
+ end
95
+
96
+ def refresh_performance
97
+ performance_data(refresh: refresh_performance?)
98
+ end
99
+
61
100
  def refresh?
62
101
  params.key? :refresh
63
102
  end
103
+
104
+ def refresh_all?
105
+ params[:refresh].nil? || params[:refresh].casecmp?('all') # nil is for backward compatibility
106
+ end
107
+
108
+ def refresh_tests?
109
+ return false unless refresh? || expired?
110
+ refresh_all? || params[:refresh].casecmp?('tests') || expired?
111
+ end
112
+
113
+ def refresh_history?
114
+ return false unless refresh?
115
+ refresh_all? || params[:refresh].casecmp?('history')
116
+ end
117
+
118
+ def refresh_performance?
119
+ return false unless refresh?
120
+ refresh_all? || params[:refresh].casecmp?('performance')
121
+ end
64
122
  end
65
123
  end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ # This module sets up the hash keys for performance data and allows them to be used across all classes
3
+ # setting and reading from the performance data hash.
4
+ module QaServer
5
+ module PerformanceHistoryDataKeys
6
+ ALL_AUTH = :all_authorities
7
+ STATS = :stats
8
+ FOR_DATATABLE = :datatable_stats
9
+
10
+ FOR_DAY = :day
11
+ BY_HOUR = :hour
12
+
13
+ FOR_MONTH = :month
14
+ BY_DAY = :day
15
+
16
+ FOR_YEAR = :year
17
+ BY_MONTH = :month
18
+
19
+ LOW_LOAD = :low_load_ms
20
+ LOW_NORM = :low_normalization_ms
21
+ LOW_FULL = :low_full_request_ms
22
+ AVG_LOAD = :avg_load_ms
23
+ AVG_NORM = :avg_normalization_ms
24
+ AVG_FULL = :avg_full_request_ms
25
+ HIGH_LOAD = :max_load_ms
26
+ HIGH_NORM = :max_normalization_ms
27
+ HIGH_FULL = :max_full_request_ms
28
+ end
29
+ end
@@ -1,55 +1,38 @@
1
1
  # frozen_string_literal: true
2
2
  # Provide access to the scenario_results_history database table which tracks specific scenario runs over time.
3
3
  module QaServer
4
- class PerformanceHistory < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
4
+ class PerformanceHistory < ActiveRecord::Base
5
5
  self.table_name = 'performance_history'
6
6
 
7
7
  enum action: [:fetch, :search]
8
8
 
9
- PERFORMANCE_ALL_KEY = :all_authorities
10
- PERFORMANCE_STATS_KEY = :stats
11
- PERFORMANCE_FOR_LIFETIME_KEY = :lifetime_stats
12
-
13
- PERFORMANCE_FOR_DAY_KEY = :day
14
- PERFORMANCE_BY_HOUR_KEY = :hour
15
-
16
- PERFORMANCE_FOR_MONTH_KEY = :month
17
- PERFORMANCE_BY_DAY_KEY = :day
18
-
19
- PERFORMANCE_FOR_YEAR_KEY = :year
20
- PERFORMANCE_BY_MONTH_KEY = :month
21
-
22
- SUM_LOAD_TIME_KEY = :load_sum_ms
23
- SUM_NORMALIZATION_TIME_KEY = :normalization_sum_ms
24
- SUM_FULL_REQUEST_TIME_KEY = :full_request_sum_ms
25
- MIN_LOAD_TIME_KEY = :load_min_ms
26
- MIN_NORMALIZATION_TIME_KEY = :normalization_min_ms
27
- MIN_FULL_REQUEST_TIME_KEY = :full_request_min_ms
28
- MAX_LOAD_TIME_KEY = :load_max_ms
29
- MAX_NORMALIZATION_TIME_KEY = :normalization_max_ms
30
- MAX_FULL_REQUEST_TIME_KEY = :full_request_max_ms
31
- AVG_LOAD_TIME_KEY = :load_avg_ms
32
- AVG_NORMALIZATION_TIME_KEY = :normalization_avg_ms
33
- AVG_FULL_REQUEST_TIME_KEY = :full_request_avg_ms
9
+ class_attribute :stats_calculator_class, :graph_data_service_class, :graphing_service_class, :authority_list_class
10
+ self.stats_calculator_class = QaServer::PerformanceCalculatorService
11
+ self.graph_data_service_class = QaServer::PerformanceGraphDataService
12
+ self.graphing_service_class = QaServer::PerformanceGraphingService
13
+ self.authority_list_class = QaServer::AuthorityListerService
34
14
 
35
15
  class << self
16
+ include QaServer::PerformanceHistoryDataKeys
17
+
36
18
  # Save a scenario result
37
19
  # @param run_id [Integer] the run on which to gather statistics
38
20
  # @param result [Hash] the scenario result to be saved
39
21
  def save_result(dt_stamp:, authority:, action:, size_bytes:, load_time_ms:, normalization_time_ms:) # rubocop:disable Metrics/ParameterLists
40
- QaServer::PerformanceHistory.create(dt_stamp: dt_stamp,
41
- authority: authority,
42
- action: action,
43
- size_bytes: size_bytes,
44
- load_time_ms: load_time_ms,
45
- normalization_time_ms: normalization_time_ms)
22
+ create(dt_stamp: dt_stamp,
23
+ authority: authority,
24
+ action: action,
25
+ size_bytes: size_bytes,
26
+ load_time_ms: load_time_ms,
27
+ normalization_time_ms: normalization_time_ms)
46
28
  end
47
29
 
48
- # Performance data for a day, a month, and a year.
30
+ # Performance data for a day, a month, a year, and all time for each authority.
31
+ # @param datatype [Symbol] what type of data should be calculated (e.g. :datatable, :graph, :all)
49
32
  # @returns [Hash] performance statistics for the past 24 hours
50
33
  # @example
51
34
  # { all_authorities:
52
- # { lifetime_stats:
35
+ # { datatable_stats:
53
36
  # { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }
54
37
  # }
55
38
  # { day:
@@ -76,179 +59,92 @@ module QaServer
76
59
  # 11: { month: '08-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
77
60
  # }
78
61
  # }
62
+ # { AGROVOC_LD4L_CACHE: ... # same data for each authority }
79
63
  # }
80
- def performance_data
81
- data = {}
82
- data[PERFORMANCE_ALL_KEY] = {
83
- PERFORMANCE_FOR_LIFETIME_KEY => lifetime,
84
- PERFORMANCE_FOR_DAY_KEY => average_last_24_hours,
85
- PERFORMANCE_FOR_MONTH_KEY => average_last_30_days,
86
- PERFORMANCE_FOR_YEAR_KEY => average_last_12_months
87
- }
64
+ def performance_data(datatype: :datatable)
65
+ return if datatype == :none
66
+ data = calculate_data(datatype)
67
+ graphing_service_class.create_performance_graphs(performance_data: data) if calculate_graphdata? datatype
88
68
  data
89
69
  end
90
70
 
91
71
  private
92
72
 
93
- # Get hourly average for the past 24 hours.
94
- # @returns [Hash] performance statistics across all records
95
- # @example
96
- # { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }
97
- def lifetime
98
- records = PerformanceHistory.all
99
- calculate_stats(records)
73
+ def calculate_datatable?(datatype)
74
+ datatype == :datatable || datatype == :all
100
75
  end
101
76
 
102
- # Get hourly average for the past 24 hours.
103
- # @returns [Hash] performance statistics for the past 24 hours
104
- # @example
105
- # { 0: { hour: '1400', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
106
- # 1: { hour: '1500', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
107
- # 2: { hour: '1600', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
108
- # ...,
109
- # 23: { hour: 'NOW', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
110
- # }
111
- def average_last_24_hours
112
- start_hour = Time.now.beginning_of_hour - 23.hours
113
- avgs = {}
114
- 0.upto(23).each do |idx|
115
- records = PerformanceHistory.where(dt_stamp: start_hour..start_hour.end_of_hour)
116
- stats = calculate_stats(records)
117
- data = {}
118
- data[PERFORMANCE_BY_HOUR_KEY] = performance_by_hour_label(idx, start_hour)
119
- data[PERFORMANCE_STATS_KEY] = stats
120
- avgs[idx] = data
121
- start_hour += 1.hour
122
- end
123
- avgs
77
+ def calculate_graphdata?(datatype)
78
+ datatype == :graph || datatype == :all
124
79
  end
125
80
 
126
- def performance_by_hour_label(idx, start_hour)
127
- if idx == 23
128
- I18n.t('qa_server.monitor_status.performance.now')
129
- elsif ((idx + 1) % 2).zero?
130
- (start_hour.hour * 100).to_s
131
- else
132
- ""
133
- end
81
+ def calculate_data(datatype)
82
+ data = {}
83
+ auths = authority_list_class.authorities_list
84
+ data[ALL_AUTH] = data_for_authority(datatype: datatype)
85
+ auths.each { |auth_name| data[auth_name] = data_for_authority(authority_name: auth_name, datatype: datatype) }
86
+ data
134
87
  end
135
88
 
136
- # Get daily average for the past 30 days.
137
- # @returns [Hash] performance statistics for the past 30 days
138
- # @example
139
- # { 0: { day: '07-15-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
140
- # 1: { day: '07-16-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
141
- # 2: { day: '07-17-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
142
- # ...,
143
- # 29: { day: 'TODAY', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
144
- # }
145
- def average_last_30_days
146
- start_day = Time.now.beginning_of_day - 29.days
147
- avgs = {}
148
- 0.upto(29).each do |idx|
149
- records = PerformanceHistory.where(dt_stamp: start_day..start_day.end_of_day)
150
- stats = calculate_stats(records)
151
- data = {}
152
- data[PERFORMANCE_BY_DAY_KEY] = performance_by_day_label(idx, start_day)
153
- data[PERFORMANCE_STATS_KEY] = stats
154
- avgs[idx] = data
155
- start_day += 1.day
89
+ def data_for_authority(authority_name: nil, datatype:)
90
+ data = {}
91
+ data[FOR_DATATABLE] = data_table_stats(authority_name) if calculate_datatable?(datatype)
92
+ if calculate_graphdata?(datatype)
93
+ data[FOR_DAY] = graph_data_service_class.average_last_24_hours(authority_name)
94
+ data[FOR_MONTH] = graph_data_service_class.average_last_30_days(authority_name)
95
+ data[FOR_YEAR] = graph_data_service_class.average_last_12_months(authority_name)
156
96
  end
157
- avgs
97
+ data
158
98
  end
159
99
 
160
- def performance_by_day_label(idx, start_day)
161
- if idx == 29
162
- I18n.t('qa_server.monitor_status.performance.today')
163
- elsif ((idx + 1) % 5).zero?
164
- start_day.strftime("%m-%d")
165
- else
166
- ""
167
- end
168
- end
169
-
170
- # Get daily average for the past 12 months.
171
- # @returns [Hash] performance statistics for the past 12 months
100
+ # Get statistics for all available data.
101
+ # @param [String] auth_name - limit statistics to records for the given authority (default: all authorities)
102
+ # @returns [Hash] performance statistics for the datatable during the expected time period
172
103
  # @example
173
- # { 0: { month: '09-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
174
- # 1: { month: '10-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
175
- # 2: { month: '11-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
176
- # ...,
177
- # 11: { month: '08-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
178
- # }
179
- def average_last_12_months
180
- start_month = Time.now.beginning_of_month - 11.months
181
- avgs = {}
182
- 0.upto(11).each do |idx|
183
- records = PerformanceHistory.where(dt_stamp: start_month..start_month.end_of_month)
184
- stats = calculate_stats(records)
185
- data = {}
186
- data[PERFORMANCE_BY_MONTH_KEY] = start_month.strftime("%m-%Y")
187
- data[PERFORMANCE_STATS_KEY] = stats
188
- avgs[idx] = data
189
- start_month += 1.month
190
- end
191
- avgs
192
- end
193
-
194
- def calculate_stats(records)
195
- stats = init_stats
196
- return stats if records.count.zero?
197
- first = true
198
- records.each do |record|
199
- update_sum_stats(stats, record)
200
- update_min_stats(stats, record)
201
- update_max_stats(stats, record)
202
- first = false
203
- end
204
- calculate_avg_stats(stats, records)
205
- stats
104
+ # { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }
105
+ def data_table_stats(auth_name)
106
+ records = records_for_last_24_hours(auth_name) ||
107
+ records_for_last_30_days(auth_name) ||
108
+ records_for_last_12_months(auth_name) ||
109
+ all_records(auth_name)
110
+ stats_calculator_class.new(records).calculate_stats(avg: true, low: true, high: true)
206
111
  end
207
112
 
208
- MIN_STARTING_TIME = 999_999_999
209
- def init_stats
210
- stats = {}
211
- stats[SUM_LOAD_TIME_KEY] = 0
212
- stats[SUM_NORMALIZATION_TIME_KEY] = 0
213
- stats[SUM_FULL_REQUEST_TIME_KEY] = 0
214
- stats[AVG_LOAD_TIME_KEY] = 0
215
- stats[AVG_NORMALIZATION_TIME_KEY] = 0
216
- stats[AVG_FULL_REQUEST_TIME_KEY] = 0
217
- stats[MIN_LOAD_TIME_KEY] = MIN_STARTING_TIME
218
- stats[MIN_NORMALIZATION_TIME_KEY] = MIN_STARTING_TIME
219
- stats[MIN_FULL_REQUEST_TIME_KEY] = MIN_STARTING_TIME
220
- stats[MAX_LOAD_TIME_KEY] = 0
221
- stats[MAX_NORMALIZATION_TIME_KEY] = 0
222
- stats[MAX_FULL_REQUEST_TIME_KEY] = 0
223
- stats
113
+ def expected_time_period
114
+ QaServer.config.performance_datatable_default_time_period
224
115
  end
225
116
 
226
- def update_sum_stats(stats, record)
227
- stats[SUM_LOAD_TIME_KEY] += record.load_time_ms
228
- stats[SUM_NORMALIZATION_TIME_KEY] += record.normalization_time_ms
229
- stats[SUM_FULL_REQUEST_TIME_KEY] += full_request_time_ms(record)
117
+ def records_for_last_24_hours(auth_name)
118
+ return unless expected_time_period == :day
119
+ end_hour = Time.now.getlocal
120
+ start_hour = end_hour - 23.hours
121
+ where_clause = { dt_stamp: start_hour..end_hour }
122
+ records_for_authority(auth_name, where_clause)
230
123
  end
231
124
 
232
- def update_min_stats(stats, record)
233
- stats[MIN_LOAD_TIME_KEY] = [stats[MIN_LOAD_TIME_KEY], record.load_time_ms].min
234
- stats[MIN_NORMALIZATION_TIME_KEY] = [stats[MIN_NORMALIZATION_TIME_KEY], record.normalization_time_ms].min
235
- stats[MIN_FULL_REQUEST_TIME_KEY] = [stats[MIN_FULL_REQUEST_TIME_KEY], full_request_time_ms(record)].min
125
+ def records_for_last_30_days(auth_name)
126
+ return unless expected_time_period == :month
127
+ end_day = Time.now.getlocal
128
+ start_day = end_day - 29.days
129
+ where_clause = { dt_stamp: start_day..end_day }
130
+ records_for_authority(auth_name, where_clause)
236
131
  end
237
132
 
238
- def update_max_stats(stats, record)
239
- stats[MAX_LOAD_TIME_KEY] = [stats[MAX_LOAD_TIME_KEY], record.load_time_ms].max
240
- stats[MAX_NORMALIZATION_TIME_KEY] = [stats[MAX_NORMALIZATION_TIME_KEY], record.normalization_time_ms].max
241
- stats[MAX_FULL_REQUEST_TIME_KEY] = [stats[MAX_FULL_REQUEST_TIME_KEY], full_request_time_ms(record)].max
133
+ def records_for_last_12_months(auth_name)
134
+ return unless expected_time_period == :year
135
+ end_month = Time.now.getlocal
136
+ start_month = end_month - 11.months
137
+ where_clause = { dt_stamp: start_month..end_month }
138
+ records_for_authority(auth_name, where_clause)
242
139
  end
243
140
 
244
- def calculate_avg_stats(stats, records)
245
- stats[AVG_LOAD_TIME_KEY] = stats[SUM_LOAD_TIME_KEY] / records.count
246
- stats[AVG_NORMALIZATION_TIME_KEY] = stats[SUM_NORMALIZATION_TIME_KEY] / records.count
247
- stats[AVG_FULL_REQUEST_TIME_KEY] = stats[SUM_FULL_REQUEST_TIME_KEY] / records.count
141
+ def all_records(auth_name)
142
+ auth_name.nil? ? PerformanceHistory.all : where(authority: auth_name)
248
143
  end
249
144
 
250
- def full_request_time_ms(record)
251
- record.load_time_ms + record.normalization_time_ms
145
+ def records_for_authority(auth_name, where_clause)
146
+ where_clause[:authority] = auth_name unless auth_name.nil?
147
+ where(where_clause)
252
148
  end
253
149
  end
254
150
  end
@@ -6,7 +6,7 @@ module PrependedLinkedData::FindTerm
6
6
  saved_performance_data = performance_data
7
7
  performance_data = true
8
8
  full_results = super
9
- QaServer::PerformanceHistory.save_result(dt_stamp: Time.now,
9
+ QaServer::PerformanceHistory.save_result(dt_stamp: Time.now.getlocal,
10
10
  authority: authority_name,
11
11
  action: 'fetch',
12
12
  size_bytes: full_results[:performance][:fetched_bytes],
@@ -6,7 +6,7 @@ module PrependedLinkedData::SearchQuery
6
6
  saved_performance_data = performance_data
7
7
  performance_data = true
8
8
  full_results = super
9
- QaServer::PerformanceHistory.save_result(dt_stamp: Time.now,
9
+ QaServer::PerformanceHistory.save_result(dt_stamp: Time.now.getlocal,
10
10
  authority: authority_name,
11
11
  action: 'search',
12
12
  size_bytes: full_results[:performance][:fetched_bytes],
@@ -18,4 +18,3 @@ module QaServer::MonitorStatus
18
18
  end
19
19
  end
20
20
  end
21
- # frozen_string_literal: true
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+ # This module provides access methods into the performance data hash.
3
+ module QaServer::MonitorStatus
4
+ module PerformanceDatatableBehavior
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ def datatable_stats(authority_data)
8
+ authority_data[FOR_DATATABLE]
9
+ end
10
+
11
+ def low_load(stats)
12
+ format_stat stats[LOW_LOAD]
13
+ end
14
+
15
+ def low_normalization(stats)
16
+ format_stat stats[LOW_NORM]
17
+ end
18
+
19
+ def low_full_request(stats)
20
+ format_stat stats[LOW_FULL]
21
+ end
22
+
23
+ def high_load(stats)
24
+ format_stat stats[HIGH_LOAD]
25
+ end
26
+
27
+ def high_normalization(stats)
28
+ format_stat stats[HIGH_NORM]
29
+ end
30
+
31
+ def high_full_request(stats)
32
+ format_stat stats[HIGH_FULL]
33
+ end
34
+
35
+ def avg_load(stats)
36
+ format_stat stats[AVG_LOAD]
37
+ end
38
+
39
+ def avg_normalization(stats)
40
+ format_stat stats[AVG_NORM]
41
+ end
42
+
43
+ def avg_full_request(stats)
44
+ format_stat stats[AVG_FULL]
45
+ end
46
+
47
+ def low_full_request_style(stats)
48
+ performance_style_class(stats, LOW_FULL)
49
+ end
50
+
51
+ def high_full_request_style(stats)
52
+ performance_style_class(stats, HIGH_FULL)
53
+ end
54
+
55
+ def avg_full_request_style(stats)
56
+ performance_style_class(stats, AVG_FULL)
57
+ end
58
+
59
+ def performance_table_description
60
+ case expected_time_period
61
+ when :day
62
+ I18n.t('qa_server.monitor_status.performance.datatable_day_desc')
63
+ when :month
64
+ I18n.t('qa_server.monitor_status.performance.datatable_month_desc')
65
+ when :year
66
+ I18n.t('qa_server.monitor_status.performance.datatable_year_desc')
67
+ else
68
+ I18n.t('qa_server.monitor_status.performance.datatable_all_desc')
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def expected_time_period
75
+ QaServer.config.performance_datatable_default_time_period
76
+ end
77
+
78
+ def format_stat(stat)
79
+ return '' if stat.nil?
80
+ format("%0.1f", stat)
81
+ end
82
+
83
+ def performance_style_class(stats, stat_key)
84
+ return "status-bad" if max_threshold_exceeded(stats, stat_key)
85
+ return "status-unknown" if desired_threshold_not_met(stats, stat_key)
86
+ "status-good"
87
+ end
88
+
89
+ def max_threshold_exceeded(stats, stat_key)
90
+ return false if stats[stat_key].nil?
91
+ return true if stats[stat_key] > QaServer.config.performance_datatable_max_threshold
92
+ false
93
+ end
94
+
95
+ def desired_threshold_not_met(stats, stat_key)
96
+ return false if stats[stat_key].nil?
97
+ return true unless stats[stat_key] < QaServer.config.performance_datatable_warning_threshold
98
+ false
99
+ end
100
+ end
101
+ end