qa_server 7.2.1 → 7.6.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.
Files changed (116) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop_fixme.yml +3 -0
  3. data/.travis.yml +4 -5
  4. data/CHANGELOG.md +41 -0
  5. data/Rakefile +1 -1
  6. data/app/assets/stylesheets/qa_server/_check-status.scss +36 -0
  7. data/app/cache_processors/concerns/qa_server/cache_keys.rb +0 -5
  8. data/app/cache_processors/qa_server/cache_expiry_service.rb +13 -8
  9. data/app/cache_processors/qa_server/job_id_cache.rb +29 -0
  10. data/app/cache_processors/qa_server/performance_cache.rb +34 -34
  11. data/app/cache_processors/qa_server/performance_day_graph_cache.rb +27 -0
  12. data/app/cache_processors/qa_server/performance_month_graph_cache.rb +27 -0
  13. data/app/cache_processors/qa_server/performance_year_graph_cache.rb +27 -0
  14. data/app/cache_processors/qa_server/scenario_history_cache.rb +7 -7
  15. data/app/cache_processors/qa_server/scenario_history_graph_cache.rb +12 -17
  16. data/app/cache_processors/qa_server/scenario_run_cache.rb +8 -8
  17. data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +7 -7
  18. data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +7 -7
  19. data/app/controllers/concerns/qa_server/authority_validation_behavior.rb +49 -44
  20. data/app/controllers/qa_server/check_status_controller.rb +92 -22
  21. data/app/controllers/qa_server/fetch_controller.rb +36 -36
  22. data/app/controllers/qa_server/monitor_status_controller.rb +108 -108
  23. data/app/jobs/qa_server/history_graph_job.rb +28 -0
  24. data/app/jobs/qa_server/monitor_tests_job.rb +19 -39
  25. data/app/jobs/qa_server/performance_day_graph_job.rb +45 -0
  26. data/app/jobs/qa_server/performance_month_graph_job.rb +45 -0
  27. data/app/jobs/qa_server/performance_per_byte_job.rb +85 -0
  28. data/app/jobs/qa_server/performance_year_graph_job.rb +45 -0
  29. data/app/loggers/qa_server/scenario_logger.rb +74 -4
  30. data/app/models/concerns/qa_server/performance_history_data_keys.rb +8 -0
  31. data/app/models/qa_server/authority_scenario.rb +4 -4
  32. data/app/models/qa_server/authority_status.rb +2 -2
  33. data/app/models/qa_server/authority_status_failure.rb +1 -1
  34. data/app/models/qa_server/performance_history.rb +2 -2
  35. data/app/models/qa_server/scenario_run_history.rb +52 -52
  36. data/app/models/qa_server/scenario_run_registry.rb +2 -2
  37. data/app/models/qa_server/scenarios.rb +26 -26
  38. data/app/models/qa_server/search_scenario.rb +24 -13
  39. data/app/models/qa_server/term_scenario.rb +29 -29
  40. data/app/prepends/prepended_linked_data/find_term.rb +40 -40
  41. data/app/prepends/prepended_linked_data/search_query.rb +36 -36
  42. data/app/prepends/prepended_rdf/rdf_graph.rb +7 -7
  43. data/app/presenters/concerns/qa_server/monitor_status/performance_datatable_behavior.rb +32 -32
  44. data/app/presenters/concerns/qa_server/monitor_status/performance_graph_behavior.rb +64 -64
  45. data/app/presenters/qa_server/check_status_presenter.rb +63 -7
  46. data/app/presenters/qa_server/monitor_status/current_status_presenter.rb +9 -8
  47. data/app/services/concerns/qa_server/gruff_graph.rb +16 -16
  48. data/app/services/qa_server/authority_loader_service.rb +14 -14
  49. data/app/services/qa_server/authority_validator_service.rb +1 -0
  50. data/app/services/qa_server/database_migrator.rb +14 -14
  51. data/app/services/qa_server/history_graphing_service.rb +30 -30
  52. data/app/services/qa_server/performance_calculator_service.rb +80 -80
  53. data/app/services/qa_server/performance_datatable_service.rb +35 -35
  54. data/app/services/qa_server/performance_graph_data_service.rb +28 -28
  55. data/app/services/qa_server/performance_graphing_service.rb +58 -58
  56. data/app/services/qa_server/performance_per_byte_calculator_service.rb +88 -0
  57. data/app/services/qa_server/performance_per_byte_data_service.rb +41 -0
  58. data/app/services/qa_server/scenarios_loader_service.rb +1 -1
  59. data/app/services/qa_server/time_period_service.rb +21 -21
  60. data/app/validators/qa_server/scenario_validator.rb +99 -87
  61. data/app/validators/qa_server/search_scenario_validator.rb +67 -61
  62. data/app/validators/qa_server/term_scenario_validator.rb +20 -15
  63. data/app/views/qa_server/check_status/index.html.erb +120 -24
  64. data/app/views/qa_server/monitor_status/_test_summary.html.erb +1 -1
  65. data/config/i18n-tasks.yml +133 -0
  66. data/config/locales/qa_server.en.yml +16 -0
  67. data/lib/generators/qa_server/assets_generator.rb +4 -4
  68. data/lib/generators/qa_server/templates/config/authorities/linked_data/cerl_ld4l_cache.json +2 -2
  69. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +62 -1
  70. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +45 -11
  71. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_ulan_ld4l_cache.json +104 -8
  72. data/lib/generators/qa_server/templates/config/authorities/linked_data/isni_ld4l_cache.json +90 -0
  73. data/lib/generators/qa_server/templates/config/authorities/linked_data/ligatus_ld4l_cache.json +133 -0
  74. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo2_ld4l_cache.json +248 -0
  75. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo3_ld4l_cache.json +248 -0
  76. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo_ld4l_cache.json +4 -4
  77. data/lib/generators/qa_server/templates/config/authorities/linked_data/locvocabs_ld4l_cache.json +117 -0
  78. data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_nlm_ld4l_cache.json +135 -3
  79. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +5 -0
  80. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +2 -4
  81. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +31 -0
  82. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +31 -0
  83. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/cerl_ld4l_cache_validation.yml +26 -14
  84. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +33 -0
  85. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +35 -0
  86. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +55 -5
  87. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +253 -0
  88. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +31 -1
  89. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +38 -1
  90. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/isni_ld4l_cache_validation.yml +10 -0
  91. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/ligatus_ld4l_cache_validation.yml +36 -0
  92. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locdemographics_ld4l_cache_validation.yml +69 -44
  93. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +22 -0
  94. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +65 -0
  95. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo2_ld4l_cache_validation.yml +78 -0
  96. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo3_ld4l_cache_validation.yml +73 -0
  97. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo_ld4l_cache_validation.yml +71 -3
  98. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locperformance_ld4l_cache_validation.yml +6 -0
  99. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +30 -0
  100. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locvocabs_ld4l_cache_validation.yml +430 -0
  101. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_nlm_ld4l_cache_validation.yml +54 -1
  102. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +37 -0
  103. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +71 -5
  104. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +73 -2
  105. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +73 -0
  106. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/rda_registry_ld4l_cache_validation.yml +307 -0
  107. data/lib/qa_server/configuration.rb +28 -24
  108. data/lib/qa_server/version.rb +1 -1
  109. data/qa_server.gemspec +6 -5
  110. data/spec/feature/accuracy_spec.rb +32 -0
  111. data/spec/i18n_spec.rb +36 -0
  112. data/spec/spec_helper.rb +4 -0
  113. metadata +74 -20
  114. data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +0 -60
  115. data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +0 -65
  116. data/app/cache_processors/qa_server/performance_monthly_graph_cache.rb +0 -60
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the graph of historical test runs per authority.
3
+ module QaServer
4
+ class HistoryGraphJob < ApplicationJob
5
+ queue_as :default
6
+
7
+ class_attribute :graphing_service
8
+ self.graphing_service = QaServer::HistoryGraphingService
9
+
10
+ def perform(data:)
11
+ # checking active_job_id? prevents race conditions for long running jobs
12
+ generate_graph(data) if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
13
+ end
14
+
15
+ private
16
+
17
+ def generate_graph(data)
18
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) - GENERATING historical summary graph")
19
+ graphing_service.generate_graph(data)
20
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) COMPLETED historical summary graph generation")
21
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
22
+ end
23
+
24
+ def job_key
25
+ "QaServer::HistoryGraphJob--job_id"
26
+ end
27
+ end
28
+ end
@@ -10,49 +10,29 @@ module QaServer
10
10
  self.scenario_run_registry_class = QaServer::ScenarioRunRegistry
