qa_server 7.2.0 → 7.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop_fixme.yml +6 -0
  3. data/.travis.yml +4 -5
  4. data/CHANGELOG.md +38 -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 +105 -105
  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 +18 -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/services/concerns/qa_server/gruff_graph.rb +16 -16
  47. data/app/services/qa_server/authority_loader_service.rb +14 -14
  48. data/app/services/qa_server/authority_validator_service.rb +1 -0
  49. data/app/services/qa_server/database_migrator.rb +14 -14
  50. data/app/services/qa_server/history_graphing_service.rb +30 -30
  51. data/app/services/qa_server/performance_calculator_service.rb +80 -80
  52. data/app/services/qa_server/performance_datatable_service.rb +35 -35
  53. data/app/services/qa_server/performance_graph_data_service.rb +28 -28
  54. data/app/services/qa_server/performance_graphing_service.rb +58 -58
  55. data/app/services/qa_server/performance_per_byte_calculator_service.rb +88 -0
  56. data/app/services/qa_server/performance_per_byte_data_service.rb +41 -0
  57. data/app/services/qa_server/scenarios_loader_service.rb +1 -1
  58. data/app/services/qa_server/time_period_service.rb +21 -21
  59. data/app/validators/qa_server/scenario_validator.rb +99 -87
  60. data/app/validators/qa_server/search_scenario_validator.rb +67 -61
  61. data/app/validators/qa_server/term_scenario_validator.rb +20 -15
  62. data/app/views/qa_server/check_status/index.html.erb +120 -24
  63. data/config/i18n-tasks.yml +133 -0
  64. data/config/locales/qa_server.en.yml +15 -0
  65. data/lib/generators/qa_server/assets_generator.rb +4 -4
  66. data/lib/generators/qa_server/templates/config/authorities/linked_data/cerl_ld4l_cache.json +2 -2
  67. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_aat_ld4l_cache.json +62 -1
  68. data/lib/generators/qa_server/templates/config/authorities/linked_data/getty_tgn_ld4l_cache.json +28 -4
  69. data/lib/generators/qa_server/templates/config/authorities/linked_data/isni_ld4l_cache.json +90 -0
  70. data/lib/generators/qa_server/templates/config/authorities/linked_data/ligatus_ld4l_cache.json +133 -0
  71. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo2_ld4l_cache.json +248 -0
  72. data/lib/generators/qa_server/templates/config/authorities/linked_data/locnames_rwo3_ld4l_cache.json +248 -0
  73. data/lib/generators/qa_server/templates/config/authorities/linked_data/locvocabs_ld4l_cache.json +117 -0
  74. data/lib/generators/qa_server/templates/config/authorities/linked_data/mesh_nlm_ld4l_cache.json +135 -3
  75. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_direct.json +1 -0
  76. data/lib/generators/qa_server/templates/config/authorities/linked_data/oclcfast_ld4l_cache.json +1 -4
  77. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_direct_validation.yml +31 -0
  78. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/agrovoc_ld4l_cache_validation.yml +31 -0
  79. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/cerl_ld4l_cache_validation.yml +23 -11
  80. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/dbpedia_ld4l_cache_validation.yml +33 -0
  81. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_direct_validation.yml +35 -0
  82. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/geonames_ld4l_cache_validation.yml +58 -5
  83. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_aat_ld4l_cache_validation.yml +256 -0
  84. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_tgn_ld4l_cache_validation.yml +35 -1
  85. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/getty_ulan_ld4l_cache_validation.yml +37 -0
  86. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/isni_ld4l_cache_validation.yml +10 -0
  87. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/ligatus_ld4l_cache_validation.yml +36 -0
  88. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locdemographics_ld4l_cache_validation.yml +73 -44
  89. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locgenres_ld4l_cache_validation.yml +31 -0
  90. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_ld4l_cache_validation.yml +71 -0
  91. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locnames_rwo_ld4l_cache_validation.yml +70 -2
  92. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locperformance_ld4l_cache_validation.yml +6 -0
  93. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locsubjects_ld4l_cache_validation.yml +32 -0
  94. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/locvocabs_ld4l_cache_validation.yml +184 -0
  95. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/mesh_nlm_ld4l_cache_validation.yml +51 -1
  96. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/nalt_ld4l_cache_validation.yml +37 -0
  97. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclc_fast_validation.yml +71 -5
  98. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_direct_validation.yml +66 -1
  99. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/oclcfast_ld4l_cache_validation.yml +57 -0
  100. data/lib/generators/qa_server/templates/config/authorities/linked_data/scenarios/rda_registry_ld4l_cache_validation.yml +310 -0
  101. data/lib/qa_server/configuration.rb +28 -24
  102. data/lib/qa_server/version.rb +1 -1
  103. data/qa_server.gemspec +2 -1
  104. data/spec/feature/accuracy_spec.rb +32 -0
  105. data/spec/i18n_spec.rb +36 -0
  106. data/spec/spec_helper.rb +4 -0
  107. metadata +46 -12
  108. data/app/cache_processors/qa_server/performance_daily_graph_cache.rb +0 -60
  109. data/app/cache_processors/qa_server/performance_hourly_graph_cache.rb +0 -65
  110. 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