qa_server 7.2.1 → 7.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4a11e25bb0e1f04c1f4d6a9e1970f1cb438fc752
4
- data.tar.gz: 4a97306cce9c2b6dff9a4e417db000a06c79f3e5
3
+ metadata.gz: fd13388cd52b97f47cbc007512409654b26e4742
4
+ data.tar.gz: 2e7fd2e75b65e662460c334cb9c87a39bb246e9e
5
5
  SHA512:
6
- metadata.gz: c8902939fc36473dbbf7979d0166f72d8e05912ad8b1713268cbe9297f9cfe5c0d01f96cb7b248864c6952c9c9430a061702e783eb37b2536bacc318e04ef637
7
- data.tar.gz: f831642e258fa4d658b283151b73d792242f999629febf58f8f82297b0bed98df5641a4cf03158ffcb689c50438e716ef54734d4bac8182a3be7a8c21cde17c6
6
+ metadata.gz: cc1aff80d3bf495a4dbedc6fdef33ec4e580f38d3e9953048ac5a991e550b807e5a772059a7ef934cada9243506ef48ef717ef973419a8b0bce8b1aae38de480
7
+ data.tar.gz: aa8a277abc68f7db17bec6653990e5c3476e89d0860f670cf99f846cb82e26b76c187502c7bd059781a9212596184fd97654363b0b8be885cea29c1088fb94c2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 7.3.0 (2020-04-08)
2
+
3
+ * move generation of graphs to background jobs
4
+
1
5
  ### 7.2.1 (2020-02-23)
2
6
 
3
7
  * fix graph fails generation when any label is empty string
@@ -2,15 +2,10 @@
2
2
  # This module sets up the keys used to identify data in Rails.cache
3
3
  module QaServer
4
4
  module CacheKeys
5
- SCENARIO_RUN_TEST_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_test_data"
6
5
  SCENARIO_RUN_SUMMARY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_summary_data"
7
6
  SCENARIO_RUN_FAILURE_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_failure_data"
8
7
  SCENARIO_RUN_HISTORY_DATA_CACHE_KEY = "QaServer--CacheKeys--scenario_run_history_data"
9
- SCENARIO_RUN_HISTORY_GRAPH_CACHE_KEY = "QaServer--CacheKeys--scenario_run_history_graph"
10
8
 
11
9
  PERFORMANCE_DATATABLE_DATA_CACHE_KEY = "QaServer--Cache--performance_datatable_data"
12
- PERFORMANCE_GRAPH_HOURLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_hourly_data"
13
- PERFORMANCE_GRAPH_DAILY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_daily_data"
14
- PERFORMANCE_GRAPH_MONTHLY_DATA_CACHE_KEY = "QaServer--CacheKeys--performance_graph_monthly_data"
15
10
  end
16
11
  end
@@ -8,6 +8,11 @@ module QaServer
8
8
  cache_expires_at - QaServer::TimeService.current_time
9
9
  end
10
10
 
11
+ def end_of_hour_expiry
12
+ ct = QaServer::TimeService.current_time
13
+ ct.end_of_hour - ct
14
+ end
15
+
11
16
  # @param key [String] cache key
12
17
  # @param force [Boolean] if true, forces cache to regenerate by returning true; otherwise, uses cache expiry to determine whether cache has expired