11
11
 
12
12
  def perform
13
- Rails.cache.fetch("QaServer::MonitorStatusController/latest_test_run_from_cache", expires_in: QaServer::CacheExpiryService.cache_expiry, race_condition_ttl: 5.minutes, force: true) do
14
- job_id = SecureRandom.uuid
15
- monitor_tests_job_id = job_id unless monitor_tests_job_id
16
- run_tests if monitor_tests_job_id == job_id # avoid race conditions
17
- scenario_run_registry_class.latest_run
18
- end
13
+ # checking active_job_id? prevents race conditions for long running jobs
14
+ run_tests if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id, expires_in: 2.hours)
19
15
  end
20
16
 
21
- private
17
+ private
22
18
 
23
- def run_tests
24
- QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) RUNNING monitoring tests")
25
- validate(authorities_list)
26
- log_results(authorities_list, status_log.to_a)
27
- scenario_run_registry_class.save_run(scenarios_results: status_log.to_a)
28
- QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) COMPLETED monitoring tests")
29
- QaServer.config.performance_cache.write_all # write out cache after completing tests
30
- reset_monitor_tests_job_id
31
- end
32
-
33
- # @return [String, Boolean] Returns job id of the job currently running tests; otherwise, false if tests are not running
34
- def monitor_tests_job_id
35
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 5.minutes) { false }
36
- end
37
-
38
- # Set the id of the job that will run the tests.
39
- # @param job_id [String] UUID for job running the tests
40
- def monitor_tests_job_id=(job_id)
41
- # check to see if there is a current job already running tests
42
- current_job_id = Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 5.seconds) { job_id }
43
-
44
- # current_job_id may be false meaning tests are not currently running; in which case, it is ok to force set job_id
45
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 30.seconds, force: true) { job_id } unless current_job_id
46
- end
19
+ def run_tests
20
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) RUNNING monitoring tests")
21
+ validate(authorities_list)
22
+ log_results(authorities_list, status_log.to_a)
23
+ scenario_run_registry_class.save_run(scenarios_results: status_log.to_a)
24
+ QaServer.config.monitor_logger.debug("(#{self.class}##{__method__}-#{job_id}) COMPLETED monitoring tests")
25
+ QaServer.config.performance_cache.write_all # write out cache after completing tests
26
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
27
+ end
47
28
 
