qa_server 2.1.0 → 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|