qa_server 6.2.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/app/cache_processors/concerns/qa_server/cache_keys.rb +15 -0
- data/app/cache_processors/qa_server/cache_expiry_service.rb +33 -0
- data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +60 -0
- data/app/cache_processors/qa_server/performance_datatable_cache.rb +33 -0
- data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +65 -0
- data/app/cache_processors/qa_server/performance_monthly_graph_cache.rb +60 -0
- data/app/cache_processors/qa_server/scenario_history_cache.rb +35 -0
- data/app/cache_processors/qa_server/scenario_run_cache.rb +28 -0
- data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +51 -0
- data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +40 -0
- data/app/controllers/qa_server/monitor_status_controller.rb +39 -48
- data/app/jobs/qa_server/monitor_tests_job.rb +1 -1
- data/app/models/qa_server/scenario_run_history.rb +27 -84
- data/app/models/qa_server/scenario_run_registry.rb +1 -1
- data/app/services/qa_server/performance_datatable_service.rb +6 -9
- data/app/services/qa_server/performance_graph_data_service.rb +77 -154
- data/app/services/qa_server/performance_graphing_service.rb +34 -47
- data/lib/qa_server/version.rb +1 -1
- data/spec/{services/qa_server/monitor_cache_service_spec.rb → cache_processors/qa_server/cache_expiry_service_spec.rb} +1 -1
- metadata +15 -6
- data/app/services/qa_server/monitor_cache_service.rb +0 -22
- /data/app/{models → cache_processors}/qa_server/performance_cache.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fb73032a8e4f6dfb0d782a8635d8f43668b63a06
|
4
|
+
data.tar.gz: a857cd62d41bc035a241419815e9fff67fdf1d5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 490cfcc14713a0fad8e3d5d60aa5d23a5699c5c3ab23359164848a8f5a3223bbf8fb2bbbffbd9f59b5220efed3eec4f4d63a8fece546dee916886f91a51f0287
|
7
|
+
data.tar.gz: '04027957aeb5955a65a4a5d23d4fd11c7b98827c650ba9b736512953fb10c260e11c9ad4f76de85991861706874eedd7e04bb523184c2a1693e079dc0317b142'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
### 7.0.0 (2020-02-19)
|
2
|
+
|
3
|
+
* refactor of caching system to simplify the process
|
4
|
+
* rename monitor_cache_service to cache_expiry_service
|
5
|
+
* move generation of hourly graph to cache_processors
|
6
|
+
* move generation of daily and monthly graphs to cache_processors
|
7
|
+
* move performance datatable cache control to cache_processors
|
8
|
+
* move caching of summary and historical data to cache_processors
|
9
|
+
* move caching of test execution marker to cache_processors
|
10
|
+
* move performance cache of performance data to cache_processors
|
11
|
+
|
1
12
|
### 6.2.0 (2020-02-17)
|
2
13
|
|
3
14
|
* use authentication for refreshing monitor tests
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This module sets up the keys used to identify data in Rails.cache
|
3
|
+
module QaServer
|
4
|
+
module CacheKeys
|
5
|
+
SCENARIO_RUN_TEST_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_test_data"
|
6
|
+
SCENARIO_RUN_SUMMARY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_summary_data"
|
7
|
+
SCENARIO_RUN_FAILURE_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_failure_data"
|
8
|
+
SCENARIO_RUN_HISTORY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_history_data"
|
9
|
+
|
10
|
+
PERFORMANCE_DATATABLE_DATA_CACHE_KEY = "QaServer--Cache--performance_datatable_data"
|
11
|
+
PERFORMANCE_GRAPH_HOURLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_hourly_data"
|
12
|
+
PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_daily_data"
|
13
|
+
PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_monthly_data"
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Helper methods for caching for monitoring status.
|
3
|
+
module QaServer
|
4
|
+
class CacheExpiryService
|
5
|
+
class << self
|
6
|
+
# @return [Float] number of seconds until cache should expire
|
7
|
+
def cache_expiry
|
8
|
+
cache_expires_at - QaServer::TimeService.current_time
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param key [String] cache key
|
12
|
+
# @param force [Boolean] if true, forces cache to regenerate by returning true; otherwise, uses cache expiry to determine whether cache has expired
|
13
|
+
# @return [Boolean] true if cache has expired or is being forced to expire
|
14
|
+
def cache_expired?(key:, force:, next_expiry:)
|
15
|
+
# will return true only if the full expiry has passed or force was requested
|
16
|
+
force = Rails.cache.fetch(key, expires_in: 5.minutes, race_condition_ttl: 30.seconds, force: force) { true }
|
17
|
+
# reset cache so it will next expired at expected time
|
18
|
+
Rails.cache.fetch(key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: true) { false }
|
19
|
+
force
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# @return [ActiveSupport::TimeWithZone] DateTime at which cache should expire
|
25
|
+
def cache_expires_at
|
26
|
+
offset = QaServer.config.hour_offset_to_expire_cache
|
27
|
+
offset_time = QaServer::TimeService.current_time
|
28
|
+
offset_time = offset_time.tomorrow unless (offset_time + 5.minutes).hour < offset
|
29
|
+
offset_time.beginning_of_day + offset.hours - 5.minutes
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generate graphs for the past 30 days using cached data. Graphs are generated only if the cache has expired.
|
3
|
+
module QaServer
|
4
|
+
class PerformanceDailyGraphCache
|
5
|
+
class_attribute :authority_list_class, :graph_data_service, :graphing_service
|
6
|
+
self.authority_list_class = QaServer::AuthorityListerService
|
7
|
+
self.graph_data_service = QaServer::PerformanceGraphDataService
|
8
|
+
self.graphing_service = QaServer::PerformanceGraphingService
|
9
|
+
|
10
|
+
class << self
|
11
|
+
include QaServer::CacheKeys
|
12
|
+
include QaServer::PerformanceHistoryDataKeys
|
13
|
+
|
14
|
+
# Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
|
15
|
+
# @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
|
16
|
+
def generate_graphs(force: false)
|
17
|
+
return unless QaServer::CacheExpiryService.cache_expired?(key: cache_key_for_force, force: force, next_expiry: next_expiry)
|
18
|
+
QaServer.config.monitor_logger.debug("(QaServer::PerformanceDailyGraphCache) - GENERATING daily performance graphs (force: #{force})")
|
19
|
+
generate_graphs_for_authorities
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_graphs_for_authorities
|
25
|
+
auths = authority_list_class.authorities_list
|
26
|
+
generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
|
27
|
+
auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_graphs_for_authority(authority_name:)
|
31
|
+
[SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
|
32
|
+
hash[action] = generate_30_day_graph(authority_name: authority_name, action: action)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_30_day_graph(authority_name:, action:)
|
37
|
+
# real expiration or force caught by cache_expired? So if we are here, either the cache has expired
|
38
|
+
# or force was requested. We still expire the cache and use ttl to catch race conditions.
|
39
|
+
Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
|
40
|
+
expires_in: next_expiry, race_condition_ttl: 1.hour, force: true) do
|
41
|
+
data = graph_data_service.calculate_last_30_days(authority_name: authority_name, action: action)
|
42
|
+
graphing_service.generate_daily_graph(authority_name: authority_name, action: action, data: data)
|
43
|
+
data
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def cache_key_for_authority_action(authority_name:, action:)
|
48
|
+
"#{PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def cache_key_for_force
|
52
|
+
"#{PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY}--force"
|
53
|
+
end
|
54
|
+
|
55
|
+
def next_expiry
|
56
|
+
QaServer::CacheExpiryService.cache_expiry
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Maintain a cache of data for the Performance Datatable
|
3
|
+
module QaServer
|
4
|
+
class PerformanceDatatableCache
|
5
|
+
include QaServer::CacheKeys
|
6
|
+
|
7
|
+
class_attribute :performance_data_service
|
8
|
+
self.performance_data_service = QaServer::PerformanceDatatableService
|
9
|
+
|
10
|
+
# Retrieve performance datatable data from the cache
|
11
|
+
# @param force [Boolean] if true, calculate the stats even if the cache hasn't expired; otherwise, use cache if not expired
|
12
|
+
# @returns [Hash] performance statistics for configured time period by action for each authority
|
13
|
+
# @example
|
14
|
+
# { all_authorities:
|
15
|
+
# { search:
|
16
|
+
# { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
|
17
|
+
# retrieve_10th_ms: 12.3, graph_load_10th_ms: 12.3, normalization_10th_ms: 4.2, full_request_10th_ms: 16.5,
|
18
|
+
# retrieve_90th_ms: 12.3, graph_load_90th_ms: 12.3, normalization_90th_ms: 4.2, full_request_90th_ms: 16.5 },
|
19
|
+
# fetch: { ... # same data as for search_stats },
|
20
|
+
# all: { ... # same data as for search_stats }
|
21
|
+
# },
|
22
|
+
# AGROVOC_LD4L_CACHE: { ... # same data for each authority }
|
23
|
+
# }
|
24
|
+
def self.data(force: false)
|
25
|
+
Rails.cache.fetch(PERFORMANCE_DATATABLE_DATA_CACHE_KEY,
|
26
|
+
expires_in: QaServer::CacheExpiryService.cache_expiry,
|
27
|
+
race_condition_ttl: 5.minutes, force: force) do
|
28
|
+
QaServer.config.monitor_logger.debug("(QaServer::PerformanceDatatableCache) - CALCULATING performance datatable stats (force: #{force})")
|
29
|
+
performance_data_service.calculate_datatable_data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generate graphs for the past 24 hours using cached data. The last hour of data is always calculated and all graphs
|
3
|
+
# for are generated.
|
4
|
+
module QaServer
|
5
|
+
class PerformanceHourlyGraphCache
|
6
|
+
class_attribute :authority_list_class, :graph_data_service, :graphing_service
|
7
|
+
self.authority_list_class = QaServer::AuthorityListerService
|
8
|
+
self.graph_data_service = QaServer::PerformanceGraphDataService
|
9
|
+
self.graphing_service = QaServer::PerformanceGraphingService
|
10
|
+
|
11
|
+
class << self
|
12
|
+
include QaServer::CacheKeys
|
13
|
+
include QaServer::PerformanceHistoryDataKeys
|
14
|
+
|
15
|
+
# Generates graphs for the past 24 hours for :search, :fetch, and :all actions for each authority.
|
16
|
+
# @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
|
17
|
+
def generate_graphs(force: false)
|
18
|
+
QaServer.config.monitor_logger.debug("(QaServer::PerformanceHourlyGraphCache) - GENERATING hourly performance graphs (force: #{force})")
|
19
|
+
QaServer.config.performance_cache.write_all
|
20
|
+
generate_graphs_for_authorities(force: force)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def generate_graphs_for_authorities(force:)
|
26
|
+
auths = authority_list_class.authorities_list
|
27
|
+
generate_graphs_for_authority(authority_name: ALL_AUTH, force: force) # generates graph for all authorities
|
28
|
+
auths.each { |authname| generate_graphs_for_authority(authority_name: authname, force: force) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate_graphs_for_authority(authority_name:, force:)
|
32
|
+
[SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
|
33
|
+
hash[action] = generate_24_hour_graph(authority_name: authority_name, action: action, force: force)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate_24_hour_graph(authority_name:, action:, force:)
|
38
|
+
graph_created = false
|
39
|
+
data = Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
|
40
|
+
expires_in: QaServer::TimeService.current_time.end_of_hour - QaServer::TimeService.current_time,
|
41
|
+
race_condition_ttl: 1.hour, force: force) do
|
42
|
+
data = graph_data_service.calculate_last_24_hours(authority_name: authority_name, action: action)
|
43
|
+
graphing_service.generate_hourly_graph(authority_name: authority_name, action: action, data: data)
|
44
|
+
graph_created = true
|
45
|
+
data
|
46
|
+
end
|
47
|
+
regen_last_hour_and_graph(authority_name: authority_name, action: action, data: data) unless graph_created
|
48
|
+
end
|
49
|
+
|
50
|
+
def regen_last_hour_and_graph(authority_name:, action:, data:)
|
51
|
+
Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
|
52
|
+
expires_in: QaServer::TimeService.current_time.end_of_hour - QaServer::TimeService.current_time,
|
53
|
+
race_condition_ttl: 1.hour, force: true) do
|
54
|
+
data = graph_data_service.recalculate_last_hour(authority_name: authority_name, action: action, averages: data)
|
55
|
+
graphing_service.generate_hourly_graph(authority_name: authority_name, action: action, data: data)
|
56
|
+
data
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def cache_key_for_authority_action(authority_name:, action:)
|
61
|
+
"#{PERFORMANCE_GRAPH_HOURLY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generate graphs for the past 12 months using cached data. Graphs are generated only if the cache has expired.
|
3
|
+
module QaServer
|
4
|
+
class PerformanceMonthlyGraphCache
|
5
|
+
class_attribute :authority_list_class, :graph_data_service, :graphing_service
|
6
|
+
self.authority_list_class = QaServer::AuthorityListerService
|
7
|
+
self.graph_data_service = QaServer::PerformanceGraphDataService
|
8
|
+
self.graphing_service = QaServer::PerformanceGraphingService
|
9
|
+
|
10
|
+
class << self
|
11
|
+
include QaServer::CacheKeys
|
12
|
+
include QaServer::PerformanceHistoryDataKeys
|
13
|
+
|
14
|
+
# Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
|
15
|
+
# @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
|
16
|
+
def generate_graphs(force: false)
|
17
|
+
return unless QaServer::CacheExpiryService.cache_expired?(key: cache_key_for_force, force: force, next_expiry: next_expiry)
|
18
|
+
QaServer.config.monitor_logger.debug("(QaServer::PerformanceMonthlyGraphCache) - GENERATING monthly performance graphs (force: #{force})")
|
19
|
+
generate_graphs_for_authorities
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def generate_graphs_for_authorities
|
25
|
+
auths = authority_list_class.authorities_list
|
26
|
+
generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
|
27
|
+
auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
|
28
|
+
end
|
29
|
+
|
30
|
+
def generate_graphs_for_authority(authority_name:)
|
31
|
+
[SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
|
32
|
+
hash[action] = generate_12_month_graph(authority_name: authority_name, action: action)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def generate_12_month_graph(authority_name:, action:)
|
37
|
+
# real expiration or force caught by cache_expired? So if we are here, either the cache has expired
|
38
|
+
# or force was requested. We still expire the cache and use ttl to catch race conditions.
|
39
|
+
Rails.cache.fetch(cache_key_for_authority_action(authority_name: authority_name, action: action),
|
40
|
+
expires_in: next_expiry, race_condition_ttl: 1.hour, force: true) do
|
41
|
+
data = graph_data_service.calculate_last_12_months(authority_name: authority_name, action: action)
|
42
|
+
graphing_service.generate_monthly_graph(authority_name: authority_name, action: action, data: data)
|
43
|
+
data
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def cache_key_for_authority_action(authority_name:, action:)
|
48
|
+
"#{PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY}--#{authority_name}--#{action}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def cache_key_for_force
|
52
|
+
"#{PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY}--force"
|
53
|
+
end
|
54
|
+
|
55
|
+
def next_expiry
|
56
|
+
QaServer::CacheExpiryService.cache_expiry
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Maintain a cache of data for Authority Connection History table displayed on Monitor Status page
|
3
|
+
module QaServer
|
4
|
+
class ScenarioHistoryCache
|
5
|
+
class_attribute :scenario_history_class
|
6
|
+
self.scenario_history_class = QaServer::ScenarioRunHistory
|
7
|
+
|
8
|
+
class << self
|
9
|
+
include QaServer::CacheKeys
|
10
|
+
|
11
|
+
# Get a summary of the number of days passing/failing for scenario runs during configured time period
|
12
|
+
# @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
|
13
|
+
# @returns [Array<Hash>] count of days with passing/failing tests for each authority
|
14
|
+
# @example [auth_name, failing, passing]
|
15
|
+
# { 'agrovoc' => { good: 31, bad: 2 },
|
16
|
+
# 'geonames_ld4l_cache' => { good: 32, bad: 1 } }
|
17
|
+
def historical_summary(force: false)
|
18
|
+
Rails.cache.fetch(cache_key_for_historical_data, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
|
19
|
+
QaServer.config.monitor_logger.debug("(QaServer::ScenarioHistoryCache) - CALCULATING HISTORY of scenario runs (force: force)")
|
20
|
+
scenario_history_class.historical_summary
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def cache_key_for_historical_data
|
27
|
+
SCENARIO_RUN_HISTORY_DATA_CACHE_KEY
|
28
|
+
end
|
29
|
+
|
30
|
+
def next_expiry
|
31
|
+
QaServer::CacheExpiryService.cache_expiry
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Maintain a cache controlling the execution of scenario tests.
|
3
|
+
module QaServer
|
4
|
+
class ScenarioRunCache
|
5
|
+
class << self
|
6
|
+
include QaServer::CacheKeys
|
7
|
+
|
8
|
+
# Run connection tests
|
9
|
+
def run_tests(force: false)
|
10
|
+
Rails.cache.fetch(cache_key_for_running_tests, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
|
11
|
+
QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunCache) - KICKING OFF TEST RUN (force: #{force})")
|
12
|
+
QaServer::MonitorTestsJob.perform_later
|
13
|
+
"Test run initiated at #{QaServer::TimeService.current_time}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def cache_key_for_running_tests
|
20
|
+
SCENARIO_RUN_TEST_DATA_CACHE_KEY
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_expiry
|
24
|
+
QaServer::CacheExpiryService.cache_expiry
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Maintain a cache of failure data for scenario runs
|
3
|
+
module QaServer
|
4
|
+
class ScenarioRunFailuresCache
|
5
|
+
class_attribute :scenario_history_class
|
6
|
+
self.scenario_history_class = QaServer::ScenarioRunHistory
|
7
|
+
|
8
|
+
class << self
|
9
|
+
include QaServer::CacheKeys
|
10
|
+
|
11
|
+
# Set of failures for a run
|
12
|
+
# @param run [QaServer::ScenarioRunRegistry]
|
13
|
+
# @returns [Array<Hash>] details for any failing scenarios in the run
|
14
|
+
# @example
|
15
|
+
# [ { status: :bad,
|
16
|
+
# authority_name: "geonames_ld4l_cache",
|
17
|
+
# subauthority_name: "area",
|
18
|
+
# service: "ld4l_cache",
|
19
|
+
# action: "search",
|
20
|
+
# url: "/qa/search/linked_data/geonames_ld4l_cache/area?q=France&maxRecords=4",
|
21
|
+
# err_message: "Unable to connect to authority",
|
22
|
+
# scenario_type: :connection
|
23
|
+
# run_time: 11.2 },
|
24
|
+
# { status: :unknown,
|
25
|
+
# authority_name: "oclcfast_ld4l_cache",
|
26
|
+
# subauthority_name: "Person",
|
27
|
+
# service: "ld4l_cache",
|
28
|
+
# action: "search",
|
29
|
+
# url: "/qa/search/linked_data/oclcfast_ld4l_cache/person?q=mark twain&maxRecords=4",
|
30
|
+
# err_message: "Not enough search results returned",
|
31
|
+
# scenario_type: :connection
|
32
|
+
# run_time: 0.123 } ]
|
33
|
+
def failures_for_run(run:)
|
34
|
+
Rails.cache.fetch(cache_key_for_run_failures(run.id), expires_in: next_expiry, race_condition_ttl: 30.seconds) do
|
35
|
+
QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunFailuresCache) - CALCULATING FAILURES for scenario run #{run.id}")
|
36
|
+
scenario_history_class.run_failures(run_id: run.id)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def cache_key_for_run_failures(id)
|
43
|
+
"#{SCENARIO_RUN_FAILURE_DATA_CACHE_KEY}--#{id}{"
|
44
|
+
end
|
45
|
+
|
46
|
+
def next_expiry
|
47
|
+
QaServer::CacheExpiryService.cache_expiry
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Maintain a cache of summary test data for scenario runs
|
3
|
+
module QaServer
|
4
|
+
class ScenarioRunSummaryCache
|
5
|
+
class_attribute :scenario_history_class
|
6
|
+
self.scenario_history_class = QaServer::ScenarioRunHistory
|
7
|
+
|
8
|
+
class << self
|
9
|
+
include QaServer::CacheKeys
|
10
|
+
|
11
|
+
# Summary for a run
|
12
|
+
# @param run [QaServer::ScenarioRunRegistry]
|
13
|
+
# @returns [QaServer::ScenarioRunSummary] statistics on the requested run
|
14
|
+
# @example ScenarioRunSummary includes methods for accessing
|
15
|
+
# * run_id [Integer] e.g. 14
|
16
|
+
# * run_dt_stamp [ActiveSupport::TimeWithZone] e.g. Wed, 19 Feb 2020 16:01:07 UTC +00:00
|
17
|
+
# * authority_count [Integer] e.g. 22
|
18
|
+
# * failing_authority_count [Integer] e.g. 1
|
19
|
+
# * passing_scenario_count [Integer] e.g. 156
|
20
|
+
# * failing_scenario_count [Integer] e.g. 3
|
21
|
+
# * total_scenario_count [Integer] e.g. 159
|
22
|
+
def summary_for_run(run:)
|
23
|
+
Rails.cache.fetch(cache_key_for_run_summary(run.id), expires_in: next_expiry, race_condition_ttl: 30.seconds) do
|
24
|
+
QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunSummaryCache) - CALCULATING SUMMARY for scenario run #{run.id}")
|
25
|
+
scenario_history_class.run_summary(scenario_run: run)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def cache_key_for_run_summary(id)
|
32
|
+
"#{SCENARIO_RUN_SUMMARY_DATA_CACHE_KEY}--#{id}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def next_expiry
|
36
|
+
QaServer::CacheExpiryService.cache_expiry
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -7,78 +7,63 @@ module QaServer
|
|
7
7
|
include QaServer::AuthorityValidationBehavior
|
8
8
|
|
9
9
|
class_attribute :presenter_class,
|
10
|
-
:scenario_run_registry_class
|
11
|
-
:scenario_history_class,
|
12
|
-
:performance_history_class,
|
13
|
-
:graphing_service_class
|
10
|
+
:scenario_run_registry_class
|
14
11
|
self.presenter_class = QaServer::MonitorStatusPresenter
|
15
12
|
self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
|
16
|
-
self.scenario_history_class = QaServer::ScenarioRunHistory
|
17
|
-
self.performance_history_class = QaServer::PerformanceHistory
|
18
|
-
self.graphing_service_class = QaServer::PerformanceGraphingService
|
19
13
|
|
20
14
|
# Sets up presenter with data to display in the UI
|
21
15
|
def index
|
22
16
|
log_header
|
23
|
-
|
17
|
+
update_tests
|
18
|
+
update_performance_graphs
|
24
19
|
commit_cache if commit_cache?
|
25
20
|
@presenter = presenter_class.new(current_summary: latest_summary,
|
26
21
|
current_failure_data: latest_failures,
|
27
22
|
historical_summary_data: historical_data,
|
28
23
|
performance_data: performance_table_data)
|
29
|
-
|
30
|
-
QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}) DONE rendering")
|
24
|
+
QaServer.config.monitor_logger.debug("~~~~~~~~ DONE rendering monitor status")
|
31
25
|
render 'index', status: :internal_server_error if latest_summary.failing_authority_count.positive?
|
32
26
|
end
|
33
27
|
|
34
28
|
private
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
@latest_test_run ||= latest_test_run_from_cache
|
30
|
+
def update_tests
|
31
|
+
QaServer::ScenarioRunCache.run_tests(force: refresh_tests?)
|
39
32
|
end
|
40
33
|
|
41
|
-
#
|
42
|
-
|
43
|
-
|
44
|
-
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer::MonitorCacheService.cache_expiry, race_condition_ttl: 5.minutes, force: refresh_tests?) do
|
45
|
-
QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}) get latest run of monitoring tests - cache expired or refresh requested (force: #{refresh_tests?})")
|
46
|
-
QaServer::MonitorTestsJob.perform_later
|
47
|
-
scenario_run_registry_class.latest_run
|
48
|
-
end
|
34
|
+
# Sets @latest_test_run [QaServer::ScenarioRunRegistry]
|
35
|
+
def latest_test_run
|
36
|
+
@latest_test_run ||= scenario_run_registry_class.latest_run
|
49
37
|
end
|
50
38
|
|
51
|
-
#
|
39
|
+
# @returns [QaServer::ScenarioRunSummary] summary statistics on the latest run
|
52
40
|
def latest_summary
|
53
|
-
|
41
|
+
QaServer::ScenarioRunSummaryCache.summary_for_run(run: latest_test_run)
|
54
42
|
end
|
55
43
|
|
44
|
+
# @returns [Array<Hash>] scenario details for any failing scenarios in the latest run
|
45
|
+
# @see QaServer::ScenarioRunHistory#run_failures for structure of output
|
56
46
|
def latest_failures
|
57
|
-
|
47
|
+
QaServer::ScenarioRunFailuresCache.failures_for_run(run: latest_test_run)
|
58
48
|
end
|
59
49
|
|
60
|
-
#
|
50
|
+
# Get a summary level of historical data
|
51
|
+
# @returns [Array<Hash>] summary of passing/failing tests for each authority
|
52
|
+
# @see QaServer::ScenarioRunHistory#historical_summary for structure of output
|
61
53
|
def historical_data
|
62
|
-
|
54
|
+
QaServer::ScenarioHistoryCache.historical_summary(force: refresh_history?)
|
63
55
|
end
|
64
56
|
|
65
|
-
# Sets @performance_table_data [Hash<Hash>]
|
66
57
|
def performance_table_data
|
67
|
-
|
58
|
+
return {} unless QaServer.config.display_performance_graph?
|
59
|
+
QaServer::PerformanceDatatableCache.data(force: refresh_performance_table?)
|
68
60
|
end
|
69
61
|
|
70
62
|
def update_performance_graphs
|
71
|
-
return unless display_performance_graph?
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
def display_performance_datatable?
|
77
|
-
@display_performance_datatable ||= QaServer.config.display_performance_datatable?
|
78
|
-
end
|
79
|
-
|
80
|
-
def display_performance_graph?
|
81
|
-
@display_performance_graph ||= QaServer.config.display_performance_graph?
|
63
|
+
return unless QaServer.config.display_performance_graph?
|
64
|
+
QaServer::PerformanceHourlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
|
65
|
+
QaServer::PerformanceDailyGraphCache.generate_graphs(force: refresh_performance_graphs?)
|
66
|
+
QaServer::PerformanceMonthlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
|
82
67
|
end
|
83
68
|
|
84
69
|
def refresh?
|
@@ -91,18 +76,23 @@ module QaServer
|
|
91
76
|
end
|
92
77
|
|
93
78
|
def refresh_tests?
|
94
|
-
|
95
|
-
refresh_all? || params[:refresh].casecmp?('tests')
|
79
|
+
refresh? ? (refresh_all? || params[:refresh].casecmp?('tests')) : false
|
96
80
|
end
|
97
81
|
|
98
82
|
def refresh_history?
|
99
|
-
|
100
|
-
refresh_all? || params[:refresh].casecmp?('history')
|
83
|
+
refresh? ? (refresh_all? || params[:refresh].casecmp?('history')) : false
|
101
84
|
end
|
102
85
|
|
103
86
|
def refresh_performance?
|
104
|
-
|
105
|
-
|
87
|
+
refresh? ? (refresh_all? || params[:refresh].casecmp?('performance')) : false
|
88
|
+
end
|
89
|
+
|
90
|
+
def refresh_performance_table?
|
91
|
+
refresh? ? (refresh_performance? || params[:refresh].casecmp?('performance_table')) : false
|
92
|
+
end
|
93
|
+
|
94
|
+
def refresh_performance_graphs?
|
95
|
+
refresh? ? (refresh_performance? || params[:refresh].casecmp?('performance_graphs')) : false
|
106
96
|
end
|
107
97
|
|
108
98
|
def commit_cache?
|
@@ -124,9 +114,10 @@ module QaServer
|
|
124
114
|
end
|
125
115
|
|
126
116
|
def log_header
|
127
|
-
QaServer.config.monitor_logger.debug("
|
128
|
-
QaServer.config.monitor_logger.debug("
|
129
|
-
|
117
|
+
QaServer.config.monitor_logger.debug("------------------------------------ monitor status -----------------------------------")
|
118
|
+
QaServer.config.monitor_logger.debug("refresh_all? #{refresh_all?}, refresh_tests? #{refresh_tests?}, refresh_history? #{refresh_history?}")
|
119
|
+
QaServer.config.monitor_logger.debug("refresh_performance? #{refresh_performance?}, refresh_performance_table? #{refresh_performance_table?}, " \
|
120
|
+
"refresh_performance_graphs? #{refresh_performance_graphs?})")
|
130
121
|
end
|
131
122
|
end
|
132
123
|
end
|
@@ -10,7 +10,7 @@ module QaServer
|
|
10
10
|
self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
|
11
11
|
|
12
12
|
def perform
|
13
|
-
Rails.cache.fetch("QaServer::MonitorStatusController/latest_test_run_from_cache", expires_in: QaServer::
|
13
|
+
Rails.cache.fetch("QaServer::MonitorStatusController/latest_test_run_from_cache", expires_in: QaServer::CacheExpiryService.cache_expiry, race_condition_ttl: 5.minutes, force: true) do
|
14
14
|
job_id = SecureRandom.uuid
|
15
15
|
monitor_tests_job_id = job_id unless monitor_tests_job_id
|
16
16
|
run_tests if monitor_tests_job_id == job_id # avoid race conditions
|