13
18
  # @return [Boolean] true if cache has expired or is being forced to expire
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ # Provide service methods for getting a list of all authorities and scenarios for an authority.
3
+ module QaServer
4
+ class JobIdCache
5
+ class << self
6
+ # Is the passed in job_id the active one for the job_key?
7
+ # @param job_key [String] key unique to the job being run (e.g. "QaServer::Jobs::MonitorTestsJob")
8
+ # @param job_id [String] UUID for job running the tests
9
+ # @param expires_in [ActiveSupport::Duration] This should be at least as long as the expected job run time to avoid multiple instances of the job running at the same time.
10
+ # @note When job completes, call reset_job_id to invalidate the cache
11
+ def active_job_id?(job_key:, job_id:, expires_in: 30.minutes)
12
+ cached_job_id = Rails.cache.fetch(cache_key(job_key), expires_in: expires_in, race_condition_ttl: 5.minutes) { job_id }
13
+ cached_job_id == job_id
14
+ end
15
+
16
+ # Delete cache for job id for the job represented by job_key. Call this when the job completes.
17
+ # @param job_key [String] key unique to the job being run (e.g. "QaServer::Jobs::MonitorTestsJob")
18
+ def reset_job_id(job_key:)
19
+ Rails.cache.delete(cache_key(job_key))
20
+ end
21
+
22
+ private
23
+
24
+ def cache_key(job_key)
25
+ "#{job_key}-job_id"
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ # Cache the datetime_stamp of the last time the performance day graph was generated. Calls job to generate the graph if expired.
3
+ module QaServer
4
+ class PerformanceDayGraphCache
5
+ class << self
6
+ # Generates graphs for the past 24 hours for :search, :fetch, and :all actions for each authority.
7
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
8
+ def generate_graphs(force: false)
9
+ Rails.cache.fetch(cache_key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
10
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceDayGraphCache) - KICKING OFF PERFORMANCE DAY GRAPH GENERATION (force: #{force})")
11
+ QaServer::PerformanceDayGraphJob.perform_later
12
+ "Graphs generation initiated at #{QaServer::TimeService.current_time}"
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def cache_key
19
+ "QaServer::PerformanceDayGraphCache.generate_graphs--latest_generation_initiated"
20
+ end
21
+
22
+ def next_expiry
23
+ QaServer::CacheExpiryService.end_of_hour_expiry
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ # Cache the datetime_stamp of the last time the performance month graph was generated. Calls job to generate the graph if expired.
3
+ module QaServer
4
+ class PerformanceMonthGraphCache
5
+ class << self
6
+ # Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
7
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
8
+ def generate_graphs(force: false)
9
+ Rails.cache.fetch(cache_key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
10
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceMonthGraphCache) - KICKING OFF PERFORMANCE MONTH GRAPH GENERATION (force: #{force})")
11
+ QaServer::PerformanceMonthGraphJob.perform_later
12
+ "Graphs generation initiated at #{QaServer::TimeService.current_time}"
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def cache_key
19
+ "QaServer::PerformanceMonthGraphCache.generate_graphs--latest_generation_initiated"
20
+ end
21
+
22
+ def next_expiry
23
+ QaServer::CacheExpiryService.cache_expiry
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+ # Cache the datetime_stamp of the last time the performance year graph was generated. Calls job to generate the graph if expired.
3
+ module QaServer
4
+ class PerformanceYearGraphCache
5
+ class << self
6
+ # Generates graphs for the 12 months for :search, :fetch, and :all actions for each authority.
7
+ # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
8
+ def generate_graphs(force: false)
9
+ Rails.cache.fetch(cache_key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
10
+ QaServer.config.monitor_logger.debug("(QaServer::PerformanceYearGraphCache) - KICKING OFF PERFORMANCE YEAR GRAPH GENERATION (force: #{force})")
11
+ QaServer::PerformanceYearGraphJob.perform_later
12
+ "Graphs generation initiated at #{QaServer::TimeService.current_time}"
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def cache_key
19
+ "QaServer::PerformanceYearGraphCache.generate_graphs--latest_generation_initiated"
20
+ end
21
+
22
+ def next_expiry
23
+ QaServer::CacheExpiryService.cache_expiry
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,26 +2,21 @@
2
2
  # Generate graphs for the past 30 days using cached data. Graphs are generated only if the cache has expired.
3
3
  module QaServer
4
4
  class ScenarioHistoryGraphCache
5
- class_attribute :graphing_service
6
- self.graphing_service = QaServer::HistoryGraphingService
7
-
8
5
  class << self
9
- include QaServer::CacheKeys
10
-
11
- HISTORICAL_GRAPH_FILENAME = 'historical_side_stacked_bar.png'
12
-
13
6
  # Generates graphs for the past 30 days for :search, :fetch, and :all actions for each authority.
14
7
  # @param force [Boolean] if true, run the tests even if the cache hasn't expired; otherwise, use cache if not expired
15
8
  def generate_graph(data:, force: false)
16
- return unless QaServer::CacheExpiryService.cache_expired?(key: cache_key_for_force, force: force, next_expiry: next_expiry)
17
- QaServer.config.monitor_logger.debug("(QaServer::ScenarioHistoryGraphCache) - GENERATING historical summary graph (force: #{force})")
18
- graphing_service.generate_graph(data)
9
+ Rails.cache.fetch(cache_key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
10
+ QaServer.config.monitor_logger.debug("(QaServer::ScenarioHistoryGraphCache) - KICKING OFF HISTORY GRAPH GENERATION (force: #{force})")
11
+ QaServer::HistoryGraphJob.perform_later(data: data)
12
+ "Graph generation initiated at #{QaServer::TimeService.current_time}"
13
+ end
19
14
  end
20
15
 
21
16
  private
22
17
 
23
- def cache_key_for_force
24
- "#{SCENARIO_RUN_HISTORY_GRAPH_CACHE_KEY}--force"
18
+ def cache_key
19
+ "QaServer::ScenarioHistoryGraphCache.generate_graph--latest_generation_initiated"
25
20
  end
26
21
 
27
22
  def next_expiry
@@ -7,7 +7,7 @@ module QaServer
7
7
 
8
8
  # Run connection tests
9
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
10
+ Rails.cache.fetch(cache_key, expires_in: next_expiry, race_condition_ttl: 30.seconds, force: force) do
11
11
  QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunCache) - KICKING OFF TEST RUN (force: #{force})")
12
12
  QaServer::MonitorTestsJob.perform_later
13
13
  "Test run initiated at #{QaServer::TimeService.current_time}"
@@ -16,8 +16,8 @@ module QaServer
16
16
 
17
17
  private
18
18
 
19
- def cache_key_for_running_tests
20
- SCENARIO_RUN_TEST_DATA_CACHE_KEY
19
+ def cache_key
20
+ "QaServer::ScenarioRunCache.run_tests--latest_run_initiated"
21
21
  end
22
22
 
23
23
  def next_expiry
@@ -71,9 +71,9 @@ module QaServer
71
71
 
72
72
  def update_performance_graphs
73
73
  return unless QaServer.config.display_performance_graph?
74
- QaServer::PerformanceHourlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
75
- QaServer::PerformanceDailyGraphCache.generate_graphs(force: refresh_performance_graphs?)
76
- QaServer::PerformanceMonthlyGraphCache.generate_graphs(force: refresh_performance_graphs?)
74
+ QaServer::PerformanceDayGraphCache.generate_graphs(force: refresh_performance_graphs?)
75
+ QaServer::PerformanceMonthGraphCache.generate_graphs(force: refresh_performance_graphs?)
76
+ QaServer::PerformanceYearGraphCache.generate_graphs(force: refresh_performance_graphs?)
77
77
  end
78
78
 
79
79
  def refresh?
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the graph of historical test runs per authority.
3
+ module QaServer
4
+ class HistoryGraphJob < ApplicationJob
5
+ queue_as :default
6
+
7
+ class_attribute :graphing_service
8
+ self.graphing_service = QaServer::HistoryGraphingService
9
+
10
+ def perform(data:)
11
+ # checking active_job_id? prevents race conditions for long running jobs
12
+ generate_graph(data) if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
13
+ end
14
+
15
+ private
16
+
17
+ def generate_graph(data)
18
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) - GENERATING historical summary graph")
19
+ graphing_service.generate_graph(data)
20
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) COMPLETED historical summary graph generation")
21
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
22
+ end
23
+
24
+ def job_key
25
+ "QaServer::HistoryGraphJob--job_id"
26
+ end
27
+ end
28
+ end
@@ -10,12 +10,8 @@ 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::CacheExpiryService.cache_expiry, race_condition_ttl: 5.minutes, force: true) do
14
- job_id = SecureRandom.uuid
15
- monitor_tests_job_id = job_id unless monitor_tests_job_id
16
- run_tests if monitor_tests_job_id == job_id # avoid race conditions
17
- scenario_run_registry_class.latest_run
18
- end
13
+ # checking active_job_id? prevents race conditions for long running jobs
14
+ run_tests if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id, expires_in: 2.hours)
19
15
  end
