qa_server 7.2.0 → 7.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop_fixme.yml +6 -0
- data/.travis.yml +4 -5
- data/CHANGELOG.md +38 -0
- data/Rakefile +1 -1
- data/app/assets/stylesheets/qa_server/_check-status.scss +36 -0
- data/app/cache_processors/concerns/qa_server/cache_keys.rb +0 -5
- data/app/cache_processors/qa_server/cache_expiry_service.rb +13 -8
- data/app/cache_processors/qa_server/job_id_cache.rb +29 -0
- data/app/cache_processors/qa_server/performance_cache.rb +34 -34
- data/app/cache_processors/qa_server/performance_day_graph_cache.rb +27 -0
- data/app/cache_processors/qa_server/performance_month_graph_cache.rb +27 -0
- data/app/cache_processors/qa_server/performance_year_graph_cache.rb +27 -0
- data/app/cache_processors/qa_server/scenario_history_cache.rb +7 -7
- data/app/cache_processors/qa_server/scenario_history_graph_cache.rb +12 -17
- data/app/cache_processors/qa_server/scenario_run_cache.rb +8 -8
- data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +7 -7
- data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +7 -7
- data/app/controllers/concerns/qa_server/authority_validation_behavior.rb +49 -44
- data/app/controllers/qa_server/check_status_controller.rb +92 -22
- data/app/controllers/qa_server/fetch_controller.rb +36 -36
- data/app/controllers/qa_server/monitor_status_controller.rb +105 -105
- data/app/jobs/qa_server/history_graph_job.rb +28 -0
- data/app/jobs/qa_server/monitor_tests_job.rb +19 -39
- data/app/jobs/qa_server/performance_day_graph_job.rb +45 -0
- data/app/jobs/qa_server/performance_month_graph_job.rb +45 -0
- data/app/jobs/qa_server/performance_per_byte_job.rb +85 -0
- data/app/jobs/qa_server/performance_year_graph_job.rb +45 -0
- data/app/loggers/qa_server/scenario_logger.rb +74 -4
- data/app/models/concerns/qa_server/performance_history_data_keys.rb +8 -0
- data/app/models/qa_server/authority_scenario.rb +4 -4
- data/app/models/qa_server/authority_status.rb +2 -2
- data/app/models/qa_server/authority_status_failure.rb +1 -1
- data/app/models/qa_server/performance_history.rb +2 -2
- data/app/models/qa_server/scenario_run_history.rb +52 -52
- data/app/models/qa_server/scenario_run_registry.rb +2 -2
- data/app/models/qa_server/scenarios.rb +26 -26
- data/app/models/qa_server/search_scenario.rb +18 -13
- data/app/models/qa_server/term_scenario.rb +29 -29
- data/app/prepends/prepended_linked_data/find_term.rb +40 -40
- data/app/prepends/prepended_linked_data/search_query.rb +36 -36
- data/app/prepends/prepended_rdf/rdf_graph.rb +7 -7
- data/app/presenters/concerns/qa_server/monitor_status/performance_datatable_behavior.rb +32 -32
- data/app/presenters/concerns/qa_server/monitor_status/performance_graph_behavior.rb +64 -64
- data/app/presenters/qa_server/check_status_presenter.rb +63 -7
- data/app/services/concerns/qa_server/gruff_graph.rb +16 -16
- data/app/services/qa_server/authority_loader_service.rb +14 -14
- data/app/services/qa_server/authority_validator_service.rb +1 -0
- data/app/services/qa_server/database_migrator.rb +14 -14
- data/app/services/qa_server/history_graphing_service.rb +30 -30
- data/app/services/qa_server/performance_calculator_service.rb +80 -80
- data/app/services/qa_server/performance_datatable_service.rb +35 -35
- data/app/services/qa_server/performance_graph_data_service.rb +28 -28
- data/app/services/qa_server/performance_graphing_service.rb +58 -58
- data/app/services/qa_server/performance_per_byte_calculator_service.rb +88 -0
- data/app/services/qa_server/performance_per_byte_data_service.rb +41 -0
- data/app/services/qa_server/scenarios_loader_service.rb +1 -1
- data/app/services/qa_server/time_period_service.rb +21 -21
- data/app/validators/qa_server/scenario_validator.rb +99 -87
- data/app/validators/qa_server/search_scenario_validator.rb +67 -61
- data/app/validators/qa_server/term_scenario_validator.rb +20 -15
- data/app/views/qa_server/check_status/index.html.erb +120 -24
- data/config/i18n-tasks.yml +133 -0
- data/config/locales/qa_server.en.yml +15 -0
- data/lib/generators/qa_server/assets_generator.rb +4 -4
- data/lib/generators/qa_server/templates/config/authorities/linked_data/cerl_ld4l_cache.json +2 -2
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +62 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +28 -4
- data/lib/generators/qa_server/templates/config/authorities/linked_data/isni_ld4l_cache.json +90 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/ligatus_ld4l_cache.json +133 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo2_ld4l_cache.json +248 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo3_ld4l_cache.json +248 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locvocabs_ld4l_cache.json +117 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_nlm_ld4l_cache.json +135 -3
- data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +1 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +1 -4
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +31 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +31 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/cerl_ld4l_cache_validation.yml +23 -11
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +33 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +35 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +58 -5
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +256 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +35 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +37 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/isni_ld4l_cache_validation.yml +10 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/ligatus_ld4l_cache_validation.yml +36 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locdemographics_ld4l_cache_validation.yml +73 -44
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +31 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +71 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo_ld4l_cache_validation.yml +70 -2
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locperformance_ld4l_cache_validation.yml +6 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +32 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locvocabs_ld4l_cache_validation.yml +184 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_nlm_ld4l_cache_validation.yml +51 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +37 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +71 -5
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +66 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +57 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/rda_registry_ld4l_cache_validation.yml +310 -0
- data/lib/qa_server/configuration.rb +28 -24
- data/lib/qa_server/version.rb +1 -1
- data/qa_server.gemspec +2 -1
- data/spec/feature/accuracy_spec.rb +32 -0
- data/spec/i18n_spec.rb +36 -0
- data/spec/spec_helper.rb +4 -0
- metadata +46 -12
- data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +0 -60
- data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +0 -65
- data/app/cache_processors/qa_server/performance_monthly_graph_cache.rb +0 -60
@@ -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
|
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. }},
|
@@ -88,39 +88,39 @@ module QaServer
|
|
88
88
|
averages
|
89
89
|
end
|
90
90
|
|
91
|
-
|
91
|
+
private
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
93
|
+
def records_by(authority_name, action, time_period)
|
94
|
+
where_clause = { dt_stamp: time_period }
|
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
|
97
|
+
performance_data_class.where(where_clause)
|
98
|
+
end
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
100
|
+
def performance_by_hour_label(idx, start_hour)
|
101
|
+
if idx == 23
|
102
|
+
I18n.t('qa_server.monitor_status.performance.now')
|
103
|
+
elsif ((idx + 1) % 2).zero?
|
104
|
+
(start_hour.hour * 100).to_s
|
105
|
+
else
|
106
|
+
" "
|
108
107
|
end
|
108
|
+
end
|
109
109
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
end
|
110
|
+
def performance_by_day_label(idx, start_day)
|
111
|
+
if idx == 29
|
112
|
+
I18n.t('qa_server.monitor_status.performance.today')
|
113
|
+
elsif ((idx + 1) % 5).zero?
|
114
|
+
start_day.strftime("%m-%d")
|
115
|
+
else
|
116
|
+
" "
|
118
117
|
end
|
118
|
+
end
|
119
119
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
120
|
+
def calculate_from_records(records, range_idx, range_label)
|
121
|
+
stats = stats_calculator_class.new(records).calculate_average_stats
|
122
|
+
{ STATS => stats, range_idx => range_label }
|
123
|
+
end
|
124
124
|
end
|
125
125
|
end
|
126
126
|
end
|
@@ -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
|
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
|
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,76 +56,76 @@ 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
|
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),
|
63
63
|
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
private
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
def performance_graph_full_path(authority_name, action, time_period)
|
69
|
+
graph_full_path(graph_filename(authority_name, action, time_period))
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
72
|
+
def graph_filename(authority_name, action, time_period)
|
73
|
+
"performance_of_#{authority_name}_#{action}_for_#{time_period}_graph.png"
|
74
|
+
end
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
88
|
-
[labels, retrieve_data, graph_load_data, normalization_data]
|
76
|
+
def rework_performance_data_for_gruff(performance_data, label_key)
|
77
|
+
labels = {}
|
78
|
+
# full_load_data = []
|
79
|
+
retrieve_data = []
|
80
|
+
graph_load_data = []
|
81
|
+
normalization_data = []
|
82
|
+
performance_data.each do |i, data|
|
83
|
+
labels[i] = data[label_key]
|
84
|
+
retrieve_data << data[STATS][AVG_RETR]
|
85
|
+
graph_load_data << graph_load_time(data)
|
86
|
+
normalization_data << data[STATS][AVG_NORM]
|
89
87
|
end
|
88
|
+
[labels, retrieve_data, graph_load_data, normalization_data]
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
91
|
+
def graph_load_time(data)
|
92
|
+
# For some sense of backward compatibility and to avoid losing the usefulness of previously collected data,
|
93
|
+
# create the graph using the old :load stat when both :retrieve and :graph_load are 0. If the value truly
|
94
|
+
# is 0, then :load will also be 0.
|
95
|
+
# NOTE: It's ok to use AVG_RETR for the retrieve data point because it is 0.
|
96
|
+
# rubocop:disable Style/TernaryParentheses
|
97
|
+
(data[STATS][AVG_RETR].zero? && data[STATS][AVG_GRPH].zero?) ? data[STATS][AVG_LOAD] : data[STATS][AVG_GRPH]
|
98
|
+
# rubocop:enable Style/TernaryParentheses
|
99
|
+
end
|
100
100
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
101
|
+
def performance_graph_theme(g, x_axis_label)
|
102
|
+
g.theme_pastel
|
103
|
+
g.colors = [QaServer.config.performance_normalization_color,
|
104
|
+
QaServer.config.performance_graph_load_color,
|
105
|
+
QaServer.config.performance_retrieve_color]
|
106
|
+
g.marker_font_size = 12
|
107
|
+
g.x_axis_increment = 10
|
108
|
+
g.x_axis_label = x_axis_label
|
109
|
+
g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
|
110
|
+
g.minimum_value = 0
|
111
|
+
g.maximum_value = QaServer.config.performance_y_axis_max
|
112
|
+
end
|
113
113
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
114
|
+
def create_gruff_graph(performance_data, performance_graph_full_path, x_axis_label)
|
115
|
+
g = Gruff::StackedBar.new
|
116
|
+
performance_graph_theme(g, x_axis_label)
|
117
|
+
g.labels = performance_data[0]
|
118
|
+
g.data(I18n.t('qa_server.monitor_status.performance.retrieve_time_ms'), performance_data[1])
|
119
|
+
g.data(I18n.t('qa_server.monitor_status.performance.graph_load_time_ms'), performance_data[2])
|
120
|
+
g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[3])
|
121
|
+
g.write performance_graph_full_path
|
122
|
+
end
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
124
|
+
def log_failure(authority_name, action, time_period)
|
125
|
+
relative_path = performance_graph_image_path(authority_name: authority_name, action: action, time_period: time_period)
|
126
|
+
exists = performance_graph_image_exists?(authority_name: authority_name, action: action, time_period: time_period)
|
127
|
+
QaServer.config.monitor_logger.warn("FAILED to write performance graph at #{relative_path}") unless exists
|
128
|
+
end
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This class calculates min, max, average stats for load, normalization, and full request times for a given set of performance records.
|
3
|
+
require 'matrix'
|
4
|
+
module QaServer
|
5
|
+
class PerformancePerByteCalculatorService
|
6
|
+
include QaServer::PerformanceHistoryDataKeys
|
7
|
+
|
8
|
+
TIME = 0
|
9
|
+
BYTES = 1
|
10
|
+
|
11
|
+
attr_reader :n, :stats, :records
|
12
|
+
|
13
|
+
# @param records [Array <Qa::PerformanceHistory>] set of records used to calculate the statistics
|
14
|
+
def initialize(records:, n:)
|
15
|
+
@records = records
|
16
|
+
@n = n
|
17
|
+
@stats = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Calculate performance statistics with percentiles. Min is at the 10th percentile. Max is at the 90th percentile.
|
21
|
+
# @return [Hash] hash of the statistics
|
22
|
+
# @example
|
23
|
+
# { data_raw_bytes_from_source: [16271, 16271],
|
24
|
+
# retrieve_bytes_per_ms: [67.24433786890475, 55.51210410757532],
|
25
|
+
# retrieve_ms_per_byte: [0.014871140555351083, 0.018014089288745542]
|
26
|
+
# graph_load_bytes_per_ms_ms: [86.74089418722461, 54.97464153778724],
|
27
|
+
# graph_load_ms_per_byte: [0.011528587632974647, 0.018190205011389522],
|
28
|
+
# normalization_bytes_per_ms: [64.70169466560836, 89.25337465693322],
|
29
|
+
# normalization_ms_per_byte: [0.01530700843338457, 0.015455545718983178]
|
30
|
+
# }
|
31
|
+
def calculate
|
32
|
+
extract_bytes
|
33
|
+
calculate_retrieve_stats
|
34
|
+
calculate_graph_load_stats
|
35
|
+
calculate_normalization_stats
|
36
|
+
stats
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def extract_bytes
|
42
|
+
stats[SRC_BYTES] = retrieve_data.count.zero? ? 0 : retrieve_data.map { |d| d[BYTES] }
|
43
|
+
end
|
44
|
+
|
45
|
+
def calculate_retrieve_stats
|
46
|
+
stats[BPMS_RETR] = calculate_bytes_per_ms(retrieve_data)
|
47
|
+
stats[MSPB_RETR] = calculate_ms_per_byte(retrieve_data)
|
48
|
+
end
|
49
|
+
|
50
|
+
def calculate_graph_load_stats
|
51
|
+
stats[BPMS_GRPH] = calculate_bytes_per_ms(graph_load_data)
|
52
|
+
stats[MSPB_GRPH] = calculate_ms_per_byte(graph_load_data)
|
53
|
+
end
|
54
|
+
|
55
|
+
def calculate_normalization_stats
|
56
|
+
stats[BPMS_NORM] = calculate_bytes_per_ms(norm_data)
|
57
|
+
stats[MSPB_NORM] = calculate_ms_per_byte(norm_data)
|
58
|
+
end
|
59
|
+
|
60
|
+
def calculate_bytes_per_ms(data)
|
61
|
+
return 0 if data.count.zero?
|
62
|
+
return data[0][BYTES] / d[0][TIME] if data.count == 1
|
63
|
+
data.map { |d| d[BYTES] / d[TIME] }
|
64
|
+
end
|
65
|
+
|
66
|
+
def calculate_ms_per_byte(data)
|
67
|
+
return 0 if data.count.zero?
|
68
|
+
return data[0][TIME] / d[0][BYTES] if data.count == 1
|
69
|
+
data.map { |d| d[TIME] / d[BYTES] }
|
70
|
+
end
|
71
|
+
|
72
|
+
def data(column)
|
73
|
+
records.where.not(column => nil).order(dt_stamp: :desc).limit(n).pluck(column, :size_bytes)
|
74
|
+
end
|
75
|
+
|
76
|
+
def retrieve_data
|
77
|
+
@retrieve_data ||= data(:retrieve_time_ms)
|
78
|
+
end
|
79
|
+
|
80
|
+
def graph_load_data
|
81
|
+
@graph_data ||= data(:graph_load_time_ms)
|
82
|
+
end
|
83
|
+
|
84
|
+
def norm_data
|
85
|
+
@norm_data ||= data(:normalization_time_ms)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# This class calculates performance stats based on size of data.
|
3
|
+
module QaServer
|
4
|
+
class PerformancePerByteDataService
|
5
|
+
class << self
|
6
|
+
include QaServer::PerformanceHistoryDataKeys
|
7
|
+
|
8
|
+
class_attribute :stats_calculator_class, :performance_data_class
|
9
|
+
self.stats_calculator_class = QaServer::PerformancePerByteCalculatorService
|
10
|
+
self.performance_data_class = QaServer::PerformanceHistory
|
11
|
+
|
12
|
+
# Performance data based on size of data.
|
13
|
+
# @param authority_name [String] name of an authority
|
14
|
+
# @param action [Symbol] :search, :fetch, or :all_actions
|
15
|
+
# @param n [Integer] calculate stats for last n records
|
16
|
+
# @returns [Hash] performance statistics based on size of data
|
17
|
+
# @example returns for n=2
|
18
|
+
# { data_raw_bytes_from_source: [16271, 16271],
|
19
|
+
# retrieve_bytes_per_ms: [67.24433786890475, 55.51210410757532],
|
20
|
+
# retrieve_ms_per_byte: [0.014871140555351083, 0.018014089288745542]
|
21
|
+
# graph_load_bytes_per_ms_ms: [86.74089418722461, 54.97464153778724],
|
22
|
+
# graph_load_ms_per_byte: [0.011528587632974647, 0.018190205011389522],
|
23
|
+
# normalization_bytes_per_ms: [64.70169466560836, 89.25337465693322],
|
24
|
+
# normalization_ms_per_byte: [0.01530700843338457, 0.015455545718983178]
|
25
|
+
# }
|
26
|
+
def calculate(authority_name:, action:, n: 10)
|
27
|
+
records = records_by(authority_name, action)
|
28
|
+
stats_calculator_class.new(records: records, n: n).calculate
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def records_by(authority_name, action)
|
34
|
+
where_clause = {}
|
35
|
+
where_clause[:authority] = authority_name unless authority_name.nil? || authority_name == ALL_AUTH
|
36
|
+
where_clause[:action] = action unless action.nil? || action == ALL_ACTIONS
|
37
|
+
performance_data_class.where(where_clause)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -32,7 +32,7 @@ module QaServer
|
|
32
32
|
|
33
33
|
def self.load_config(authority_name, status_log)
|
34
34
|
scenarios_config = YAML.load_file(scenario_path(authority_name))
|
35
|
-
|
35
|
+
if scenarios_config.blank?
|
36
36
|
status_log.add(authority_name: authority_name,
|
37
37
|
status: QaServer::ScenarioValidator::FAIL,
|
38
38
|
error_message: "Unable to load scenarios for authority '#{authority_name}'; cause: UNKNOWN")
|
@@ -63,31 +63,31 @@ module QaServer
|
|
63
63
|
where_with_authority(where_clause, auth_name, auth_table)
|
64
64
|
end
|
65
65
|
|
66
|
-
|
66
|
+
private
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
68
|
+
def where_for_dt_stamp(dt_table, dt_column, time_period)
|
69
|
+
end_range = QaServer::TimeService.current_time
|
70
|
+
start_range = end_range - time_period
|
71
|
+
where_clause = { dt_column => start_range..end_range }
|
72
|
+
where_clause = { dt_table => where_clause } unless dt_table.nil?
|
73
|
+
where_clause
|
74
|
+
end
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
end
|
83
|
-
where_clause
|
76
|
+
def where_with_authority(where_clause, auth_name, auth_table)
|
77
|
+
return where_clause if auth_name.nil?
|
78
|
+
if auth_table.nil?
|
79
|
+
where_clause[:authority] = auth_name
|
80
|
+
else
|
81
|
+
where_clause[auth_table] = { authority: auth_name }
|
84
82
|
end
|
83
|
+
where_clause
|
84
|
+
end
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
86
|
+
def validate_params(auth_name, auth_table, dt_table)
|
87
|
+
raise ArgumentError, "Do not specify auth_table when auth_name is not specified" if auth_table.present? && auth_name.nil?
|
88
|
+
return if auth_name.nil?
|
89
|
+
raise ArgumentError, "Either both table names need to be specified or neither" if auth_table.present? ^ dt_table.present?
|
90
|
+
end
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
@@ -8,6 +8,7 @@ module QaServer
|
|
8
8
|
|
9
9
|
VALIDATE_CONNECTION = :connection
|
10
10
|
VALIDATE_ACCURACY = :accuracy
|
11
|
+
VALIDATE_ACCURACY_COMPARISON = :accuracy_comparison
|
11
12
|
ALL_VALIDATIONS = :all_validations
|
12
13
|
DEFAULT_VALIDATION_TYPE = VALIDATE_CONNECTION
|
13
14
|
|
@@ -33,92 +34,103 @@ module QaServer
|
|
33
34
|
log
|
34
35
|
end
|
35
36
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
# Log the structure of the scenario and status of a test run.
|
40
|
+
# @param [Hash] status_info holding information to be logged
|
41
|
+
# @see QaServer::ScenarioLogger
|
42
|
+
def log(status_info = {})
|
43
|
+
status_info[:authority_name] = authority_name
|
44
|
+
status_info[:validation_type] = scenario_validation_type
|
45
|
+
status_info[:subauth] = subauthority_name
|
46
|
+
status_info[:service] = service
|
47
|
+
status_info[:action] = action
|
48
|
+
status_info[:url] = url
|
49
|
+
status_info[:request_data] = request_data
|
50
|
+
status_log.add(status_info)
|
51
|
+
end
|
52
|
+
|
53
|
+
def run_accuracy_scenario
|
54
|
+
# ABSTRACT - must be implemented by scenario validator for specific types
|
55
|
+
end
|
56
|
+
|
57
|
+
def run_connection_scenario
|
58
|
+
# ABSTRACT - must be implemented by scenario validator for specific types
|
59
|
+
end
|
60
|
+
|
61
|
+
def request_data
|
62
|
+
# ABSTRACT - must be implemented by scenario validator for specific types
|
63
|
+
end
|
64
|
+
|
65
|
+
# Runs the test in the block passed by the specific scenario type.
|
66
|
+
# @return [Symbol] :good (PASS) or :unknown (UNKNOWN) based on whether enough results were returned
|
67
|
+
def test_connection(min_expected_size: MIN_EXPECTED_SIZE, scenario_type_name:)
|
68
|
+
dt_start = QaServer::TimeService.current_time
|
69
|
+
results = yield if block_given?
|
70
|
+
dt_end = QaServer::TimeService.current_time
|
71
|
+
actual_size = results.to_s.length
|
72
|
+
status = actual_size > min_expected_size ? PASS : UNKNOWN
|
73
|
+
errmsg = status == PASS ? '' : "#{scenario_type_name.capitalize} scenario unknown status; cause: Results actual size (#{actual_size} < expected size (#{min_expected_size})"
|
74
|
+
log(status: status, error_message: errmsg, normalization_run_time: (dt_end - dt_start)) # TODO: need to get run times from results
|
75
|
+
rescue Exception => e
|
76
|
+
dt_end = QaServer::TimeService.current_time
|
77
|
+
log(status: FAIL, error_message: "Exception executing #{scenario_type_name} scenario; cause: #{e.message}", request_run_time: (dt_end - dt_start))
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [Qa::Authorities::LinkedData::GenericAuthority] authority instance the scenarios run against
|
81
|
+
def authority
|
82
|
+
scenario.authority
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [Symbol] name of the authority (e.g. :CERL_LD4L_CACHE)
|
86
|
+
def authority_name
|
87
|
+
scenario.authority_name.upcase
|
88
|
+
end
|
89
|
+
|
90
|
+
# @return [String] name of the subauthority (e.g. "person")
|
91
|
+
def subauthority_name
|
92
|
+
scenario.subauthority_name
|
93
|
+
end
|
94
|
+
|
95
|
+
# @return [String] service providing the data (e.g. "ld4l_cache" or "direct")
|
96
|
+
def service
|
97
|
+
scenario.service
|
98
|
+
end
|
99
|
+
|
100
|
+
# @return [String] relative URL with ready to execute (e.g. ""/authorities/search/linked_data/cerl_ld4l_cache/person?q=office")
|
101
|
+
def url
|
102
|
+
scenario.url
|
103
|
+
end
|
104
|
+
|
105
|
+
# @return [String] action being tested (e.g. "search" or "term")
|
106
|
+
def action
|
107
|
+
# ABSTRACT - must be implemented by scenario validator for specific types
|
108
|
+
end
|
109
|
+
|
110
|
+
def scenario_validation_type
|
111
|
+
return VALIDATE_CONNECTION if connection_scenario?
|
112
|
+
return VALIDATE_ACCURACY if accuracy_scenario?
|
113
|
+
nil
|
114
|
+
end
|
115
|
+
|
116
|
+
def validating_connections?
|
117
|
+
return true if validation_type == VALIDATE_CONNECTION || validation_type == ALL_VALIDATIONS
|
118
|
+
false
|
119
|
+
end
|
120
|
+
|
121
|
+
def validating_accuracy?
|
122
|
+
return true if [VALIDATE_ACCURACY, VALIDATE_ACCURACY_COMPARISON, ALL_VALIDATIONS].include? validation_type
|
123
|
+
false
|
124
|
+
end
|
125
|
+
|
126
|
+
def accuracy_scenario?
|
127
|
+
# ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
|
128
|
+
false
|
129
|
+
end
|
130
|
+
|
131
|
+
def connection_scenario?
|
132
|
+
# ABSTRACT define in specific scenario type validator (i.e. QaServer::TermScenarioValidator, QaServer::SearchScenarioValidator)
|
133
|
+
false
|
134
|
+
end
|
123
135
|
end
|
124
136
|
end
|