48
- # Set job id for monitor tests to false indicating that tests are not currently running
49
- def reset_monitor_tests_job_id
50
- Rails.cache.fetch("QaServer:monitor_tests-job_id", expires_in: 2.hours, race_condition_ttl: 30.seconds, force: true) { false }
51
- end
29
+ def log_results(authorities_list, results)
30
+ QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) authorities_list is empty") if authorities_list&.empty?
31
+ QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) test results are empty") if results&.empty?
32
+ end
52
33
 
53
- def log_results(authorities_list, results)
54
- QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) authorities_list is empty") if authorities_list&.empty?
55
- QaServer.config.monitor_logger.warn("(#{self.class}##{__method__}-#{job_id}) test results are empty") if results&.empty?
56
- end
34
+ def job_key
35
+ "QaServer::MonitorTestsJob--job_id"
36
+ end
57
37
  end
58
38
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance day graph covering the last 24 hours.
3
+ module QaServer
4
+ class PerformanceDayGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance day graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance day graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
28
+ end
29
+
30
+ def generate_graphs_for_authority(authority_name:)
31
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
32
+ hash[action] = generate_24_hour_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_24_hour_graph(authority_name:, action:)
37
+ data = graph_data_service.calculate_last_24_hours(authority_name: authority_name, action: action)
38
+ graphing_service.generate_day_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceDayGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance month graph covering the last 30 days.
3
+ module QaServer
4
+ class PerformanceMonthGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance month graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance month graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
28
+ end
29
+
30
+ def generate_graphs_for_authority(authority_name:)
31
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
32
+ hash[action] = generate_30_day_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_30_day_graph(authority_name:, action:)
37
+ data = graph_data_service.calculate_last_30_days(authority_name: authority_name, action: action)
38
+ graphing_service.generate_month_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceMonthGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance day graph covering the last 24 hours.
3
+ module QaServer
4
+ class PerformancePerByteJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :data_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.data_service = QaServer::PerformancePerByteDataService
12
+ # self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform(n: 10, action: :search, authority_complexity_ratings: {})
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_data_for_authorities(n, action, authority_complexity_ratings) if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_data_for_authorities(n, action, authority_complexity_ratings)
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance by byte data")
23
+ auths = authority_list_class.authorities_list
24
+ data = if action.nil?
25
+ # generate_data_for_authority(ALL_AUTH, n) # generates data for all authorities
26
+ auths.each_with_object({}) { |authname, hash| hash[authname] = generate_data_for_authority(authname, n) }
27
+ else
28
+ auths.each_with_object({}) { |authname, hash| hash[authname] = { action => generate_data(authname, action, n) } }
29
+ end
30
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance by byte data generation")
31
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
32
+ convert_to_csv(data, authority_complexity_ratings)
33
+ end
34
+
35
+ def generate_data_for_authority(authority_name, n)
36
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
37
+ hash[action] = generate_data(authority_name, action, n)
38
+ end
39
+ end
40
+
41
+ def generate_data(authority_name, action, n)
42
+ data_service.calculate(authority_name: authority_name, action: action, n: n)
43
+ # graphing_service.generate_day_graph(authority_name: authority_name, action: action, data: data)
44
+ end
45
+
46
+ # @param data [Hash] performance statistics based on size of data
47
+ # @param authority_complexity_ratings [Hash] complexity rating of the extended context included with results
48
+ # @example data
49
+ # { data_raw_bytes_from_source: [16271, 16271],
50
+ # retrieve_bytes_per_ms: [67.24433786890475, 55.51210410757532],
51
+ # retrieve_ms_per_byte: [0.014871140555351083, 0.018014089288745542]
52
+ # graph_load_bytes_per_ms_ms: [86.74089418722461, 54.97464153778724],
53
+ # graph_load_ms_per_byte: [0.011528587632974647, 0.018190205011389522],
54
+ # normalization_bytes_per_ms: [64.70169466560836, 89.25337465693322],
55
+ # normalization_ms_per_byte: [0.01530700843338457, 0.015455545718983178]
56
+ # }
57
+ def convert_to_csv(data, authority_complexity_ratings) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
58
+ performance_file = File.new('log/performance.csv', 'w')
59
+ performance_file.write("authority name, complexity_rating, action, size_bytes, ")
60
+ performance_file.write("retrieve_bytes_per_ms, graph_load_bytes_per_ms, normalize_bytes_per_ms, ")
61
+ performance_file.puts("retrieve_ms_per_byte, graph_load_ms_per_byte, normalize_ms_per_byte")
62
+ data.each do |auth_name, auth_data|
63
+ complexity_rating = authority_complexity_ratings.key?(auth_name) ? authority_complexity_ratings[auth_name] : "UNKNOWN"
64
+ auth_data.each do |action, action_data|
65
+ auth_action = "#{auth_name}, #{complexity_rating}, #{action}"
66
+ 0.upto(action_data[:retrieve_bytes_per_ms].size - 1) do |idx|
67
+ performance_file.write(auth_action)
68
+ performance_file.write(", #{action_data[SRC_BYTES][idx]}")
69
+ performance_file.write(", #{action_data[BPMS_RETR][idx]}")
70
+ performance_file.write(", #{action_data[BPMS_GRPH][idx]}")
71
+ performance_file.write(", #{action_data[BPMS_NORM][idx]}")
72
+ performance_file.write(", #{action_data[MSPB_RETR][idx]}")
73
+ performance_file.write(", #{action_data[MSPB_GRPH][idx]}")
74
+ performance_file.puts(", #{action_data[MSPB_NORM][idx]}")
75
+ end
76
+ end
77
+ end
78
+ performance_file.close
79
+ end
80
+
81
+ def job_key
82
+ "QaServer::PerformanceByByteJob--job_id"
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+ # Job to generate the performance year graph covering the last 12 months.
3
+ module QaServer
4
+ class PerformanceYearGraphJob < ApplicationJob
5
+ include QaServer::PerformanceHistoryDataKeys
6
+
7
+ queue_as :default
8
+
9
+ class_attribute :authority_list_class, :graph_data_service, :graphing_service
10
+ self.authority_list_class = QaServer::AuthorityListerService
11
+ self.graph_data_service = QaServer::PerformanceGraphDataService
12
+ self.graphing_service = QaServer::PerformanceGraphingService
13
+
14
+ def perform
15
+ # checking active_job_id? prevents race conditions for long running jobs
16
+ generate_graphs_for_authorities if QaServer::JobIdCache.active_job_id?(job_key: job_key, job_id: job_id)
17
+ end
18
+
19
+ private
20
+
21
+ def generate_graphs_for_authorities
22
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) - GENERATING performance year graph")
23
+ auths = authority_list_class.authorities_list
24
+ generate_graphs_for_authority(authority_name: ALL_AUTH) # generates graph for all authorities
25
+ auths.each { |authname| generate_graphs_for_authority(authority_name: authname) }
26
+ QaServer.config.monitor_logger.debug("(#{self.class}-#{job_id}) COMPLETED performance year graph generation")
27
+ QaServer::JobIdCache.reset_job_id(job_key: job_key)
28
+ end
29
+
30
+ def generate_graphs_for_authority(authority_name:)
31
+ [SEARCH, FETCH, ALL_ACTIONS].each_with_object({}) do |action, hash|
32
+ hash[action] = generate_12_month_graph(authority_name: authority_name, action: action)
33
+ end
34
+ end
35
+
36
+ def generate_12_month_graph(authority_name:, action:)
37
+ data = graph_data_service.calculate_last_12_months(authority_name: authority_name, action: action)
38
+ graphing_service.generate_year_graph(authority_name: authority_name, action: action, data: data)
39
+ end
40
+
41
+ def job_key
42
+ "QaServer::PerformanceYearGraphJob--job_id"
43
+ end
44
+ end
45
+ end
@@ -28,6 +28,7 @@ module QaServer
28
28
  # @option service [String] identifies the primary service provider (e.g. 'ld4l_cache', 'direct', etc.)
