qa_server 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +6 -0
- data/app/assets/stylesheets/qa_server/_fetch.scss +16 -0
- data/app/assets/stylesheets/qa_server/_monitor-status.scss +34 -0
- data/app/assets/stylesheets/qa_server/_qa_server.scss +1 -1
- data/app/assets/stylesheets/qa_server/_styles.scss +4 -0
- data/app/controllers/qa_server/fetch_controller.rb +60 -0
- data/app/controllers/qa_server/monitor_status_controller.rb +4 -2
- data/app/models/qa_server/performance_history.rb +151 -0
- data/app/prepends/prepended_linked_data/find_term.rb +16 -0
- data/app/prepends/prepended_linked_data/search_query.rb +16 -0
- data/app/presenters/qa_server/fetch_presenter.rb +65 -0
- data/app/presenters/qa_server/monitor_status_presenter.rb +114 -8
- data/app/presenters/qa_server/navmenu_presenter.rb +1 -0
- data/app/services/qa_server/authority_loader_service.rb +35 -29
- data/app/views/layouts/qa_server.html.erb +3 -1
- data/app/views/qa_server/fetch/index.html.erb +62 -0
- data/app/views/qa_server/monitor_status/index.html.erb +62 -2
- data/config/locales/qa_server.en.yml +24 -0
- data/config/routes.rb +1 -0
- data/lib/generators/qa_server/config_generator.rb +9 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/DISABLED/scenarios/mesh_bioportal_ld4l_cache_validation.yml +2 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +1 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +1 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_ulan_ld4l_cache.json +1 -1
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locdemographics_ld4l_cache.json +110 -3
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locgenres_ld4l_cache.json +71 -25
- data/lib/generators/qa_server/templates/config/authorities/linked_data/locsubjects_ld4l_cache.json +76 -12
- data/lib/generators/qa_server/templates/config/authorities/linked_data/nalt_ld4l_cache.json +2 -4
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_direct_validation.yml +3 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/loc_validation.yml +6 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locdemographics_ld4l_cache_validation.yml +1 -0
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +13 -14
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +1 -18
- data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +10 -10
- data/lib/generators/qa_server/templates/db/migrate/20190813045549_create_performance_history.rb.erb +12 -0
- data/lib/qa_server/version.rb +1 -1
- metadata +10 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6b1aa8683845f3afeadc0dd3b26a77b56f881fed
|
|
4
|
+
data.tar.gz: 4a38cff642e17ba1be32215b8d89f840963bf1f7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1fd0e79db6c61c2f696eb04eee64f18ef0e82393eba5cc57b13b9641158f235a8d28008ee85f6cc86a1c6641d4d7663e0ffbd8c5a0b1f0c6137b4e5543820af8
|
|
7
|
+
data.tar.gz: 7fbb5e3f7c86a6e26b7dc891a6306cb618b038ddecaa29b0c405a5bf31c3c29049560c0591902e20164ac9715ede061ed3252281e16f6256afcc3bce5620f32a
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
div.results-section {
|
|
2
|
+
margin-top: 50px;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
div.results-panel {
|
|
6
|
+
padding: 50px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.submit_button {
|
|
10
|
+
padding-top: 5px;
|
|
11
|
+
padding-bottom: 5px;
|
|
12
|
+
padding-left: 15px;
|
|
13
|
+
padding-right: 15px;
|
|
14
|
+
background-color: #303d4d;
|
|
15
|
+
color: whitesmoke;
|
|
16
|
+
}
|
|
@@ -11,3 +11,37 @@ p.status-update-dtstamp {
|
|
|
11
11
|
color: darkred;
|
|
12
12
|
font-style: italic;
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
div.right-menu-section {
|
|
16
|
+
padding-top: 50px;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
ul.right-menu {
|
|
20
|
+
list-style-type: none;
|
|
21
|
+
li.clickable {
|
|
22
|
+
display: inline;
|
|
23
|
+
padding-right: 30px;
|
|
24
|
+
color: #337ab7;
|
|
25
|
+
}
|
|
26
|
+
li.clickable:hover {
|
|
27
|
+
color: #23527c;
|
|
28
|
+
text-decoration: underline;
|
|
29
|
+
}
|
|
30
|
+
li.selected {
|
|
31
|
+
display: inline;
|
|
32
|
+
padding-right: 30px;
|
|
33
|
+
font-weight: bold;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
div#performance-by-the-hour {
|
|
38
|
+
display: block;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
div#performance-by-the-day {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
div#performance-by-the-month {
|
|
46
|
+
display: none;
|
|
47
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
@import 'qa_server/styles', 'qa_server/header', 'qa_server/footer', 'qa_server/home-page', 'qa_server/usage',
|
|
2
|
-
'qa_server/authorities', 'qa_server/check-status', 'qa_server/monitor-status';
|
|
2
|
+
'qa_server/authorities', 'qa_server/check-status', 'qa_server/monitor-status', 'qa_server/fetch';
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Controller for Check Status header menu item
|
|
3
|
+
module QaServer
|
|
4
|
+
class FetchController < ApplicationController
|
|
5
|
+
layout 'qa_server'
|
|
6
|
+
|
|
7
|
+
class_attribute :presenter_class,
|
|
8
|
+
:lister_class
|
|
9
|
+
|
|
10
|
+
self.presenter_class = QaServer::FetchPresenter
|
|
11
|
+
self.lister_class = QaServer::AuthorityListerService
|
|
12
|
+
|
|
13
|
+
# Sets up presenter with data to display in the UI
|
|
14
|
+
def index
|
|
15
|
+
flash[:error] = "Authority is required." if uri? && !authority_name?
|
|
16
|
+
@presenter = presenter_class.new(authorities_list: authorities_list,
|
|
17
|
+
authority: authority_name,
|
|
18
|
+
uri: uri,
|
|
19
|
+
format: format,
|
|
20
|
+
term_results: term_results)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
def authorities_list
|
|
26
|
+
@authorities_list ||= lister_class.authorities_list
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# @return [Qa::Authorities::LinkedData::GenericAuthority] the instance of the QA authority
|
|
30
|
+
def authority
|
|
31
|
+
return unless authority_name?
|
|
32
|
+
@authority ||= QaServer::AuthorityLoaderService.load(authority_name: authority_name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def uri?
|
|
36
|
+
uri.present?
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def uri
|
|
40
|
+
@uri ||= params.key?(:uri) ? params[:uri] : nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def authority_name?
|
|
44
|
+
authority_name.present?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def authority_name
|
|
48
|
+
@authority_name ||= params.key?(:authority) ? params[:authority].downcase : nil
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def format
|
|
52
|
+
@format ||= params.key?(:results_format) ? params[:results_format] : 'json'
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def term_results
|
|
56
|
+
return unless authority_name? && uri?
|
|
57
|
+
@term_results = authority.find(uri, format: format)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -4,11 +4,13 @@ module QaServer
|
|
|
4
4
|
class MonitorStatusController < QaServer::AuthorityValidationController
|
|
5
5
|
class_attribute :presenter_class,
|
|
6
6
|
:scenario_run_registry_class,
|
|
7
|
-
:scenario_history_class
|
|
7
|
+
:scenario_history_class,
|
|
8
|
+
:performance_history_class
|
|
8
9
|
|
|
9
10
|
self.presenter_class = QaServer::MonitorStatusPresenter
|
|
10
11
|
self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
|
|
11
12
|
self.scenario_history_class = QaServer::ScenarioRunHistory
|
|
13
|
+
self.performance_history_class = QaServer::PerformanceHistory
|
|
12
14
|
|
|
13
15
|
# Sets up presenter with data to display in the UI
|
|
14
16
|
def index
|
|
@@ -20,7 +22,7 @@ module QaServer
|
|
|
20
22
|
@presenter = presenter_class.new(current_summary: latest_summary,
|
|
21
23
|
current_failure_data: latest_failures,
|
|
22
24
|
historical_summary_data: historical_summary_data,
|
|
23
|
-
performance_data:
|
|
25
|
+
performance_data: performance_history_class.performance_data)
|
|
24
26
|
render 'index', status: :internal_server_error if latest_summary.failing_authority_count.positive?
|
|
25
27
|
end
|
|
26
28
|
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# Provide access to the scenario_results_history database table which tracks specific scenario runs over time.
|
|
3
|
+
module QaServer
|
|
4
|
+
class PerformanceHistory < ActiveRecord::Base
|
|
5
|
+
self.table_name = 'performance_history'
|
|
6
|
+
|
|
7
|
+
enum action: [:fetch, :search]
|
|
8
|
+
|
|
9
|
+
PERFORMANCE_FOR_DAY_KEY = :day
|
|
10
|
+
PERFORMANCE_BY_HOUR_KEY = :hour
|
|
11
|
+
|
|
12
|
+
PERFORMANCE_FOR_MONTH_KEY = :month
|
|
13
|
+
PERFORMANCE_BY_DAY_KEY = :day
|
|
14
|
+
|
|
15
|
+
PERFORMANCE_FOR_YEAR_KEY = :year
|
|
16
|
+
PERFORMANCE_BY_MONTH_KEY = :month
|
|
17
|
+
|
|
18
|
+
LOAD_TIME_KEY = :load_avg_ms
|
|
19
|
+
NORMALIZATION_TIME_KEY = :normalization_avg_ms
|
|
20
|
+
COMBINED_TIME_KEY = :combined_avg_ms
|
|
21
|
+
|
|
22
|
+
class << self
|
|
23
|
+
|
|
24
|
+
# Save a scenario result
|
|
25
|
+
# @param run_id [Integer] the run on which to gather statistics
|
|
26
|
+
# @param result [Hash] the scenario result to be saved
|
|
27
|
+
def save_result(dt_stamp:, authority:, action:, size_bytes:, load_time_ms:, normalization_time_ms: )
|
|
28
|
+
QaServer::PerformanceHistory.create(dt_stamp: dt_stamp,
|
|
29
|
+
authority: authority,
|
|
30
|
+
action: action,
|
|
31
|
+
size_bytes: size_bytes,
|
|
32
|
+
load_time_ms: load_time_ms,
|
|
33
|
+
normalization_time_ms: normalization_time_ms)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Performance data for a day, a month, and a year.
|
|
37
|
+
# @returns [Hash] performance statistics for the past 24 hours
|
|
38
|
+
# @example
|
|
39
|
+
# { 0: { hour: 1400, load_avg_ms: 12.3, normalization_avg_ms: 4.2 },
|
|
40
|
+
# 1: { hour: 1500, load_avg_ms: 12.3, normalization_avg_ms: 4.2 },
|
|
41
|
+
# 2: { hour: 1600, load_avg_ms: 12.3, normalization_avg_ms: 4.2 },
|
|
42
|
+
# ...,
|
|
43
|
+
# 23: { hour: 1300, load_avg_ms: 12.3, normalization_avg_ms: 4.2 }
|
|
44
|
+
# }
|
|
45
|
+
def performance_data
|
|
46
|
+
data = {}
|
|
47
|
+
data[PERFORMANCE_FOR_DAY_KEY] = average_last_24_hours
|
|
48
|
+
data[PERFORMANCE_FOR_MONTH_KEY] = average_last_30_days
|
|
49
|
+
data[PERFORMANCE_FOR_YEAR_KEY] = average_last_12_months
|
|
50
|
+
data
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
# Get hourly average for the past 24 hours.
|
|
56
|
+
# @returns [Hash] performance statistics for the past 24 hours
|
|
57
|
+
# @example
|
|
58
|
+
# { 0: { hour: 1400, load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
59
|
+
# 1: { hour: 1500, load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
60
|
+
# 2: { hour: 1600, load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
61
|
+
# ...,
|
|
62
|
+
# 23: { hour: 1300, load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 }
|
|
63
|
+
# }
|
|
64
|
+
def average_last_24_hours
|
|
65
|
+
start_hour = Time.now.beginning_of_hour - 23.hour
|
|
66
|
+
avgs = {}
|
|
67
|
+
0.upto(23).each do |idx|
|
|
68
|
+
records = PerformanceHistory.where(dt_stamp: start_hour..start_hour.end_of_hour)
|
|
69
|
+
averages = calculate_averages(records)
|
|
70
|
+
data = {}
|
|
71
|
+
data[PERFORMANCE_BY_HOUR_KEY] = idx == 23 ? I18n.t('qa_server.monitor_status.performance.now') : ((idx + 1) % 2 == 0 ? (start_hour.hour * 100).to_s : "")
|
|
72
|
+
data[LOAD_TIME_KEY] = averages[:avg_load_time_ms]
|
|
73
|
+
data[NORMALIZATION_TIME_KEY] = averages[:avg_normalization_time_ms]
|
|
74
|
+
data[COMBINED_TIME_KEY] = averages[:avg_combined_time_ms]
|
|
75
|
+
avgs[idx] = data
|
|
76
|
+
start_hour = start_hour + 1.hour
|
|
77
|
+
end
|
|
78
|
+
avgs
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Get daily average for the past 30 days.
|
|
82
|
+
# @returns [Hash] performance statistics for the past 30 days
|
|
83
|
+
# @example
|
|
84
|
+
# { 0: { day: '07-15-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
85
|
+
# 1: { day: '07-16-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
86
|
+
# 2: { day: '07-17-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
87
|
+
# ...,
|
|
88
|
+
# 29: { day: '08-13-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 }
|
|
89
|
+
# }
|
|
90
|
+
def average_last_30_days
|
|
91
|
+
start_day = Time.now.beginning_of_day - 29.day
|
|
92
|
+
avgs = {}
|
|
93
|
+
0.upto(29).each do |idx|
|
|
94
|
+
records = PerformanceHistory.where(dt_stamp: start_day..start_day.end_of_day)
|
|
95
|
+
averages = calculate_averages(records)
|
|
96
|
+
data = {}
|
|
97
|
+
data[PERFORMANCE_BY_DAY_KEY] = idx == 29 ? I18n.t('qa_server.monitor_status.performance.today') : ((idx + 1) % 5 == 0 ? (start_day).strftime("%m-%d") : "")
|
|
98
|
+
data[LOAD_TIME_KEY] = averages[:avg_load_time_ms]
|
|
99
|
+
data[NORMALIZATION_TIME_KEY] = averages[:avg_normalization_time_ms]
|
|
100
|
+
data[COMBINED_TIME_KEY] = averages[:avg_combined_time_ms]
|
|
101
|
+
avgs[idx] = data
|
|
102
|
+
start_day = start_day + 1.day
|
|
103
|
+
end
|
|
104
|
+
avgs
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Get daily average for the past 12 months.
|
|
108
|
+
# @returns [Hash] performance statistics for the past 12 months
|
|
109
|
+
# @example
|
|
110
|
+
# { 0: { month: '09-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
111
|
+
# 1: { month: '10-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
112
|
+
# 2: { month: '11-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 },
|
|
113
|
+
# ...,
|
|
114
|
+
# 11: { month: '08-2019', load_avg_ms: 12.3, normalization_avg_ms: 4.2, combined_avg_ms: 16.5 }
|
|
115
|
+
# }
|
|
116
|
+
def average_last_12_months
|
|
117
|
+
start_month = Time.now.beginning_of_month - 11.month
|
|
118
|
+
avgs = {}
|
|
119
|
+
0.upto(11).each do |idx|
|
|
120
|
+
records = PerformanceHistory.where(dt_stamp: start_month..start_month.end_of_month)
|
|
121
|
+
averages = calculate_averages(records)
|
|
122
|
+
data = {}
|
|
123
|
+
data[PERFORMANCE_BY_MONTH_KEY] = (start_month).strftime("%m-%Y")
|
|
124
|
+
data[LOAD_TIME_KEY] = averages[:avg_load_time_ms]
|
|
125
|
+
data[NORMALIZATION_TIME_KEY] = averages[:avg_normalization_time_ms]
|
|
126
|
+
data[COMBINED_TIME_KEY] = averages[:avg_combined_time_ms]
|
|
127
|
+
avgs[idx] = data
|
|
128
|
+
start_month = start_month + 1.month
|
|
129
|
+
end
|
|
130
|
+
avgs
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def calculate_averages(records)
|
|
134
|
+
return { avg_load_time_ms: 0, avg_normalization_time_ms: 0, avg_combined_time_ms: 0 } if records.count.zero?
|
|
135
|
+
sum_load_times = 0
|
|
136
|
+
sum_normalization_times = 0
|
|
137
|
+
sum_combined_times = 0
|
|
138
|
+
records.each do |record|
|
|
139
|
+
sum_load_times += record.load_time_ms
|
|
140
|
+
sum_normalization_times += record.normalization_time_ms
|
|
141
|
+
sum_combined_times += (record.load_time_ms + record.normalization_time_ms)
|
|
142
|
+
end
|
|
143
|
+
{
|
|
144
|
+
avg_load_time_ms: sum_load_times / records.count,
|
|
145
|
+
avg_normalization_time_ms: sum_normalization_times / records.count,
|
|
146
|
+
avg_combined_time_ms: sum_combined_times / records.count
|
|
147
|
+
}
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module PrependedLinkedData::FindTerm
|
|
2
|
+
# Override Qa::Authorities::LinkedData::FindTerm#find method
|
|
3
|
+
# @return [Hash] single term results in requested format
|
|
4
|
+
def find(id, language: nil, replacements: {}, subauth: nil, format: nil, jsonld: false, performance_data: false) # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
|
5
|
+
saved_performance_data = performance_data
|
|
6
|
+
performance_data = true
|
|
7
|
+
full_results = super
|
|
8
|
+
QaServer::PerformanceHistory.save_result(dt_stamp: Time.now,
|
|
9
|
+
authority: authority_name,
|
|
10
|
+
action: 'fetch',
|
|
11
|
+
size_bytes: full_results[:performance][:fetched_bytes],
|
|
12
|
+
load_time_ms: (full_results[:performance][:fetch_time_s] * 1000),
|
|
13
|
+
normalization_time_ms: (full_results[:performance][:normalization_time_s] * 1000))
|
|
14
|
+
saved_performance_data ? full_results : full_results[:results]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module PrependedLinkedData::SearchQuery
|
|
2
|
+
# Override Qa::Authorities::LinkedData::SearchQuery#search method
|
|
3
|
+
# @return [String] json results for search query
|
|
4
|
+
def search(query, language: nil, replacements: {}, subauth: nil, context: false, performance_data: false) # rubocop:disable Metrics/ParameterLists
|
|
5
|
+
saved_performance_data = performance_data
|
|
6
|
+
performance_data = true
|
|
7
|
+
full_results = super
|
|
8
|
+
QaServer::PerformanceHistory.save_result(dt_stamp: Time.now,
|
|
9
|
+
authority: authority_name,
|
|
10
|
+
action: 'search',
|
|
11
|
+
size_bytes: full_results[:performance][:fetched_bytes],
|
|
12
|
+
load_time_ms: (full_results[:performance][:fetch_time_s] * 1000),
|
|
13
|
+
normalization_time_ms: (full_results[:performance][:normalization_time_s] * 1000))
|
|
14
|
+
saved_performance_data ? full_results : full_results[:results]
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# This presenter class provides all data needed by the view that checks the status of authorities.
|
|
3
|
+
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
module QaServer
|
|
7
|
+
class FetchPresenter
|
|
8
|
+
# @param authorities_list [Array<String>] a list of all loaded authorities' names
|
|
9
|
+
# @param authority [String] name of the authority from which the term was fetched (e.g. 'LOCSUBJECT_LD4L_CACHE')
|
|
10
|
+
# @param uri [String] requested URI (e.g. 'http://id.loc.gov/authorities/subjects/sh2003008312')
|
|
11
|
+
# @param format [String] return results in this format (e.g. 'json', 'jsonld', 'n3')
|
|
12
|
+
# @param term_results [String] results of fetching a term in the requested format
|
|
13
|
+
def initialize(authorities_list:, authority: nil, uri: nil, format: nil, term_results: nil)
|
|
14
|
+
@authorities_list = authorities_list.map(&:upcase)
|
|
15
|
+
@authority = authority.present? ? authority.upcase : nil
|
|
16
|
+
@uri = uri
|
|
17
|
+
@format = format
|
|
18
|
+
@term_results = term_results
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @return [Array<String>] A list of all loaded authorities' names
|
|
22
|
+
# @example ['AGROVOC_DIRECT', 'AGROVOC_LD4L_CACHE', 'LOCNAMES_LD4L_CACHE']
|
|
23
|
+
attr_reader :authorities_list
|
|
24
|
+
|
|
25
|
+
# @return [String] Name of authority that was searched
|
|
26
|
+
# @example 'AGROVOC_LD4L_CACHE'
|
|
27
|
+
attr_reader :authority
|
|
28
|
+
|
|
29
|
+
# @return [String] The requested URI
|
|
30
|
+
# @example 'http://id.loc.gov/authorities/subjects/sh2003008312'
|
|
31
|
+
attr_reader :uri
|
|
32
|
+
|
|
33
|
+
# @return [Array<String>] list of supported formats
|
|
34
|
+
def formats_list
|
|
35
|
+
['json', 'jsonld', 'n3']
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# @return [String] format for the returned results of fetching the term
|
|
39
|
+
# @example 'json', 'jsonld', 'n3'
|
|
40
|
+
attr_reader :format
|
|
41
|
+
|
|
42
|
+
def json?
|
|
43
|
+
format.casecmp? 'json'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def jsonld?
|
|
47
|
+
format.casecmp? 'jsonld'
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def n3?
|
|
51
|
+
format.casecmp? 'n3'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# @return [String] results for the term fetch in the requested format
|
|
55
|
+
def term_results
|
|
56
|
+
return JSON.pretty_generate(@term_results) if json?
|
|
57
|
+
@term_results
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [Boolean] true if search results exist; otherwise false
|
|
61
|
+
def term_results?
|
|
62
|
+
@term_results.present?
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -6,13 +6,27 @@ require 'gruff'
|
|
|
6
6
|
# This presenter class provides all data needed by the view that monitors status of authorities.
|
|
7
7
|
module QaServer
|
|
8
8
|
class MonitorStatusPresenter # rubocop:disable Metrics/ClassLength
|
|
9
|
+
class_attribute :performance_history_class
|
|
10
|
+
self.performance_history_class = QaServer::PerformanceHistory
|
|
11
|
+
|
|
9
12
|
HISTORICAL_AUTHORITY_NAME_IDX = 0
|
|
10
13
|
HISTORICAL_FAILURE_COUNT_IDX = 1
|
|
11
14
|
HISTORICAL_PASSING_COUNT_IDX = 2
|
|
12
15
|
|
|
16
|
+
PERFORMANCE_FOR_DAY_KEY = performance_history_class::PERFORMANCE_FOR_DAY_KEY
|
|
17
|
+
PERFORMANCE_BY_HOUR_KEY = performance_history_class::PERFORMANCE_BY_HOUR_KEY
|
|
18
|
+
PERFORMANCE_FOR_MONTH_KEY = performance_history_class::PERFORMANCE_FOR_MONTH_KEY
|
|
19
|
+
PERFORMANCE_BY_DAY_KEY = performance_history_class::PERFORMANCE_BY_DAY_KEY
|
|
20
|
+
PERFORMANCE_FOR_YEAR_KEY = performance_history_class::PERFORMANCE_FOR_YEAR_KEY
|
|
21
|
+
PERFORMANCE_BY_MONTH_KEY = performance_history_class::PERFORMANCE_BY_MONTH_KEY
|
|
22
|
+
LOAD_TIME_KEY = performance_history_class::LOAD_TIME_KEY
|
|
23
|
+
NORMALIZATION_TIME_KEY = performance_history_class::NORMALIZATION_TIME_KEY
|
|
24
|
+
COMBINED_TIME_KEY = performance_history_class::COMBINED_TIME_KEY
|
|
25
|
+
|
|
13
26
|
# @param current_summary [ScenarioRunSummary] summary status of the latest run of test scenarios
|
|
14
27
|
# @param current_data [Array<Hash>] current set of failures for the latest test run, if any
|
|
15
28
|
# @param historical_summary_data [Array<Hash>] summary of past failuring runs per authority to drive chart
|
|
29
|
+
# @param performance_data [Hash<Hash>] performance data
|
|
16
30
|
def initialize(current_summary:, current_failure_data:, historical_summary_data:, performance_data:)
|
|
17
31
|
@current_summary = current_summary
|
|
18
32
|
@current_failure_data = current_failure_data
|
|
@@ -101,14 +115,14 @@ module QaServer
|
|
|
101
115
|
def historical_graph
|
|
102
116
|
# g = Gruff::SideStackedBar.new('800x400')
|
|
103
117
|
g = Gruff::SideStackedBar.new
|
|
104
|
-
|
|
118
|
+
historical_graph_theme(g)
|
|
105
119
|
g.title = ''
|
|
106
120
|
historical_data = rework_historical_data_for_gruff
|
|
107
121
|
g.labels = historical_data[0]
|
|
108
122
|
g.data('Fail', historical_data[1])
|
|
109
123
|
g.data('Pass', historical_data[2])
|
|
110
124
|
g.write historical_graph_full_path
|
|
111
|
-
File.join(
|
|
125
|
+
File.join(graph_relative_path, historical_graph_filename)
|
|
112
126
|
end
|
|
113
127
|
|
|
114
128
|
# @return [String] the name of the css style class to use for the status cell based on the status of the scenario test.
|
|
@@ -175,23 +189,52 @@ module QaServer
|
|
|
175
189
|
QaServer.config.display_historical_datatable?
|
|
176
190
|
end
|
|
177
191
|
|
|
192
|
+
def performance_data?
|
|
193
|
+
@performance_data.present?
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
def performance_for_day_graph
|
|
197
|
+
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_DAY_KEY], :hour),
|
|
198
|
+
performance_for_day_graph_full_path,
|
|
199
|
+
performance_for_day_graph_filename,
|
|
200
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
def performance_for_month_graph
|
|
204
|
+
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_MONTH_KEY], :day),
|
|
205
|
+
performance_for_month_graph_full_path,
|
|
206
|
+
performance_for_month_graph_filename,
|
|
207
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_day'))
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def performance_for_year_graph
|
|
211
|
+
performance_graph_file(rework_performance_data_for_gruff(@performance_data[PERFORMANCE_FOR_YEAR_KEY], :month),
|
|
212
|
+
performance_for_year_graph_full_path,
|
|
213
|
+
performance_for_year_graph_filename,
|
|
214
|
+
I18n.t('qa_server.monitor_status.performance.x_axis_month'))
|
|
215
|
+
end
|
|
216
|
+
|
|
178
217
|
private
|
|
179
218
|
|
|
180
|
-
def
|
|
219
|
+
def historical_graph_theme(g)
|
|
181
220
|
g.theme_pastel
|
|
182
221
|
g.colors = ['#ffcccc', '#ccffcc']
|
|
183
222
|
g.marker_font_size = 12
|
|
184
223
|
g.x_axis_increment = 10
|
|
185
224
|
end
|
|
186
225
|
|
|
187
|
-
def
|
|
188
|
-
|
|
226
|
+
def graph_relative_path
|
|
227
|
+
File.join('qa_server', 'charts')
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def graph_full_path(graph_filename)
|
|
231
|
+
path = Rails.root.join('app', 'assets', 'images', graph_relative_path)
|
|
189
232
|
FileUtils.mkdir_p path
|
|
190
|
-
File.join(path,
|
|
233
|
+
File.join(path, graph_filename)
|
|
191
234
|
end
|
|
192
235
|
|
|
193
|
-
def
|
|
194
|
-
|
|
236
|
+
def historical_graph_full_path
|
|
237
|
+
graph_full_path(historical_graph_filename)
|
|
195
238
|
end
|
|
196
239
|
|
|
197
240
|
def historical_graph_filename
|
|
@@ -211,5 +254,68 @@ module QaServer
|
|
|
211
254
|
end
|
|
212
255
|
[labels, fail_data, pass_data]
|
|
213
256
|
end
|
|
257
|
+
|
|
258
|
+
def performance_graph_theme(g, x_axis_label)
|
|
259
|
+
g.theme_pastel
|
|
260
|
+
g.colors = ['#81adf4', '#8696b0', '#06578a']
|
|
261
|
+
g.marker_font_size = 12
|
|
262
|
+
g.x_axis_increment = 10
|
|
263
|
+
g.x_axis_label = x_axis_label
|
|
264
|
+
g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
|
|
265
|
+
g.dot_radius = 3
|
|
266
|
+
g.line_width = 2
|
|
267
|
+
g.minimum_value = 0
|
|
268
|
+
g.maximum_value = 1000
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def performance_for_day_graph_filename
|
|
272
|
+
'performance_for_day_graph.png'
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def performance_for_day_graph_full_path
|
|
276
|
+
graph_full_path(performance_for_day_graph_filename)
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
def performance_for_month_graph_filename
|
|
280
|
+
'performance_for_month_graph.png'
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
def performance_for_month_graph_full_path
|
|
284
|
+
graph_full_path(performance_for_month_graph_filename)
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def performance_for_year_graph_filename
|
|
288
|
+
'performance_for_year_graph.png'
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
def performance_for_year_graph_full_path
|
|
292
|
+
graph_full_path(performance_for_year_graph_filename)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def rework_performance_data_for_gruff(performance_data, label_key)
|
|
296
|
+
labels = {}
|
|
297
|
+
load_data = []
|
|
298
|
+
normalization_data = []
|
|
299
|
+
combined_data = []
|
|
300
|
+
performance_data.each do |i, data|
|
|
301
|
+
labels[i] = data[label_key]
|
|
302
|
+
load_data << data[LOAD_TIME_KEY]
|
|
303
|
+
normalization_data << data[NORMALIZATION_TIME_KEY]
|
|
304
|
+
combined_data << data[COMBINED_TIME_KEY]
|
|
305
|
+
end
|
|
306
|
+
[labels, load_data, normalization_data, combined_data]
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def performance_graph_file(performance_data, performance_graph_full_path, performance_graph_filename, x_axis_label)
|
|
310
|
+
g = Gruff::Line.new
|
|
311
|
+
performance_graph_theme(g, x_axis_label)
|
|
312
|
+
g.title = ''
|
|
313
|
+
g.labels = performance_data[0]
|
|
314
|
+
g.data(I18n.t('qa_server.monitor_status.performance.load_time_ms'), performance_data[1])
|
|
315
|
+
g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[2])
|
|
316
|
+
g.data(I18n.t('qa_server.monitor_status.performance.combined_time_ms'), performance_data[3])
|
|
317
|
+
g.write performance_graph_full_path
|
|
318
|
+
File.join(graph_relative_path, performance_graph_filename)
|
|
319
|
+
end
|
|
214
320
|
end
|
|
215
321
|
end
|