qa_server 6.2.0 → 7.0.0
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.
- 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
|