29
29
  # @option action [String] type of scenario (i.e. 'term', 'search')
30
30
  # @option url [String] example url that was used to test a specific term fetch or search query
31
+ # @option request_data [String] either the query for searches or the requested id/uri for fetch
31
32
  # @option error_message [String] error message if scenario failed
32
33
  # @option expected [Integer] the expected result (e.g. min size of result OR max position of subject within results)
33
34
  # @option actual [Integer] the actual result (e.g. actual size of results OR actual position of subject within results)
@@ -44,12 +45,14 @@ module QaServer
44
45
  service: status_info[:service] || '',
45
46
  action: status_info[:action] || '',
46
47
  url: status_info[:url] || '',
48
+ request_data: status_info[:request_data] || '',
47
49
  expected: status_info[:expected] || nil,
48
50
  actual: status_info[:actual] || nil,
49
51
  target: status_info[:target] || nil,
50
52
  err_message: status_info[:error_message] || '',
51
53
  request_run_time: status_info[:request_run_time] || nil,
52
- normalization_run_time: status_info[:normalization_run_time] || nil }
54
+ normalization_run_time: status_info[:normalization_run_time] || nil,
55
+ pending: status_info[:pending] || false }
53
56
  end
54
57
 
55
58
  # Delete from the log any tests that passed.
