qa_server 7.2.0 → 7.5.1
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 +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
|