qa_server 5.4.0 → 5.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/CHANGELOG.md +4 -0
- data/app/controllers/qa_server/monitor_status_controller.rb +25 -42
- data/app/models/qa_server/performance_cache.rb +1 -0
- data/app/models/qa_server/performance_history.rb +22 -17
- data/app/models/qa_server/scenario_run_history.rb +56 -36
- data/app/models/qa_server/scenario_run_registry.rb +14 -8
- data/app/models/qa_server/scenario_run_summary.rb +1 -1
- data/app/prepends/prepended_rdf/rdf_graph.rb +4 -4
- data/app/presenters/qa_server/monitor_status/current_status_presenter.rb +1 -1
- data/app/services/qa_server/performance_graph_data_service.rb +70 -36
- data/lib/generators/qa_server/templates/config/initializers/qa_server.rb +5 -0
- data/lib/qa_server/configuration.rb +9 -0
- data/lib/qa_server/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cfe60b29f718a16c9c86b62e0bd7807c746147b1
|
4
|
+
data.tar.gz: 51dc3758debb4b924b7859ca82f9ed49eb3475a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56e1811a7ee5b562a3e24d77fecba594955b5410824863a0745f895b2541d5d735e21c33b29b33047c4cb1d257489dc498d9bdb774f097a74c64954c2c7e0da8
|
7
|
+
data.tar.gz: '084ba6a28a84a2a235c2cb69f2aed5285399ba2e3718135302a5dbf3c297a225407a348cbf6b87ef1705b5cc59016b1bd3ae49a7b0947dda28c215961f9e0f9a'
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -13,9 +13,7 @@ module QaServer
|
|
13
13
|
|
14
14
|
# Sets up presenter with data to display in the UI
|
15
15
|
def index
|
16
|
-
|
17
|
-
historical_data = refresh_history
|
18
|
-
performance_data = refresh_performance
|
16
|
+
latest_run
|
19
17
|
@presenter = presenter_class.new(current_summary: latest_summary,
|
20
18
|
current_failure_data: latest_failures,
|
21
19
|
historical_summary_data: historical_data,
|
@@ -25,49 +23,39 @@ module QaServer
|
|
25
23
|
|
26
24
|
private
|
27
25
|
|
26
|
+
# Sets @latest_run [QaServer::ScenarioRunRegistry]
|
28
27
|
def latest_run
|
29
|
-
|
28
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: refresh_tests?) do
|
29
|
+
Rails.logger.info("#{self.class}##{__method__} - Running Tests - cache expired or refresh requested (#{refresh_tests?})")
|
30
|
+
validate(authorities_list)
|
31
|
+
scenario_run_registry_class.save_run(scenarios_results: status_log.to_a)
|
32
|
+
scenario_run_registry_class.latest_run
|
33
|
+
end
|
30
34
|
end
|
31
35
|
|
36
|
+
# Sets @latest_summary [QaServer::ScenarioRunSummary]
|
32
37
|
def latest_summary
|
33
|
-
|
38
|
+
scenario_history_class.run_summary(scenario_run: latest_run, force: refresh_tests?)
|
34
39
|
end
|
35
40
|
|
36
41
|
def latest_failures
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def update_summary_and_data
|
41
|
-
scenario_run_registry_class.save_run(scenarios_results: status_log.to_a)
|
42
|
-
@latest_summary = nil # reset so next request recalculates
|
43
|
-
@latest_failures = nil # reset so next request recalculates
|
42
|
+
scenario_history_class.run_failures(run_id: latest_run.id, force: refresh_tests?)
|
44
43
|
end
|
45
44
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def historical_summary_data(refresh: false)
|
51
|
-
# TODO: Make this refresh the same way performance data refreshes.
|
52
|
-
# Requires historical graph to move out of presenter so it can be created here only with refresh.
|
53
|
-
if refresh
|
54
|
-
@historical_summary_data = scenario_history_class.historical_summary
|
55
|
-
# TODO: Need to recreate graph here. And need to only read the graph in presenter.
|
56
|
-
end
|
57
|
-
@historical_summary_data ||= scenario_history_class.historical_summary
|
45
|
+
# Sets @historical_data [Array<Hash>]
|
46
|
+
def historical_data
|
47
|
+
scenario_history_class.historical_summary(force: refresh_history?)
|
58
48
|
end
|
59
49
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@performance_data = nil if refresh
|
64
|
-
@performance_data ||= performance_history_class.performance_data(datatype: datatype)
|
50
|
+
# Sets @performance_data [Hash<Hash>]
|
51
|
+
def performance_data
|
52
|
+
performance_history_class.performance_data(datatype: performance_datatype, force: refresh_performance?)
|
65
53
|
end
|
66
54
|
|
67
|
-
def performance_datatype
|
68
|
-
return :all if display_performance_datatable? && display_performance_graph?
|
55
|
+
def performance_datatype
|
56
|
+
return :all if display_performance_datatable? && display_performance_graph?
|
69
57
|
return :datatable if display_performance_datatable?
|
70
|
-
return :graph if display_performance_graph?
|
58
|
+
return :graph if display_performance_graph?
|
71
59
|
:none
|
72
60
|
end
|
73
61
|
|
@@ -79,12 +67,6 @@ module QaServer
|
|
79
67
|
@display_performance_graph ||= QaServer.config.display_performance_graph?
|
80
68
|
end
|
81
69
|
|
82
|
-
def refresh_tests
|
83
|
-
return unless refresh_tests?
|
84
|
-
validate(authorities_list)
|
85
|
-
update_summary_and_data
|
86
|
-
end
|
87
|
-
|
88
70
|
def refresh_history
|
89
71
|
historical_summary_data(refresh: refresh_history?)
|
90
72
|
end
|
@@ -98,12 +80,13 @@ module QaServer
|
|
98
80
|
end
|
99
81
|
|
100
82
|
def refresh_all?
|
83
|
+
return false unless refresh?
|
101
84
|
params[:refresh].nil? || params[:refresh].casecmp?('all') # nil is for backward compatibility
|
102
85
|
end
|
103
86
|
|
104
87
|
def refresh_tests?
|
105
|
-
return false unless refresh?
|
106
|
-
refresh_all? || params[:refresh].casecmp?('tests')
|
88
|
+
return false unless refresh?
|
89
|
+
refresh_all? || params[:refresh].casecmp?('tests')
|
107
90
|
end
|
108
91
|
|
109
92
|
def refresh_history?
|
@@ -112,8 +95,8 @@ module QaServer
|
|
112
95
|
end
|
113
96
|
|
114
97
|
def refresh_performance?
|
115
|
-
return false unless refresh?
|
116
|
-
refresh_all? || params[:refresh].casecmp?('performance')
|
98
|
+
return false unless refresh?
|
99
|
+
refresh_all? || params[:refresh].casecmp?('performance')
|
117
100
|
end
|
118
101
|
end
|
119
102
|
end
|
@@ -64,10 +64,10 @@ module QaServer
|
|
64
64
|
# },
|
65
65
|
# AGROVOC_LD4L_CACHE: { ... # same data for each authority }
|
66
66
|
# }
|
67
|
-
def performance_data(datatype: :datatable)
|
67
|
+
def performance_data(datatype: :datatable, force: false)
|
68
68
|
return if datatype == :none
|
69
69
|
QaServer.config.performance_cache.write_all
|
70
|
-
data = calculate_data(datatype)
|
70
|
+
data = calculate_data(datatype, force: force)
|
71
71
|
graphing_service_class.create_performance_graphs(performance_data: data) if calculate_graphdata? datatype
|
72
72
|
data
|
73
73
|
end
|
@@ -82,23 +82,23 @@ module QaServer
|
|
82
82
|
datatype == :graph || datatype == :all
|
83
83
|
end
|
84
84
|
|
85
|
-
def calculate_data(datatype)
|
85
|
+
def calculate_data(datatype, force:)
|
86
86
|
data = {}
|
87
87
|
auths = authority_list_class.authorities_list
|
88
|
-
data[ALL_AUTH] = data_for_authority(datatype: datatype)
|
89
|
-
auths.each { |auth_name| data[auth_name] = data_for_authority(authority_name: auth_name, datatype: datatype) }
|
88
|
+
data[ALL_AUTH] = data_for_authority(datatype: datatype, force: force)
|
89
|
+
auths.each { |auth_name| data[auth_name] = data_for_authority(authority_name: auth_name, datatype: datatype, force: force) }
|
90
90
|
data
|
91
91
|
end
|
92
92
|
|
93
|
-
def data_for_authority(authority_name: nil, datatype:)
|
93
|
+
def data_for_authority(authority_name: nil, datatype:, force:)
|
94
94
|
action_data = {}
|
95
95
|
[:search, :fetch, :all_actions].each do |action|
|
96
96
|
data = {}
|
97
|
-
data[FOR_DATATABLE] = data_table_stats(authority_name, action) if calculate_datatable?(datatype)
|
97
|
+
data[FOR_DATATABLE] = data_table_stats(authority_name, action, force: force) if calculate_datatable?(datatype)
|
98
98
|
if calculate_graphdata?(datatype)
|
99
|
-
data[FOR_DAY] = graph_data_service_class.average_last_24_hours(authority_name: authority_name, action: action)
|
100
|
-
data[FOR_MONTH] = graph_data_service_class.average_last_30_days(authority_name: authority_name, action: action)
|
101
|
-
data[FOR_YEAR] = graph_data_service_class.average_last_12_months(authority_name: authority_name, action: action)
|
99
|
+
data[FOR_DAY] = graph_data_service_class.average_last_24_hours(authority_name: authority_name, action: action, force: force)
|
100
|
+
data[FOR_MONTH] = graph_data_service_class.average_last_30_days(authority_name: authority_name, action: action, force: force)
|
101
|
+
data[FOR_YEAR] = graph_data_service_class.average_last_12_months(authority_name: authority_name, action: action, force: force)
|
102
102
|
end
|
103
103
|
action_data[action] = data
|
104
104
|
end
|
@@ -106,18 +106,23 @@ module QaServer
|
|
106
106
|
end
|
107
107
|
|
108
108
|
# Get statistics for all available data.
|
109
|
-
# @param [String]
|
109
|
+
# @param auth_name [String] limit statistics to records for the given authority (default: all authorities)
|
110
|
+
# @param action [Symbol] one of :search, :fetch, :all_actions
|
111
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
110
112
|
# @returns [Hash] performance statistics for the datatable during the expected time period
|
111
113
|
# @example
|
112
114
|
# { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
|
113
115
|
# retrieve_10th_ms: 12.3, graph_load_10th_ms: 12.3, normalization_10th_ms: 4.2, full_request_10th_ms: 16.5,
|
114
116
|
# retrieve_90th_ms: 12.3, graph_load_90th_ms: 12.3, normalization_90th_ms: 4.2, full_request_90th_ms: 16.5 }
|
115
|
-
def data_table_stats(auth_name, action)
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
117
|
+
def data_table_stats(auth_name, action, force:)
|
118
|
+
Rails.cache.fetch("#{self.class}/#{__method__}/#{auth_name || ALL_AUTH}/#{action}/#{FOR_DATATABLE}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
119
|
+
Rails.logger.info("#{self.class}##{__method__} - calculating performance datatable stats - cache expired or refresh requested (#{force})")
|
120
|
+
records = records_for_last_24_hours(auth_name) ||
|
121
|
+
records_for_last_30_days(auth_name) ||
|
122
|
+
records_for_last_12_months(auth_name) ||
|
123
|
+
all_records(auth_name)
|
124
|
+
stats_calculator_class.new(records, action: action).calculate_stats(avg: true, low: true, high: true)
|
125
|
+
end
|
121
126
|
end
|
122
127
|
|
123
128
|
def expected_time_period
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
# Provide access to the scenario_results_history database table which tracks specific scenario runs over time.
|
3
3
|
module QaServer
|
4
|
-
class ScenarioRunHistory < ActiveRecord::Base
|
4
|
+
class ScenarioRunHistory < ActiveRecord::Base # rubocop:disable Metrics/ClassLength
|
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
|
@@ -31,24 +31,28 @@ module QaServer
|
|
31
31
|
end
|
32
32
|
|
33
33
|
# Get a summary of passing/failing tests for a run.
|
34
|
-
# @param scenario_run [ScenarioRunRegistry] the run on which to gather statistics
|
35
|
-
# @
|
36
|
-
# @
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
42
|
-
#
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
34
|
+
# @param scenario_run [QaServer::ScenarioRunRegistry] the run on which to gather statistics
|
35
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
36
|
+
# @returns [QaServer::ScenarioRunSummary] statistics on the requested run
|
37
|
+
# @example ScenarioRunSummary includes methods for accessing
|
38
|
+
# * run_id: 14,
|
39
|
+
# * run_dt_stamp:
|
40
|
+
# * authority_count: 22,
|
41
|
+
# * failing_authority_count: 1
|
42
|
+
# * passing_scenario_count: 156,
|
43
|
+
# * failing_scenario_count: 3,
|
44
|
+
# * total_scenario_count: 159,
|
45
|
+
def self.run_summary(scenario_run:, force: false)
|
46
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
47
|
+
Rails.logger.info("#{self.class}##{__method__} - creating summary of latest run - cache expired or refresh requested (#{force})")
|
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'])
|
55
|
+
end
|
52
56
|
end
|
53
57
|
|
54
58
|
# Get set of all scenario results for a run.
|
@@ -85,6 +89,7 @@ module QaServer
|
|
85
89
|
# err_message: "Not enough search results returned",
|
86
90
|
# scenario_type: :connection
|
87
91
|
# run_time: 0.123 } ]
|
92
|
+
# @deprecated Not used anywhere. Being removed.
|
88
93
|
def self.run_results(run_id:, authority_name: nil, status: nil, url: nil)
|
89
94
|
return [] unless run_id
|
90
95
|
where = {}
|
@@ -94,9 +99,11 @@ module QaServer
|
|
94
99
|
where[:url] = url if url.present?
|
95
100
|
QaServer::ScenarioRunHistory.where(where).to_a
|
96
101
|
end
|
102
|
+
deprecation_deprecate run_results: "Not used anywhere. Being removed."
|
97
103
|
|
98
104
|
# Get set of failures for a run, if any.
|
99
105
|
# @param run_id [Integer] the run on which to gather statistics
|
106
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
100
107
|
# @returns [Array<Hash>] scenario details for any failing scenarios in the run
|
101
108
|
# @example
|
102
109
|
# [ { status: :bad,
|
@@ -117,32 +124,43 @@ module QaServer
|
|
117
124
|
# err_message: "Not enough search results returned",
|
118
125
|
# scenario_type: :connection
|
119
126
|
# run_time: 0.123 } ]
|
120
|
-
def self.run_failures(run_id:)
|
127
|
+
def self.run_failures(run_id:, force: false)
|
121
128
|
return [] unless run_id
|
122
|
-
|
129
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
130
|
+
Rails.logger.info("#{self.class}##{__method__} - finding failures in latest run - cache expired or refresh requested (#{force})")
|
131
|
+
QaServer::ScenarioRunHistory.where(scenario_run_registry_id: run_id).where.not(status: :good).to_a
|
132
|
+
end
|
123
133
|
end
|
124
134
|
|
125
135
|
# Get a summary level of historical data
|
126
|
-
# @returns [Array<
|
127
|
-
# @example
|
136
|
+
# @returns [Array<Array>] summary of passing/failing tests for each authority
|
137
|
+
# @example [auth_name, failing, passing]
|
128
138
|
# [ [ 'agrovoc', 0, 24 ],
|
129
139
|
# [ 'geonames_ld4l_cache', 2, 22 ] ... ]
|
130
|
-
def self.historical_summary
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
data << auth_data
|
140
|
+
def self.historical_summary(force: false)
|
141
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
142
|
+
Rails.logger.info("#{self.class}##{__method__} - calculating pass/fail per authority across all time - cache expired or refresh requested (#{force})")
|
143
|
+
runs = all_runs_per_authority
|
144
|
+
failures = failing_runs_per_authority
|
145
|
+
return [] unless runs.present?
|
146
|
+
data = []
|
147
|
+
runs.each do |auth_name, run_count|
|
148
|
+
data << pass_fail_stats_for_authority(failures, auth_name, run_count)
|
149
|
+
end
|
150
|
+
data
|
142
151
|
end
|
143
|
-
data
|
144
152
|
end
|
145
153
|
|
154
|
+
def self.pass_fail_stats_for_authority(failures, auth_name, run_count)
|
155
|
+
auth_data = []
|
156
|
+
auth_data[0] = auth_name
|
157
|
+
failure_count = failures.key?(auth_name) ? failures[auth_name] : 0
|
158
|
+
auth_data[1] = failure_count
|
159
|
+
auth_data[2] = run_count - failure_count # passing
|
160
|
+
auth_data
|
161
|
+
end
|
162
|
+
private_class_method :pass_fail_stats_for_authority
|
163
|
+
|
146
164
|
def self.authorities_in_run(run_id:)
|
147
165
|
QaServer::ScenarioRunHistory.where(scenario_run_registry_id: run_id).pluck(:authority_name).uniq
|
148
166
|
end
|
@@ -153,6 +171,8 @@ module QaServer
|
|
153
171
|
end
|
154
172
|
private_class_method :authorities_with_failures_in_run
|
155
173
|
|
174
|
+
# @return [Hash] status counts across all authorities (used for current test summary)
|
175
|
+
# @example { "good" => 23, "bad" => 3, "unknown" => 0 }
|
156
176
|
def self.status_counts_in_run(run_id:)
|
157
177
|
status = QaServer::ScenarioRunHistory.group('status').where(scenario_run_registry_id: run_id).count
|
158
178
|
status["good"] = 0 unless status.key? "good"
|
@@ -5,7 +5,7 @@ module QaServer
|
|
5
5
|
self.table_name = 'scenario_run_registry'
|
6
6
|
has_many :scenario_run_history, foreign_key: :scenario_run_registry_id
|
7
7
|
|
8
|
-
#
|
8
|
+
# @return [ScenarioRunRegistry] registry data for latest run (e.g. id, dt_stamp)
|
9
9
|
def self.latest_run
|
10
10
|
return nil unless QaServer::ScenarioRunRegistry.last
|
11
11
|
QaServer::ScenarioRunRegistry.last # Can we count on last to always be the one with the latest dt_stamp?
|
@@ -14,21 +14,27 @@ module QaServer
|
|
14
14
|
# latest_run.id
|
15
15
|
end
|
16
16
|
|
17
|
-
#
|
17
|
+
# @return [Integer] id for latest test run
|
18
|
+
# @deprecated Not used anywhere. Being removed.
|
18
19
|
def self.latest_run_id
|
19
20
|
latest = latest_run
|
20
21
|
return nil unless latest
|
21
22
|
lastest.id
|
22
23
|
end
|
24
|
+
deprecation_deprecate latest_run_id: "Not used anywhere. Being removed."
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
# @return [String] datetime stamp of first registered run
|
27
|
+
def self.first_run_dt
|
28
|
+
Rails.cache.fetch("#{self.class}/#{__method__}", expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour) do
|
29
|
+
QaServer::ScenarioRunRegistry.first.dt_stamp.in_time_zone("Eastern Time (US & Canada)").strftime("%m/%d/%y - %I:%M %p")
|
30
|
+
end
|
27
31
|
end
|
28
32
|
|
29
|
-
|
30
|
-
|
33
|
+
# Register and save latest test run results
|
34
|
+
# @param scenarios_results [Array<Hash>] results of latest test run
|
35
|
+
def self.save_run(scenarios_results:)
|
36
|
+
run = QaServer::ScenarioRunRegistry.create(dt_stamp: QaServer.current_time)
|
37
|
+
scenarios_results.each { |result| QaServer::ScenarioRunHistory.save_result(run_id: run.id, scenario_result: result) }
|
31
38
|
end
|
32
|
-
private_class_method :dt_stamp_now_et
|
33
39
|
end
|
34
40
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
#
|
2
|
+
# Holds test run summary data providing methods for accessing each data point.
|
3
3
|
module QaServer
|
4
4
|
class ScenarioRunSummary
|
5
5
|
# @return [Integer] the id of the scenario run being summarized
|
@@ -17,15 +17,15 @@ module PrependedRdf::RdfGraph
|
|
17
17
|
raise TypeError, "#{self} is immutable" if immutable?
|
18
18
|
phid, real_url = parse_phid(url)
|
19
19
|
performance_udpates = {}
|
20
|
-
start_time_s =
|
20
|
+
start_time_s = QaServer.current_time_s
|
21
21
|
|
22
22
|
reader = RDF::Reader.open(real_url, { base_uri: real_url }.merge(options))
|
23
23
|
|
24
|
-
end_time_s =
|
24
|
+
end_time_s = QaServer.current_time_s
|
25
25
|
performance_udpates[:retrieve_time_ms] = (end_time_s - start_time_s) * 1000
|
26
26
|
QaServer.config.performance_tracker.write "#{format('%.6f', end_time_s - start_time_s)}, " # read data
|
27
27
|
|
28
|
-
start_time_s =
|
28
|
+
start_time_s = QaServer.current_time_s
|
29
29
|
|
30
30
|
if graph_name
|
31
31
|
statements = []
|
@@ -40,7 +40,7 @@ module PrependedRdf::RdfGraph
|
|
40
40
|
nil
|
41
41
|
end
|
42
42
|
|
43
|
-
end_time_s =
|
43
|
+
end_time_s = QaServer.current_time_s
|
44
44
|
performance_udpates[:graph_load_time_ms] = (end_time_s - start_time_s) * 1000
|
45
45
|
QaServer.config.performance_cache.update(id: phid, updates: performance_udpates)
|
46
46
|
QaServer.config.performance_tracker.write "#{format('%.6f', end_time_s - start_time_s)}, " # load graph
|
@@ -16,7 +16,7 @@ module QaServer::MonitorStatus
|
|
16
16
|
|
17
17
|
# @return [String] date of first recorded test run
|
18
18
|
def first_updated
|
19
|
-
QaServer::ScenarioRunRegistry.
|
19
|
+
QaServer::ScenarioRunRegistry.first_run_dt
|
20
20
|
end
|
21
21
|
|
22
22
|
# @return [Integer] number of loaded authorities
|
@@ -10,6 +10,9 @@ module QaServer
|
|
10
10
|
self.performance_data_class = QaServer::PerformanceHistory
|
11
11
|
|
12
12
|
# Get hourly average for the past 24 hours.
|
13
|
+
# @param authority_name [String] limit statistics to records for the given authority (default: all authorities)
|
14
|
+
# @param action [Symbol] one of :search, :fetch, :all_actions
|
15
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
13
16
|
# @returns [Hash] performance statistics for the past 24 hours
|
14
17
|
# @example
|
15
18
|
# { 0: { hour: '1400', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
@@ -18,22 +21,19 @@ module QaServer
|
|
18
21
|
# ...,
|
19
22
|
# 23: { hour: 'NOW', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
20
23
|
# }
|
21
|
-
def average_last_24_hours(authority_name: nil, action: nil)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
data = {}
|
28
|
-
data[BY_HOUR] = performance_by_hour_label(idx, start_hour)
|
29
|
-
data[STATS] = stats
|
30
|
-
avgs[idx] = data
|
31
|
-
start_hour += 1.hour
|
24
|
+
def average_last_24_hours(authority_name: nil, action: nil, force: false)
|
25
|
+
Rails.cache.fetch("#{self.class}/#{__method__}/#{authority_name || ALL_AUTH}/#{action}/#{FOR_DAY}",
|
26
|
+
expires_in: QaServer.current_time.end_of_hour - QaServer.current_time,
|
27
|
+
race_condition_ttl: 1.hour, force: force) do
|
28
|
+
Rails.logger.info("#{self.class}##{__method__} - calculating performance stats for last 24 hours - cache expired or refresh requested (#{force})")
|
29
|
+
calculate_last_24_hours(authority_name, action)
|
32
30
|
end
|
33
|
-
avgs
|
34
31
|
end
|
35
32
|
|
36
33
|
# Get daily average for the past 30 days.
|
34
|
+
# @param authority_name [String] limit statistics to records for the given authority (default: all authorities)
|
35
|
+
# @param action [Symbol] one of :search, :fetch, :all_actions
|
36
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
37
37
|
# @returns [Hash] performance statistics for the past 30 days
|
38
38
|
# @example
|
39
39
|
# { 0: { day: '07-15-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
@@ -42,22 +42,18 @@ module QaServer
|
|
42
42
|
# ...,
|
43
43
|
# 29: { day: 'TODAY', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
44
44
|
# }
|
45
|
-
def average_last_30_days(authority_name: nil, action: nil)
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
|
51
|
-
data = {}
|
52
|
-
data[BY_DAY] = performance_by_day_label(idx, start_day)
|
53
|
-
data[STATS] = stats
|
54
|
-
avgs[idx] = data
|
55
|
-
start_day += 1.day
|
45
|
+
def average_last_30_days(authority_name: nil, action: nil, force: false)
|
46
|
+
Rails.cache.fetch("#{self.class}/#{__method__}/#{authority_name || ALL_AUTH}/#{action}/#{FOR_MONTH}",
|
47
|
+
expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
48
|
+
Rails.logger.info("#{self.class}##{__method__} - calculating performance stats for last 30 days - cache expired or refresh requested (#{force})")
|
49
|
+
calculate_last_30_days(authority_name, action)
|
56
50
|
end
|
57
|
-
avgs
|
58
51
|
end
|
59
52
|
|
60
53
|
# Get daily average for the past 12 months.
|
54
|
+
# @param authority_name [String] limit statistics to records for the given authority (default: all authorities)
|
55
|
+
# @param action [Symbol] one of :search, :fetch, :all_actions
|
56
|
+
# @param force [Boolean] if true, forces cache to regenerate; otherwise, returns value from cache unless expired
|
61
57
|
# @returns [Hash] performance statistics for the past 12 months
|
62
58
|
# @example
|
63
59
|
# { 0: { month: '09-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }},
|
@@ -66,19 +62,12 @@ module QaServer
|
|
66
62
|
# ...,
|
67
63
|
# 11: { month: '08-2019', stats: { load_avg_ms: 12.3, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5, etc. }}
|
68
64
|
# }
|
69
|
-
def average_last_12_months(authority_name: nil, action: nil)
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
|
75
|
-
data = {}
|
76
|
-
data[BY_MONTH] = start_month.strftime("%m-%Y")
|
77
|
-
data[STATS] = stats
|
78
|
-
avgs[idx] = data
|
79
|
-
start_month += 1.month
|
65
|
+
def average_last_12_months(authority_name: nil, action: nil, force: false)
|
66
|
+
Rails.cache.fetch("#{self.class}/#{__method__}/#{authority_name || ALL_AUTH}/#{action}/#{FOR_YEAR}",
|
67
|
+
expires_in: QaServer.cache_expiry, race_condition_ttl: 1.hour, force: force) do
|
68
|
+
Rails.logger.info("#{self.class}##{__method__} - calculating performance stats for last 12 months - cache expired or refresh requested (#{force})")
|
69
|
+
calculate_last_12_months(authority_name, action)
|
80
70
|
end
|
81
|
-
avgs
|
82
71
|
end
|
83
72
|
|
84
73
|
private
|
@@ -109,6 +98,51 @@ module QaServer
|
|
109
98
|
""
|
110
99
|
end
|
111
100
|
end
|
101
|
+
|
102
|
+
def calculate_last_24_hours(authority_name, action)
|
103
|
+
start_hour = QaServer.current_time.beginning_of_hour - 23.hours
|
104
|
+
avgs = {}
|
105
|
+
0.upto(23).each do |idx|
|
106
|
+
records = records_by(authority_name, action, start_hour..start_hour.end_of_hour)
|
107
|
+
stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
|
108
|
+
data = {}
|
109
|
+
data[BY_HOUR] = performance_by_hour_label(idx, start_hour)
|
110
|
+
data[STATS] = stats
|
111
|
+
avgs[idx] = data
|
112
|
+
start_hour += 1.hour
|
113
|
+
end
|
114
|
+
avgs
|
115
|
+
end
|
116
|
+
|
117
|
+
def calculate_last_30_days(authority_name, action)
|
118
|
+
start_day = QaServer.current_time.beginning_of_day - 29.days
|
119
|
+
avgs = {}
|
120
|
+
0.upto(29).each do |idx|
|
121
|
+
records = records_by(authority_name, action, start_day..start_day.end_of_day)
|
122
|
+
stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
|
123
|
+
data = {}
|
124
|
+
data[BY_DAY] = performance_by_day_label(idx, start_day)
|
125
|
+
data[STATS] = stats
|
126
|
+
avgs[idx] = data
|
127
|
+
start_day += 1.day
|
128
|
+
end
|
129
|
+
avgs
|
130
|
+
end
|
131
|
+
|
132
|
+
def calculate_last_12_months(authority_name, action)
|
133
|
+
start_month = QaServer.current_time.beginning_of_month - 11.months
|
134
|
+
avgs = {}
|
135
|
+
0.upto(11).each do |idx|
|
136
|
+
records = records_by(authority_name, action, start_month..start_month.end_of_month)
|
137
|
+
stats = stats_calculator_class.new(records).calculate_stats(avg: true, full: false)
|
138
|
+
data = {}
|
139
|
+
data[BY_MONTH] = start_month.strftime("%m-%Y")
|
140
|
+
data[STATS] = stats
|
141
|
+
avgs[idx] = data
|
142
|
+
start_month += 1.month
|
143
|
+
end
|
144
|
+
avgs
|
145
|
+
end
|
112
146
|
end
|
113
147
|
end
|
114
148
|
end
|
@@ -73,4 +73,9 @@ QaServer.config do |config|
|
|
73
73
|
# impact and may need to be suppressed. Performance stats will not be gathered when this config is true.
|
74
74
|
# @param [Boolean] do not gather performance data when true (defaults to false for backward compatibitily)
|
75
75
|
# config.suppress_performance_gathering = false
|
76
|
+
|
77
|
+
# Performance data is gathered on every incoming query. Basic stats are logged from QA. Full stats are logged
|
78
|
+
# by QaServer and can eat up logging realestate. To suppress the logging of details, set this config to true.
|
79
|
+
# @param [Boolean] do not log performance data details when true (defaults to false for backward compatibitily)
|
80
|
+
# config.suppress_logging_performance_datails = false
|
76
81
|
end
|
@@ -179,6 +179,15 @@ module QaServer
|
|
179
179
|
@suppress_performance_gathering ||= false
|
180
180
|
end
|
181
181
|
|
182
|
+
# Performance data is gathered on every incoming query. Basic stats are logged from QA. Full stats are logged
|
183
|
+
# by QaServer and can eat up logging realestate. To suppress the logging of details, set this config to true.
|
184
|
+
# @param [Boolean] do not log performance data details when true (defaults to false for backward compatibitily)
|
185
|
+
attr_writer :suppress_logging_performance_datails
|
186
|
+
def suppress_logging_performance_datails
|
187
|
+
@suppress_logging_performance_datails ||= false
|
188
|
+
end
|
189
|
+
|
190
|
+
# TODO: consider refactor performance caching to use Rails cache
|
182
191
|
def performance_cache
|
183
192
|
@performance_cache ||= QaServer::PerformanceCache.new
|
184
193
|
end
|
data/lib/qa_server/version.rb
CHANGED
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: 5.
|
4
|
+
version: 5.5.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-01-
|
11
|
+
date: 2020-01-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|