@@ -60,16 +63,83 @@ module QaServer
60
63
  # Append a log to this log.
61
64
  # @param [ScenarioLog] the log to append to this log
62
65
  def append(other)
63
- return unless other.present?
66
+ return if other.blank?
64
67
  @log += other.to_a
65
68
  @test_count += other.test_count
66
69
  @failure_count += other.failure_count
67
70
  end
68
71
 
69
72
  # @return selected scenario test results data as an array limited to the specified type or all scenarios if type is nil
70
- def filter(type: nil)
73
+ # @example ungrouped
74
+ # [ { type: :accuracy_test,
75
+ # status: :PASS,
76
+ # authority_name: 'CERL_LD4L_CACHE',
77
+ # subauthority_name: 'imprint',
78
+ # service: 'ld4l_cache',
79
+ # action: 'search',
80
+ # url: '/qa/search/linked_data/cerl_ld4l_cache/imprint?q=Plantin&maxRecords=8',
81
+ # request_data: 'Plantin',
82
+ # expected: 1,
83
+ # actual: 1,
84
+ # target: 'http://thesaurus.cerl.org/record/cni00007649',
85
+ # err_message: '',
86
+ # request_run_time: 0.032,
87
+ # normalization_run_time: 0.011,
88
+ # pending: false },
89
+ # ... ]
90
+ # @example grouped
91
+ # { CERL_LD4L_CACHE =
92
+ # [ { type: :accuracy_test,
93
+ # status: :PASS,
94
+ # authority_name: 'CERL_LD4L_CACHE',
95
+ # subauthority_name: 'imprint',
96
+ # service: 'ld4l_cache',
97
+ # action: 'search',
98
+ # url: '/qa/search/linked_data/cerl_ld4l_cache/imprint?q=Plantin&maxRecords=8',
99
+ # request_data: 'Plantin',
100
+ # expected: 1,
101
+ # actual: 1,
102
+ # target: 'http://thesaurus.cerl.org/record/cni00007649',
103
+ # err_message: '',
104
+ # request_run_time: 0.032,
105
+ # normalization_run_time: 0.011,
106
+ # pending: false },
107
+ # ... # all others for CERL_LD4L_CACHE
108
+ # ],
109
+ # CERL_NEW_LD4L_CACHE =
110
+ # [ { type: :accuracy_test,
111
+ # status: :PASS,
112
+ # authority_name: 'CERL_NEW_LD4L_CACHE',
113
+ # subauthority_name: 'imprint',
114
+ # service: 'ld4l_cache',
115
+ # action: 'search',
116
+ # url: '/qa/search/linked_data/cerl_new_ld4l_cache/imprint?q=Plantin&maxRecords=8',
117
+ # request_data: 'Plantin',
118
+ # expected: 1,
119
+ # actual: 1,
120
+ # target: 'http://thesaurus.cerl.org/record/cni00007649',
121
+ # err_message: '',
122
+ # request_run_time: 0.022,
123
+ # normalization_run_time: 0.011,
124
+ # pending: false },
125
+ # ... # all others for CERL_NEW_LD4L_CACHE
126
+ # ]
127
+ # }
128
+ def filter(type: nil, group: false)
129
+ return group_data(@log) if group && type.blank?
71
130
  return @log if type.blank?