20
16
 
21
17
  private
@@ -27,32 +23,16 @@ module QaServer
27
23
  scenario_run_registry_class.save_run(scenarios_results: status_log.to_a)
28
24
  QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) COMPLETED monitoring tests")
29
25
  QaServer.config.performance_cache.write_all # write out cache after completing tests
30
- reset_monitor_tests_job_id
31
- end
32
-
33
- # @return [String, Boolean] Returns job id of the job currently running tests; otherwise, false if tests are not running
34
- def monitor_tests_job_id
35
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 5.minutes) { false }
36
- end
37
-
38
- # Set the id of the job that will run the tests.
39
- # @param job_id [String] UUID for job running the tests
40
- def monitor_tests_job_id=(job_id)
41
- # check to see if there is a current job already running tests
42
- current_job_id = Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 5.seconds) { job_id }
43
-
44
- # current_job_id may be false meaning tests are not currently running; in which case, it is ok to force set job_id
45
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 30.seconds, force: true) { job_id } unless current_job_id
46
- end
47
-
48
- # Set job id for monitor tests to false indicating that tests are not currently running
49
- def reset_monitor_tests_job_id
50
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 30.seconds, force: true) { false }
26
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
51
27
  end
52
28
 
53
29
  def log_results(authorities_list, results)
