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
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# Provide access to the scenario_run_history database table which tracks scenario runs over time.
|
3
3
|
module QaServer
|
4
|
-
class ScenarioRunHistory < ActiveRecord::Base
|
4
|
+
class ScenarioRunHistory < ActiveRecord::Base
|
5
5
|
self.table_name = 'scenario_run_history'
|
6
6
|
belongs_to :scenario_run_registry
|
7
7
|
enum scenario_type: [:connection, :accuracy, :performance], _suffix: :type
|
@@ -35,78 +35,27 @@ module QaServer
|
|
35
35
|
|
36
36
|
# Get a summary of passing/failing tests for a run.
|
37
37
|
# @param scenario_run [QaServer::ScenarioRunRegistry] the run on which to gather statistics
|
38
|
-
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
39
38
|
# @returns [QaServer::ScenarioRunSummary] statistics on the requested run
|
40
39
|
# @example ScenarioRunSummary includes methods for accessing
|
41
|
-
# * run_id
|
42
|
-
# * run_dt_stamp:
|
43
|
-
# * authority_count
|
44
|
-
# * failing_authority_count
|
45
|
-
# * passing_scenario_count
|
46
|
-
# * failing_scenario_count
|
47
|
-
# * total_scenario_count
|
48
|
-
def run_summary(scenario_run
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
passing_scenario_count: status['good'],
|
57
|
-
failing_scenario_count: status['bad'] + status['unknown'])
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# Get set of all scenario results for a run.
|
62
|
-
# @param run_id [Integer] the run on which to gather statistics
|
63
|
-
# @param authority_name [String] limit results to those for the authority with this name
|
64
|
-
# @param status [Array<Symbol> | Symbol] :good, :bad, :unknown, or any of these in an array to select multiple status
|
65
|
-
# @param url [String] limit results to a specific scenario URL
|
66
|
-
# @returns [Array<ScenarioRunHistory>] scenario details for all scenarios in the run
|
67
|
-
# @example
|
68
|
-
# [ { status: :bad,
|
69
|
-
# authority_name: "geonames_ld4l_cache",
|
70
|
-
# subauthority_name: "area",
|
71
|
-
# service: "ld4l_cache",
|
72
|
-
# action: "search",
|
73
|
-
# url: "/qa/search/linked_data/geonames_ld4l_cache/area?q=France&maxRecords=4",
|
74
|
-
# err_message: "Unable to connect to authority",
|
75
|
-
# scenario_type: :connection
|
76
|
-
# run_time: 11.2 },
|
77
|
-
# { status: :good,
|
78
|
-
# authority_name: "oclcfast_ld4l_cache",
|
79
|
-
# subauthority_name: "Organization",
|
80
|
-
# service: "ld4l_cache",
|
81
|
-
# action: "search",
|
82
|
-
# url: "/qa/search/linked_data/oclcfast_ld4l_cache/organization?q=mark twain&maxRecords=4",
|
83
|
-
# err_message: "",
|
84
|
-
# scenario_type: :connection
|
85
|
-
# run_time: 0.131 },
|
86
|
-
# { status: :unknown,
|
87
|
-
# authority_name: "oclcfast_ld4l_cache",
|
88
|
-
# subauthority_name: "Person",
|
89
|
-
# service: "ld4l_cache",
|
90
|
-
# action: "search",
|
91
|
-
# url: "/qa/search/linked_data/oclcfast_ld4l_cache/person?q=mark twain&maxRecords=4",
|
92
|
-
# err_message: "Not enough search results returned",
|
93
|
-
# scenario_type: :connection
|
94
|
-
# run_time: 0.123 } ]
|
95
|
-
# @deprecated Not used anywhere. Being removed.
|
96
|
-
def run_results(run_id:, authority_name: nil, status: nil, url: nil)
|
97
|
-
return [] unless run_id
|
98
|
-
where = {}
|
99
|
-
where[:scenario_run_registry_id] = run_id
|
100
|
-
where[:authority_name] = authority_name if authority_name.present?
|
101
|
-
where[:status] = status if status.present?
|
102
|
-
where[:url] = url if url.present?
|
103
|
-
QaServer::ScenarioRunHistory.where(where).to_a
|
40
|
+
# * run_id [Integer] e.g. 14
|
41
|
+
# * run_dt_stamp [ActiveSupport::TimeWithZone] e.g. Wed, 19 Feb 2020 16:01:07 UTC +00:00
|
42
|
+
# * authority_count [Integer] e.g. 22
|
43
|
+
# * failing_authority_count [Integer] e.g. 1
|
44
|
+
# * passing_scenario_count [Integer] e.g. 156
|
45
|
+
# * failing_scenario_count [Integer] e.g. 3
|
46
|
+
# * total_scenario_count [Integer] e.g. 159
|
47
|
+
def run_summary(scenario_run:)
|
48
|
+
status = status_counts_in_run(run_id: scenario_run.id)
|
49
|
+
summary_class.new(run_id: scenario_run.id,
|
50
|
+
run_dt_stamp: scenario_run.dt_stamp,
|
51
|
+
authority_count: authorities_in_run(run_id: scenario_run.id).count,
|
52
|
+
failing_authority_count: authorities_with_failures_in_run(run_id: scenario_run.id).count,
|
53
|
+
passing_scenario_count: status['good'],
|
54
|
+
failing_scenario_count: status['bad'] + status['unknown'])
|
104
55
|
end
|
105
|
-
deprecation_deprecate run_results: "Not used anywhere. Being removed."
|
106
56
|
|
107
57
|
# Get set of failures for a run, if any.
|
108
58
|
# @param run_id [Integer] the run on which to gather statistics
|
109
|
-
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
110
59
|
# @returns [Array<Hash>] scenario details for any failing scenarios in the run
|
111
60
|
# @example
|
112
61
|
# [ { status: :bad,
|
@@ -127,29 +76,23 @@ module QaServer
|
|
127
76
|
# err_message: "Not enough search results returned",
|
128
77
|
# scenario_type: :connection
|
129
78
|
# run_time: 0.123 } ]
|
130
|
-
def run_failures(run_id
|
79
|
+
def run_failures(run_id:)
|
131
80
|
return [] unless run_id
|
132
|
-
|
133
|
-
QaServer.config.monitor_logger.debug("(QaServer::ScenarioRunHistory##{__method__}) - finding failures in latest run - cache expired or refresh requested (force: #{force})")
|
134
|
-
QaServer::ScenarioRunHistory.where(scenario_run_registry_id: run_id).where.not(status: :good).to_a
|
135
|
-
end
|
81
|
+
QaServer::ScenarioRunHistory.where(scenario_run_registry_id: run_id).where.not(status: :good).to_a
|
136
82
|
end
|
137
83
|
|
138
|
-
# Get a summary
|
139
|
-
# @returns [Array<
|
84
|
+
# Get a summary of the number of days passing/failing for scenario runs during configured time period
|
85
|
+
# @returns [Array<Hash>] count of days with passing/failing tests for each authority
|
140
86
|
# @example [auth_name, failing, passing]
|
141
87
|
# { 'agrovoc' => { good: 31, bad: 2 },
|
142
88
|
# 'geonames_ld4l_cache' => { good: 32, bad: 1 } }
|
143
|
-
def historical_summary
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
keys.each_with_object({}) do |auth, hash|
|
151
|
-
hash[auth] = { good: day_count(auth, days_good), bad: day_count(auth, days_bad) + day_count(auth, days_unknown) }
|
152
|
-
end
|
89
|
+
def historical_summary
|
90
|
+
days_good = count_days(:good)
|
91
|
+
days_bad = count_days(:bad)
|
92
|
+
days_unknown = count_days(:unknown)
|
93
|
+
keys = (days_good.keys + days_bad.keys + days_unknown.keys).uniq.sort
|
94
|
+
keys.each_with_object({}) do |auth, hash|
|
95
|
+
hash[auth] = { good: day_count(auth, days_good), bad: day_count(auth, days_bad) + day_count(auth, days_unknown) }
|
153
96
|
end
|
154
97
|
end
|
155
98
|
|
@@ -25,7 +25,7 @@ module QaServer
|
|
25
25
|
|
26
26
|
# @return [ActiveSupport::TimeWithZone] datetime stamp of first registered run
|
27
27
|
def self.first_run_dt
|
28
|
-
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer::
|
28
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer::CacheExpiryService.cache_expiry, race_condition_ttl: 30.seconds) do
|
29
29
|
QaServer::ScenarioRunRegistry.first.dt_stamp
|
30
30
|
end
|
31
31
|
end
|
@@ -11,7 +11,6 @@ module QaServer
|
|
11
11
|
self.authority_list_class = QaServer::AuthorityListerService
|
12
12
|
|
13
13
|
# Summary of performance by action for each authority for the configured time period (e.g. :day, :month, :year, :all).
|
14
|
-
# @param force [Boolean] if true, calculate the stats even if the cache hasn't expired; otherwise, use cache if not expired
|
15
14
|
# @returns [Hash] performance statistics for configured time period by action for each authority
|
16
15
|
# @example
|
17
16
|
# { all_authorities:
|
@@ -24,14 +23,12 @@ module QaServer
|
|
24
23
|
# },
|
25
24
|
# AGROVOC_LD4L_CACHE: { ... # same data for each authority }
|
26
25
|
# }
|
27
|
-
def calculate_datatable_data
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
data[
|
33
|
-
auths.each { |auth_name| data[auth_name] = datatable_data_for_authority(authority_name: auth_name) }
|
34
|
-
data
|
26
|
+
def calculate_datatable_data
|
27
|
+
data = {}
|
28
|
+
auths = authority_list_class.authorities_list
|
29
|
+
data[ALL_AUTH] = datatable_data_for_authority
|
30
|
+
auths.each_with_object(data) do |auth_name, data| # rubocop:disable Lint/ShadowingOuterLocalVariable
|
31
|
+
data[auth_name] = datatable_data_for_authority(authority_name: auth_name)
|
35
32
|
end
|
36
33
|
end
|
37
34
|
|
@@ -1,135 +1,99 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# This class
|
2
|
+
# This class calculates performance averages to be used to generate graphs for the last 24 hours, 30 days, and 12 months.
|
3
3
|
module QaServer
|
4
|
-
class PerformanceGraphDataService
|
4
|
+
class PerformanceGraphDataService
|
5
5
|
class << self
|
6
6
|
include QaServer::PerformanceHistoryDataKeys
|
7
7
|
|
8
|
-
class_attribute :stats_calculator_class, :performance_data_class
|
8
|
+
class_attribute :stats_calculator_class, :performance_data_class
|
9
9
|
self.stats_calculator_class = QaServer::PerformanceCalculatorService
|
10
10
|
self.performance_data_class = QaServer::PerformanceHistory
|
11
|
-
self.authority_list_class = QaServer::AuthorityListerService
|
12
11
|
|
13
|
-
# Performance data for
|
14
|
-
# @param
|
15
|
-
# @
|
16
|
-
# @
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
# 2: { hour: '1600', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
24
|
-
# ...,
|
25
|
-
# 23: { hour: 'NOW', retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
26
|
-
# },
|
27
|
-
# month:
|
28
|
-
# { 0: { day: '07-15-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
29
|
-
# 1: { day: '07-16-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
30
|
-
# 2: { day: '07-17-2019', 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
|
-
# ...,
|
32
|
-
# 29: { day: 'TODAY', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
33
|
-
# },
|
34
|
-
# year:
|
35
|
-
# { 0: { month: '09-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
36
|
-
# 1: { month: '10-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
37
|
-
# 2: { month: '11-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
38
|
-
# ...,
|
39
|
-
# 11: { month: '08-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
40
|
-
# }
|
41
|
-
# },
|
42
|
-
# fetch: { ... # same data as for search_stats },
|
43
|
-
# all: { ... # same data as for search_stats }
|
44
|
-
# },
|
45
|
-
# AGROVOC_LD4L_CACHE: { ... # same data for each authority }
|
12
|
+
# Performance data for the last 12 months for a specific authority and action
|
13
|
+
# @param authority_name [String] name of an authority
|
14
|
+
# @param action [Symbol] :search, :fetch, or :all_actions
|
15
|
+
# @returns [Hash] performance statistics for the past 12 months
|
16
|
+
# @example returns
|
17
|
+
# { 0: { month: '09-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
18
|
+
# 1: { month: '10-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
19
|
+
# 2: { month: '11-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
20
|
+
# ...,
|
21
|
+
# 11: { month: '08-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
46
22
|
# }
|
47
|
-
def
|
48
|
-
QaServer.
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
auths.each { |auth_name| data[auth_name] = graph_data_for_authority(authority_name: auth_name, force: force, calculate_all: calculate_all) }
|
55
|
-
data
|
23
|
+
def calculate_last_12_months(authority_name:, action:)
|
24
|
+
start_month = QaServer::TimeService.current_time.beginning_of_month - 11.months
|
25
|
+
0.upto(11).each_with_object({}) do |idx, averages|
|
26
|
+
records = records_by(authority_name, action, start_month..start_month.end_of_month)
|
27
|
+
averages[idx] = calculate_from_records(records, BY_MONTH, start_month.strftime("%m-%Y"))
|
28
|
+
start_month += 1.month
|
29
|
+
end
|
56
30
|
end
|
57
31
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
32
|
+
# Performance data for the last 30 days for a specific authority and action
|
33
|
+
# @param authority_name [String] name of an authority
|
34
|
+
# @param action [Symbol] :search, :fetch, or :all_actions
|
35
|
+
# @returns [Hash] performance statistics for the past 30 days
|
36
|
+
# @example returns
|
37
|
+
# { 0: { day: '07-15-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
38
|
+
# 1: { day: '07-16-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
39
|
+
# 2: { day: '07-17-2019', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
40
|
+
# ...,
|
41
|
+
# 29: { day: 'TODAY', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
42
|
+
# }
|
43
|
+
def calculate_last_30_days(authority_name:, action:)
|
44
|
+
start_day = QaServer::TimeService.current_time.beginning_of_day - 29.days
|
45
|
+
0.upto(29).each_with_object({}) do |idx, averages|
|
46
|
+
records = records_by(authority_name, action, start_day..start_day.end_of_day)
|
47
|
+
averages[idx] = calculate_from_records(records, BY_DAY, performance_by_day_label(idx, start_day))
|
48
|
+
start_day += 1.day
|
68
49
|
end
|
50
|
+
end
|
69
51
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
calculate_last_hour(authority_name, action, avgs)
|
52
|
+
# Performance data for the last 24 hours for a specific authority and action
|
53
|
+
# @param authority_name [String] name of an authority
|
54
|
+
# @param action [Symbol] :search, :fetch, or :all_actions
|
55
|
+
# @returns [Hash] performance statistics for the past 24 hours
|
56
|
+
# @example returns
|
57
|
+
# { 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. }},
|
58
|
+
# 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. }},
|
59
|
+
# 2: { hour: '1600', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
60
|
+
# ...,
|
61
|
+
# 23: { hour: 'NOW', retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
62
|
+
# }
|
63
|
+
def calculate_last_24_hours(authority_name:, action:)
|
64
|
+
start_hour = QaServer::TimeService.current_time.beginning_of_hour - 23.hours
|
65
|
+
0.upto(23).each_with_object({}) do |idx, averages|
|
66
|
+
records = records_by(authority_name, action, start_hour..start_hour.end_of_hour)
|
67
|
+
averages[idx] = calculate_from_records(records, BY_HOUR, performance_by_hour_label(idx, start_hour))
|
68
|
+
start_hour += 1.hour
|
89
69
|
end
|
70
|
+
end
|
90
71
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
72
|
+
# Performance data for the last 24 hours for a specific authority and action
|
73
|
+
# @param authority_name [String] name of an authority
|
74
|
+
# @param action [Symbol] :search, :fetch, or :all_actions
|
75
|
+
# @param averages [Hash] existing data for each hour
|
76
|
+
# @returns [Hash] existing hourly data with the last hour updated
|
77
|
+
# @example returns
|
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
|
+
# 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. }},
|
80
|
+
# 2: { hour: '1600', stats: { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
81
|
+
# ...,
|
82
|
+
# 23: { hour: 'NOW', retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
83
|
+
# }
|
84
|
+
def recalculate_last_hour(authority_name:, action:, averages:)
|
85
|
+
start_hour = QaServer::TimeService.current_time.beginning_of_hour
|
86
|
+
records = records_by(authority_name, action, start_hour..start_hour.end_of_hour)
|
87
|
+
averages[23] = calculate_from_records(records, BY_HOUR, performance_by_hour_label(23, start_hour))
|
88
|
+
averages
|
89
|
+
end
|
109
90
|
|
110
|
-
|
111
|
-
# @param authority_name [String] limit statistics to records for the given authority (default: all authorities)
|
112
|
-
# @param action [Symbol] one of :search, :fetch, :all_actions
|
113
|
-
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
114
|
-
# @returns [Hash] performance statistics for the past 12 months
|
115
|
-
# @example
|
116
|
-
# { 0: { month: '09-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
117
|
-
# 1: { month: '10-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
118
|
-
# 2: { month: '11-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
119
|
-
# ...,
|
120
|
-
# 11: { month: '08-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
121
|
-
# }
|
122
|
-
def average_last_12_months(authority_name: nil, action: nil, force: false)
|
123
|
-
Rails.cache.fetch("QaServer::PerformanceGraphDataService/#{__method__}/#{authority_name || ALL_AUTH}/#{action}/#{FOR_YEAR}",
|
124
|
-
expires_in: QaServer::MonitorCacheService.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
125
|
-
calculate_last_12_months(authority_name, action)
|
126
|
-
end
|
127
|
-
end
|
91
|
+
private
|
128
92
|
|
129
93
|
def records_by(authority_name, action, time_period)
|
130
94
|
where_clause = { dt_stamp: time_period }
|
131
|
-
where_clause[:authority] = authority_name unless authority_name.nil?
|
132
|
-
where_clause[:action] = action unless action.nil? || action ==
|
95
|
+
where_clause[:authority] = authority_name unless authority_name.nil? || authority_name == ALL_AUTH
|
96
|
+
where_clause[:action] = action unless action.nil? || action == ALL_ACTIONS
|
133
97
|
performance_data_class.where(where_clause)
|
134
98
|
end
|
135
99
|
|
@@ -157,47 +121,6 @@ module QaServer
|
|
157
121
|
stats = stats_calculator_class.new(records).calculate_average_stats
|
158
122
|
{ STATS => stats, range_idx => range_label }
|
159
123
|
end
|
160
|
-
|
161
|
-
def calculate_last_hour(authority_name, action, avgs)
|
162
|
-
start_hour = QaServer::TimeService.current_time.beginning_of_hour
|
163
|
-
records = records_by(authority_name, action, start_hour..start_hour.end_of_hour)
|
164
|
-
avgs[23] = calculate_from_records(records, BY_HOUR, performance_by_hour_label(23, start_hour))
|
165
|
-
avgs
|
166
|
-
end
|
167
|
-
|
168
|
-
def calculate_last_24_hours(authority_name, action)
|
169
|
-
start_hour = QaServer::TimeService.current_time.beginning_of_hour - 23.hours
|
170
|
-
0.upto(23).each_with_object({}) do |idx, avgs|
|
171
|
-
records = records_by(authority_name, action, start_hour..start_hour.end_of_hour)
|
172
|
-
avgs[idx] = calculate_from_records(records, BY_HOUR, performance_by_hour_label(idx, start_hour))
|
173
|
-
start_hour += 1.hour
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
def calculate_last_30_days(authority_name, action)
|
178
|
-
start_day = QaServer::TimeService.current_time.beginning_of_day - 29.days
|
179
|
-
0.upto(29).each_with_object({}) do |idx, avgs|
|
180
|
-
records = records_by(authority_name, action, start_day..start_day.end_of_day)
|
181
|
-
avgs[idx] = calculate_from_records(records, BY_DAY, performance_by_day_label(idx, start_day))
|
182
|
-
start_day += 1.day
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def calculate_last_12_months(authority_name, action)
|
187
|
-
start_month = QaServer::TimeService.current_time.beginning_of_month - 11.months
|
188
|
-
0.upto(11).each_with_object({}) do |idx, avgs|
|
189
|
-
records = records_by(authority_name, action, start_month..start_month.end_of_month)
|
190
|
-
avgs[idx] = calculate_from_records(records, BY_MONTH, start_month.strftime("%m-%Y"))
|
191
|
-
start_month += 1.month
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
# @returns [Boolean] true if cache has expired; otherwise, false
|
196
|
-
def cache_expired?
|
197
|
-
expired = Rails.cache.fetch("QaServer::PerformanceGraphDataService/#{__method__}", expires_in: 5.seconds) { true }
|
198
|
-
Rails.cache.fetch("QaServer::PerformanceGraphDataService/#{__method__}", expires_in: QaServer::MonitorCacheService.cache_expiry, force: expired) { false } # reset if expired
|
199
|
-
expired
|
200
|
-
end
|
201
124
|
end
|
202
125
|
end
|
203
126
|
end
|
@@ -9,17 +9,6 @@ module QaServer
|
|
9
9
|
class_attribute :authority_list_class
|
10
10
|
self.authority_list_class = QaServer::AuthorityListerService
|
11
11
|
|
12
|
-
# @param performance_data [Hash] hash of all performance data for all authorities
|
13
|
-
# @see QaServer:PerformanceHistory
|
14
|
-
def create_performance_graphs(performance_data:)
|
15
|
-
QaServer.config.monitor_logger.debug("(QaServer::PerformanceGraphingService##{__method__}) - generating graphs")
|
16
|
-
performance_data.each_key do |auth_name|
|
17
|
-
create_graphs_for_authority(performance_data, auth_name.to_sym, :search)
|
18
|
-
create_graphs_for_authority(performance_data, auth_name.to_sym, :fetch)
|
19
|
-
create_graphs_for_authority(performance_data, auth_name.to_sym, :all_actions)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
12
|
# @param authority_name [String] name of the authority
|
24
13
|
# @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
|
25
14
|
# @param time_period [Symbol] time period for the graph (i.e. :day, :month, :year)
|
@@ -27,45 +16,43 @@ module QaServer
|
|
27
16
|
File.join(graph_relative_path, graph_filename(authority_name, action, time_period))
|
28
17
|
end
|
29
18
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
gruff_data = rework_performance_data_for_gruff(data, BY_HOUR)
|
42
|
-
create_gruff_graph(gruff_data,
|
43
|
-
performance_for_day_graph_full_path(authority_name, action),
|
44
|
-
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
45
|
-
end
|
19
|
+
# Generate one 12 month graph for the authority and action given the graph data.
|
20
|
+
# @param authority_name [String] name of the authority
|
21
|
+
# @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
|
22
|
+
# @param data [Hash] data to use to generate the graph
|
23
|
+
# @see QaServer::PerformanceGraphDataService.calculate_last_12_months
|
24
|
+
def generate_monthly_graph(authority_name: ALL_AUTH, action:, data:)
|
25
|
+
gruff_data = rework_performance_data_for_gruff(data, BY_MONTH)
|
26
|
+
create_gruff_graph(gruff_data,
|
27
|
+
performance_for_year_graph_full_path(authority_name, action),
|
28
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_month'))
|
29
|
+
end
|
46
30
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
31
|
+
# Generate one 30 day graph for the authority and action given the graph data.
|
32
|
+
# @param authority_name [String] name of the authority
|
33
|
+
# @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
|
34
|
+
# @param data [Hash] data to use to generate the graph
|
35
|
+
# @see QaServer::PerformanceGraphDataService.calculate_last_30_days
|
36
|
+
def generate_daily_graph(authority_name: ALL_AUTH, action:, data:)
|
37
|
+
gruff_data = rework_performance_data_for_gruff(data, BY_DAY)
|
38
|
+
create_gruff_graph(gruff_data,
|
39
|
+
performance_for_month_graph_full_path(authority_name, action),
|
40
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_day'))
|
41
|
+
end
|
55
42
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
43
|
+
# Generate one 24 hour graph for the authority and action given the graph data.
|
44
|
+
# @param authority_name [String] name of the authority
|
45
|
+
# @param action [Symbol] action performed by the request (e.g. :search, :fetch, :all_actions)
|
46
|
+
# @param data [Hash] data to use to generate the graph
|
47
|
+
# @see QaServer::PerformanceGraphDataService.calculate_last_24_hours
|
48
|
+
def generate_hourly_graph(authority_name: ALL_AUTH, action:, data:)
|
49
|
+
gruff_data = rework_performance_data_for_gruff(data, BY_HOUR)
|
50
|
+
create_gruff_graph(gruff_data,
|
51
|
+
performance_for_day_graph_full_path(authority_name, action),
|
52
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
53
|
+
end
|
64
54
|
|
65
|
-
|
66
|
-
auth_name = authority_name.nil? ? ALL_AUTH : authority_name
|
67
|
-
data[auth_name][action].key?(time_period) ? data[auth_name][action][time_period] : {}
|
68
|
-
end
|
55
|
+
private
|
69
56
|
|
70
57
|
def performance_for_day_graph_full_path(authority_name, action)
|
71
58
|
graph_full_path(graph_filename(authority_name, action, :day))
|
data/lib/qa_server/version.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
|
-
RSpec.describe QaServer::
|
4
|
+
RSpec.describe QaServer::CacheExpiryService do
|
5
5
|
# rubocop:disable RSpec/MessageChain
|
6
6
|
let(:timezone_name) { 'Eastern Time (US & Canada)' }
|
7
7
|
before { allow(described_class).to receive_message_chain(:config, :preferred_time_zone_name).and_return(timezone_name) }
|