72
- @log.select { |entry| entry[:type] == type }
131
+ filtered_log = @log.select { |entry| entry[:type] == type }
132
+ group ? group_data(filtered_log) : filtered_log
133
+ end
134
+
135
+ def group_data(log)
136
+ grouped_data = {}
137
+ log.each do |datum|
138
+ auth_name = datum[:authority_name]
139
+ grouped_data[auth_name] = [] unless grouped_data.key? auth_name
140
+ grouped_data[auth_name] << datum
141
+ end
142
+ grouped_data
73
143
  end
74
144
 
75
145
  # @return the scenario test results data as an array
@@ -38,5 +38,13 @@ module QaServer
38
38
  HIGH_NORM = :high_normalization_ms
39
39
  HIGH_ACTN = :high_action_request_ms
40
40
  HIGH_FULL = :high_full_request_ms
41
+
42
+ SRC_BYTES = :data_raw_bytes_from_source
43
+ BPMS_RETR = :retrieve_bytes_per_ms
44
+ MSPB_RETR = :retrieve_ms_per_byte
45
+ BPMS_GRPH = :load_graph_bytes_per_ms
46
+ MSPB_GRPH = :load_graph_ms_per_byte
47
+ BPMS_NORM = :normalization_bytes_per_ms
48
+ MSPB_NORM = :normalization_ms_per_byte
41
49
  end
42
50
  end