54
30
  QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) authorities_list is empty") if authorities_list&.empty?
55
31
  QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) test results are empty") if results&.empty?
56
32
  end
33
+
34
+ def job_key
35
+ "QaServer::MonitorTestsJob--job_id"
36
+ end
57
37
  end
58
38
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance day graph covering the last 24 hours.
3
+ module QaServer
4
+ class PerformanceDayGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance day graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance day graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
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_24_hour_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_24_hour_graph(authority_name:, action:)
37
+ data = graph_data_service.calculate_last_24_hours(authority_name: authority_name, action: action)
38
+ graphing_service.generate_day_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceDayGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance month graph covering the last 30 days.
3
+ module QaServer
4
+ class PerformanceMonthGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance month graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance month graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
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
+ data = graph_data_service.calculate_last_30_days(authority_name: authority_name, action: action)
38
+ graphing_service.generate_month_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceMonthGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance year graph covering the last 12 months.
3
+ module QaServer
4
+ class PerformanceYearGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance year graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance year graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
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
+ data = graph_data_service.calculate_last_12_months(authority_name: authority_name, action: action)
38
+ graphing_service.generate_year_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceYearGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -73,7 +73,7 @@ module QaServer
73
73
  # @param authority_name [String] name of an authority
74
74
  # @param action [Symbol] :search, :fetch, or :all_actions
75
75
  # @param averages [Hash] existing data for each hour
76
- # @returns [Hash] existing hourly data with the last hour updated
76
+ # @returns [Hash] existing day data with the last hour updated
77
77
  # @example returns
78
78
  # { 0: { hour: '1400', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
79
79
  # 1: { hour: '1500', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
@@ -31,7 +31,7 @@ module QaServer
31
31
  # @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
32
32
  # @param data [Hash] data to use to generate the graph
33
33
  # @see QaServer::PerformanceGraphDataService.calculate_last_12_months
