qa_server 6.2.0 → 7.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/app/cache_processors/concerns/qa_server/cache_keys.rb +15 -0
- data/app/cache_processors/qa_server/cache_expiry_service.rb +33 -0
- data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +60 -0
- data/app/cache_processors/qa_server/performance_datatable_cache.rb +33 -0
- data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +65 -0
- data/app/cache_processors/qa_server/performance_monthly_graph_cache.rb +60 -0
- data/app/cache_processors/qa_server/scenario_history_cache.rb +35 -0
- data/app/cache_processors/qa_server/scenario_run_cache.rb +28 -0
- data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +51 -0
- data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +40 -0
- data/app/controllers/qa_server/monitor_status_controller.rb +39 -48
- data/app/jobs/qa_server/monitor_tests_job.rb +1 -1
- data/app/models/qa_server/scenario_run_history.rb +27 -84
- data/app/models/qa_server/scenario_run_registry.rb +1 -1
- data/app/services/qa_server/performance_datatable_service.rb +6 -9
- data/app/services/qa_server/performance_graph_data_service.rb +77 -154
- data/app/services/qa_server/performance_graphing_service.rb +34 -47
- data/lib/qa_server/version.rb +1 -1
- data/spec/{services/qa_server/monitor_cache_service_spec.rb → cache_processors/qa_server/cache_expiry_service_spec.rb} +1 -1
- metadata +15 -6
- data/app/services/qa_server/monitor_cache_service.rb +0 -22
- /data/app/{models → cache_processors}/qa_server/performance_cache.rb +0 -0
@@ -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) }
|