34
- def generate_monthly_graph(authority_name: ALL_AUTH, action:, data:)
34
+ def generate_year_graph(authority_name: ALL_AUTH, action:, data:)
35
35
  gruff_data = rework_performance_data_for_gruff(data, BY_MONTH)
36
36
  create_gruff_graph(gruff_data,
37
37
  performance_graph_full_path(authority_name, action, FOR_YEAR),
@@ -44,7 +44,7 @@ module QaServer
44
44
  # @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
45
45
  # @param data [Hash] data to use to generate the graph
46
46
  # @see QaServer::PerformanceGraphDataService.calculate_last_30_days
47
- def generate_daily_graph(authority_name: ALL_AUTH, action:, data:)
47
+ def generate_month_graph(authority_name: ALL_AUTH, action:, data:)
48
48
  gruff_data = rework_performance_data_for_gruff(data, BY_DAY)
49
49
  create_gruff_graph(gruff_data,
50
50
  performance_graph_full_path(authority_name, action, FOR_MONTH),
@@ -56,7 +56,7 @@ module QaServer
56
56
  # @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
57
57
  # @param data [Hash] data to use to generate the graph
58
58
  # @see QaServer::PerformanceGraphDataService.calculate_last_24_hours
59
- def generate_hourly_graph(authority_name: ALL_AUTH, action:, data:)
59
+ def generate_day_graph(authority_name: ALL_AUTH, action:, data:)
60
60
  gruff_data = rework_performance_data_for_gruff(data, BY_HOUR)
61
61
  create_gruff_graph(gruff_data,
62
62
  performance_graph_full_path(authority_name, action, FOR_DAY),
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module QaServer
3
- VERSION = '7.2.1'
3
+ VERSION = '7.3.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qa_server
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.2.1
4
+ version: 7.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - E. Lynette Rayle
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-23 00:00:00.000000000 Z
11
+ date: 2020-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -340,11 +340,12 @@ files:
340
340
  - app/assets/stylesheets/qa_server/_usage.scss
341
341
  - app/cache_processors/concerns/qa_server/cache_keys.rb
342
342
  - app/cache_processors/qa_server/cache_expiry_service.rb
343
+ - app/cache_processors/qa_server/job_id_cache.rb
343
344
  - app/cache_processors/qa_server/performance_cache.rb
344
- - app/cache_processors/qa_server/performance_daily_graph_cache.rb
345
345
  - app/cache_processors/qa_server/performance_datatable_cache.rb
346
- - app/cache_processors/qa_server/performance_hourly_graph_cache.rb
347
- - app/cache_processors/qa_server/performance_monthly_graph_cache.rb
346
+ - app/cache_processors/qa_server/performance_day_graph_cache.rb
347
+ - app/cache_processors/qa_server/performance_month_graph_cache.rb
348
+ - app/cache_processors/qa_server/performance_year_graph_cache.rb
348
349
  - app/cache_processors/qa_server/scenario_history_cache.rb
349
350
  - app/cache_processors/qa_server/scenario_history_graph_cache.rb
350
351
  - app/cache_processors/qa_server/scenario_run_cache.rb
@@ -357,7 +358,11 @@ files:
357
358
  - app/controllers/qa_server/homepage_controller.rb
358
359
  - app/controllers/qa_server/monitor_status_controller.rb
359
360
  - app/controllers/qa_server/usage_controller.rb
361
+ - app/jobs/qa_server/history_graph_job.rb
360
362
  - app/jobs/qa_server/monitor_tests_job.rb
363
+ - app/jobs/qa_server/performance_day_graph_job.rb
364
+ - app/jobs/qa_server/performance_month_graph_job.rb
365
+ - app/jobs/qa_server/performance_year_graph_job.rb
361
366
  - app/loggers/qa_server/scenario_logger.rb
362
367
  - app/models/concerns/qa_server/performance_history_data_keys.rb
363
368
  - app/models/qa_server/authority_scenario.rb
@@ -1,60 +0,0 @@
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
@@ -1,65 +0,0 @@
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
@@ -1,60 +0,0 @@
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