qa_server 7.3.0 → 7.7.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 (113) hide show
  1. checksums.yaml +5 -5
  2. data/.rubocop_fixme.yml +3 -0
  3. data/.travis.yml +4 -5
  4. data/CHANGELOG.md +45 -0
  5. data/Rakefile +1 -1
  6. data/app/assets/stylesheets/qa_server/_check-status.scss +36 -0
  7. data/app/cache_processors/qa_server/cache_expiry_service.rb +8 -8
  8. data/app/cache_processors/qa_server/job_id_cache.rb +4 -4
  9. data/app/cache_processors/qa_server/performance_cache.rb +34 -34
  10. data/app/cache_processors/qa_server/performance_day_graph_cache.rb +7 -7
  11. data/app/cache_processors/qa_server/performance_month_graph_cache.rb +7 -7
  12. data/app/cache_processors/qa_server/performance_year_graph_cache.rb +7 -7
  13. data/app/cache_processors/qa_server/scenario_history_cache.rb +7 -7
  14. data/app/cache_processors/qa_server/scenario_history_graph_cache.rb +7 -7
  15. data/app/cache_processors/qa_server/scenario_run_cache.rb +7 -7
  16. data/app/cache_processors/qa_server/scenario_run_failures_cache.rb +7 -7
  17. data/app/cache_processors/qa_server/scenario_run_summary_cache.rb +7 -7
  18. data/app/controllers/concerns/qa_server/authority_validation_behavior.rb +49 -44
  19. data/app/controllers/qa_server/check_status_controller.rb +92 -22
  20. data/app/controllers/qa_server/fetch_controller.rb +36 -36
  21. data/app/controllers/qa_server/monitor_status_controller.rb +106 -84
  22. data/app/jobs/qa_server/history_graph_job.rb +10 -10
  23. data/app/jobs/qa_server/monitor_tests_job.rb +17 -17
  24. data/app/jobs/qa_server/performance_day_graph_job.rb +21 -21
  25. data/app/jobs/qa_server/performance_month_graph_job.rb +21 -21
  26. data/app/jobs/qa_server/performance_per_byte_job.rb +85 -0
  27. data/app/jobs/qa_server/performance_year_graph_job.rb +21 -21
  28. data/app/loggers/qa_server/scenario_logger.rb +74 -4
  29. data/app/models/concerns/qa_server/performance_history_data_keys.rb +8 -0
  30. data/app/models/qa_server/authority_scenario.rb +4 -4
  31. data/app/models/qa_server/authority_status.rb +2 -2
  32. data/app/models/qa_server/authority_status_failure.rb +1 -1
  33. data/app/models/qa_server/performance_history.rb +2 -2
  34. data/app/models/qa_server/scenario_run_history.rb +63 -54
  35. data/app/models/qa_server/scenario_run_registry.rb +2 -2
  36. data/app/models/qa_server/scenarios.rb +26 -26
  37. data/app/models/qa_server/search_scenario.rb +24 -13
  38. data/app/models/qa_server/term_scenario.rb +29 -29
  39. data/app/prepends/prepended_linked_data/find_term.rb +40 -40
  40. data/app/prepends/prepended_linked_data/search_query.rb +36 -36
  41. data/app/prepends/prepended_rdf/rdf_graph.rb +7 -7
  42. data/app/presenters/concerns/qa_server/monitor_status/performance_datatable_behavior.rb +32 -32
  43. data/app/presenters/concerns/qa_server/monitor_status/performance_graph_behavior.rb +64 -64
  44. data/app/presenters/qa_server/check_status_presenter.rb +63 -7
  45. data/app/presenters/qa_server/monitor_status/current_status_presenter.rb +9 -8
  46. data/app/presenters/qa_server/monitor_status/history_presenter.rb +5 -2
  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 +27 -27
  55. data/app/services/qa_server/performance_graphing_service.rb +55 -55
  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 +21 -5
  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 +24 -12
  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 +35 -0
  112. data/spec/spec_helper.rb +4 -0
  113. metadata +66 -17
@@ -32,48 +32,48 @@ module QaServer
32
32
  end
33
33
  end
34
34
 
35
- private
35
+ private
36
36
 
37
- def datatable_data_for_authority(authority_name: nil)
38
- [:search, :fetch, :all_actions].each_with_object({}) do |action, hash|
39
- hash[action] = data_table_stats(authority_name, action)
40
- end
37
+ def datatable_data_for_authority(authority_name: nil)
38
+ [:search, :fetch, :all_actions].each_with_object({}) do |action, hash|
39
+ hash[action] = data_table_stats(authority_name, action)
41
40
  end
41
+ end
42
42
 
43
- # Get statistics for data table.
44
- # @param auth_name [String] limit statistics to records for the given authority (default: all authorities)
45
- # @param action [Symbol] one of :search, :fetch, :all_actions
46
- # @returns [Hash] performance statistics for the datatable during the expected time period
47
- # @example
48
- # { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
49
- # retrieve_10th_ms: 12.3, graph_load_10th_ms: 12.3, normalization_10th_ms: 4.2, full_request_10th_ms: 16.5,
50
- # retrieve_90th_ms: 12.3, graph_load_90th_ms: 12.3, normalization_90th_ms: 4.2, full_request_90th_ms: 16.5 }
51
- def data_table_stats(auth_name, action)
52
- records = records_for_authority(auth_name)
53
- stats_calculator_class.new(records, action: action).calculate_stats_with_percentiles
54
- end
43
+ # Get statistics for data table.
44
+ # @param auth_name [String] limit statistics to records for the given authority (default: all authorities)
45
+ # @param action [Symbol] one of :search, :fetch, :all_actions
46
+ # @returns [Hash] performance statistics for the datatable during the expected time period
47
+ # @example
48
+ # { retrieve_avg_ms: 12.3, graph_load_avg_ms: 2.1, normalization_avg_ms: 4.2, full_request_avg_ms: 16.5,
49
+ # retrieve_10th_ms: 12.3, graph_load_10th_ms: 12.3, normalization_10th_ms: 4.2, full_request_10th_ms: 16.5,
50
+ # retrieve_90th_ms: 12.3, graph_load_90th_ms: 12.3, normalization_90th_ms: 4.2, full_request_90th_ms: 16.5 }
51
+ def data_table_stats(auth_name, action)
52
+ records = records_for_authority(auth_name)
53
+ stats_calculator_class.new(records, action: action).calculate_stats_with_percentiles
54
+ end
55
55
 
56
- def expected_time_period
57
- QaServer.config.performance_datatable_default_time_period
58
- end
56
+ def expected_time_period
57
+ QaServer.config.performance_datatable_default_time_period
58
+ end
59
59
 
60
- def records_for_authority(auth_name)
61
- case expected_time_period
62
- when :day
63
- QaServer.config.performance_cache.write_all # only need to write if just using today's data
64
- performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_24_hours(auth_name: auth_name))
65
- when :month
66
- performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_30_days(auth_name: auth_name))
67
- when :year
68
- performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_12_months(auth_name: auth_name))
69
- else
70
- all_records(auth_name)
71
- end
60
+ def records_for_authority(auth_name)
61
+ case expected_time_period
62
+ when :day
63
+ QaServer.config.performance_cache.write_all # only need to write if just using today's data
64
+ performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_24_hours(auth_name: auth_name))
65
+ when :month
66
+ performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_30_days(auth_name: auth_name))
67
+ when :year
68
+ performance_data_class.where(QaServer::TimePeriodService.where_clause_for_last_12_months(auth_name: auth_name))
69
+ else
70
+ all_records(auth_name)
72
71
  end
72
+ end
73
73
 
74
- def all_records(auth_name)
75
- auth_name.nil? ? performance_data_class.all : performance_data_class.where(authority: auth_name)
76
- end
74
+ def all_records(auth_name)
75
+ auth_name.nil? ? performance_data_class.all : performance_data_class.where(authority: auth_name)
76
+ end
77
77
  end
78
78
  end
79
79
  end
@@ -88,39 +88,39 @@ module QaServer
88
88
  averages
89
89
  end
90
90
 
91
- private
91
+ private
92
92
 
93
- def records_by(authority_name, action, time_period)
94
- where_clause = { dt_stamp: time_period }
95
- where_clause[:authority] = authority_name unless authority_name.nil? || authority_name == ALL_AUTH
96
- where_clause[:action] = action unless action.nil? || action == ALL_ACTIONS
97
- performance_data_class.where(where_clause)
98
- end
93
+ def records_by(authority_name, action, time_period)
94
+ where_clause = { dt_stamp: time_period }
95
+ where_clause[:authority] = authority_name unless authority_name.nil? || authority_name == ALL_AUTH
96
+ where_clause[:action] = action unless action.nil? || action == ALL_ACTIONS
97
+ performance_data_class.where(where_clause)
98
+ end
99
99
 
100
- def performance_by_hour_label(idx, start_hour)
101
- if idx == 23
102
- I18n.t('qa_server.monitor_status.performance.now')
103
- elsif ((idx + 1) % 2).zero?
104
- (start_hour.hour * 100).to_s
105
- else
106
- " "
107
- end
100
+ def performance_by_hour_label(idx, start_hour)
101
+ if idx == 23
102
+ I18n.t('qa_server.monitor_status.performance.now')
103
+ elsif ((idx + 1) % 2).zero?
104
+ (start_hour.hour * 100).to_s
105
+ else
106
+ " "
108
107
  end
108
+ end
109
109
 
110
- def performance_by_day_label(idx, start_day)
111
- if idx == 29
112
- I18n.t('qa_server.monitor_status.performance.today')
113
- elsif ((idx + 1) % 5).zero?
114
- start_day.strftime("%m-%d")
115
- else
116
- " "
117
- end
110
+ def performance_by_day_label(idx, start_day)
111
+ if idx == 29
112
+ I18n.t('qa_server.monitor_status.performance.today')
113
+ elsif ((idx + 1) % 5).zero?
114
+ start_day.strftime("%m-%d")
115
+ else
116
+ " "
118
117
  end
118
+ end
119
119
 
120
- def calculate_from_records(records, range_idx, range_label)
121
- stats = stats_calculator_class.new(records).calculate_average_stats
122
- { STATS => stats, range_idx => range_label }
123
- end
120
+ def calculate_from_records(records, range_idx, range_label)
121
+ stats = stats_calculator_class.new(records).calculate_average_stats
122
+ { STATS => stats, range_idx => range_label }
123
+ end
124
124
  end
125
125
  end
126
126
  end
@@ -63,69 +63,69 @@ module QaServer
63
63
  I18n.t('qa_server.monitor_status.performance.x_axis_hour'))
64
64
  end
65
65
 
66
- private
66
+ private
67
67
 
68
- def performance_graph_full_path(authority_name, action, time_period)
69
- graph_full_path(graph_filename(authority_name, action, time_period))
70
- end
68
+ def performance_graph_full_path(authority_name, action, time_period)
69
+ graph_full_path(graph_filename(authority_name, action, time_period))
70
+ end
71
71
 
72
- def graph_filename(authority_name, action, time_period)
73
- "performance_of_#{authority_name}_#{action}_for_#{time_period}_graph.png"
74
- end
72
+ def graph_filename(authority_name, action, time_period)
73
+ "performance_of_#{authority_name}_#{action}_for_#{time_period}_graph.png"
74
+ end
75
75
 
76
- def rework_performance_data_for_gruff(performance_data, label_key)
77
- labels = {}
78
- # full_load_data = []
79
- retrieve_data = []
80
- graph_load_data = []
81
- normalization_data = []
82
- performance_data.each do |i, data|
83
- labels[i] = data[label_key]
84
- retrieve_data << data[STATS][AVG_RETR]
85
- graph_load_data << graph_load_time(data)
86
- normalization_data << data[STATS][AVG_NORM]
87
- end
88
- [labels, retrieve_data, graph_load_data, normalization_data]
76
+ def rework_performance_data_for_gruff(performance_data, label_key)
77
+ labels = {}
78
+ # full_load_data = []
79
+ retrieve_data = []
80
+ graph_load_data = []
81
+ normalization_data = []
82
+ performance_data.each do |i, data|
83
+ labels[i] = data[label_key]
84
+ retrieve_data << data[STATS][AVG_RETR]
85
+ graph_load_data << graph_load_time(data)
86
+ normalization_data << data[STATS][AVG_NORM]
89
87
  end
88
+ [labels, retrieve_data, graph_load_data, normalization_data]
89
+ end
90
90
 
91
- def graph_load_time(data)
92
- # For some sense of backward compatibility and to avoid losing the usefulness of previously collected data,
93
- # create the graph using the old :load stat when both :retrieve and :graph_load are 0. If the value truly
94
- # is 0, then :load will also be 0.
95
- # NOTE: It's ok to use AVG_RETR for the retrieve data point because it is 0.
96
- # rubocop:disable Style/TernaryParentheses
97
- (data[STATS][AVG_RETR].zero? && data[STATS][AVG_GRPH].zero?) ? data[STATS][AVG_LOAD] : data[STATS][AVG_GRPH]
98
- # rubocop:enable Style/TernaryParentheses
99
- end
91
+ def graph_load_time(data)
92
+ # For some sense of backward compatibility and to avoid losing the usefulness of previously collected data,
93
+ # create the graph using the old :load stat when both :retrieve and :graph_load are 0. If the value truly
94
+ # is 0, then :load will also be 0.
95
+ # NOTE: It's ok to use AVG_RETR for the retrieve data point because it is 0.
96
+ # rubocop:disable Style/TernaryParentheses
97
+ (data[STATS][AVG_RETR].zero? && data[STATS][AVG_GRPH].zero?) ? data[STATS][AVG_LOAD] : data[STATS][AVG_GRPH]
98
+ # rubocop:enable Style/TernaryParentheses
99
+ end
100
100
 
101
- def performance_graph_theme(g, x_axis_label)
102
- g.theme_pastel
103
- g.colors = [QaServer.config.performance_normalization_color,
104
- QaServer.config.performance_graph_load_color,
105
- QaServer.config.performance_retrieve_color]
106
- g.marker_font_size = 12
107
- g.x_axis_increment = 10
108
- g.x_axis_label = x_axis_label
109
- g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
110
- g.minimum_value = 0
111
- g.maximum_value = QaServer.config.performance_y_axis_max
112
- end
101
+ def performance_graph_theme(g, x_axis_label)
102
+ g.theme_pastel
103
+ g.colors = [QaServer.config.performance_normalization_color,
104
+ QaServer.config.performance_graph_load_color,
105
+ QaServer.config.performance_retrieve_color]
106
+ g.marker_font_size = 12
107
+ g.x_axis_increment = 10
108
+ g.x_axis_label = x_axis_label
109
+ g.y_axis_label = I18n.t('qa_server.monitor_status.performance.y_axis_ms')
110
+ g.minimum_value = 0
111
+ g.maximum_value = QaServer.config.performance_y_axis_max
112
+ end
113
113
 
114
- def create_gruff_graph(performance_data, performance_graph_full_path, x_axis_label)
115
- g = Gruff::StackedBar.new
116
- performance_graph_theme(g, x_axis_label)
117
- g.labels = performance_data[0]
118
- g.data(I18n.t('qa_server.monitor_status.performance.retrieve_time_ms'), performance_data[1])
119
- g.data(I18n.t('qa_server.monitor_status.performance.graph_load_time_ms'), performance_data[2])
120
- g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[3])
121
- g.write performance_graph_full_path
122
- end
114
+ def create_gruff_graph(performance_data, performance_graph_full_path, x_axis_label)
115
+ g = Gruff::StackedBar.new
116
+ performance_graph_theme(g, x_axis_label)
117
+ g.labels = performance_data[0]
118
+ g.data(I18n.t('qa_server.monitor_status.performance.retrieve_time_ms'), performance_data[1])
119
+ g.data(I18n.t('qa_server.monitor_status.performance.graph_load_time_ms'), performance_data[2])
120
+ g.data(I18n.t('qa_server.monitor_status.performance.normalization_time_ms'), performance_data[3])
121
+ g.write performance_graph_full_path
122
+ end
123
123
 
124
- def log_failure(authority_name, action, time_period)
125
- relative_path = performance_graph_image_path(authority_name: authority_name, action: action, time_period: time_period)
126
- exists = performance_graph_image_exists?(authority_name: authority_name, action: action, time_period: time_period)
127
- QaServer.config.monitor_logger.warn("FAILED to write performance graph at #{relative_path}") unless exists
128
- end
124
+ def log_failure(authority_name, action, time_period)
125
+ relative_path = performance_graph_image_path(authority_name: authority_name, action: action, time_period: time_period)
126
+ exists = performance_graph_image_exists?(authority_name: authority_name, action: action, time_period: time_period)
127
+ QaServer.config.monitor_logger.warn("FAILED to write performance graph at #{relative_path}") unless exists
128
+ end
129
129
  end
130
130
  end
131
131
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ # This class calculates min, max, average stats for load, normalization, and full request times for a given set of performance records.
3
+ require 'matrix'
4
+ module QaServer
5
+ class PerformancePerByteCalculatorService
6
+ include QaServer::PerformanceHistoryDataKeys
7
+
8
+ TIME = 0
9
+ BYTES = 1
10
+
11
+ attr_reader :n, :stats, :records
12
+
13
+ # @param records [Array <Qa::PerformanceHistory>] set of records used to calculate the statistics
14
+ def initialize(records:, n:)
15
+ @records = records
16
+ @n = n
17
+ @stats = {}
18
+ end
19
+
20
+ # Calculate performance statistics with percentiles. Min is at the 10th percentile. Max is at the 90th percentile.
21
+ # @return [Hash] hash of the statistics
22
+ # @example
23
+ # { data_raw_bytes_from_source: [16271, 16271],
24
+ # retrieve_bytes_per_ms: [67.24433786890475, 55.51210410757532],
25
+ # retrieve_ms_per_byte: [0.014871140555351083, 0.018014089288745542]
26
+ # graph_load_bytes_per_ms_ms: [86.74089418722461, 54.97464153778724],
27
+ # graph_load_ms_per_byte: [0.011528587632974647, 0.018190205011389522],
28
+ # normalization_bytes_per_ms: [64.70169466560836, 89.25337465693322],
29
+ # normalization_ms_per_byte: [0.01530700843338457, 0.015455545718983178]
30
+ # }
31
+ def calculate
32
+ extract_bytes
33
+ calculate_retrieve_stats
34
+ calculate_graph_load_stats
35
+ calculate_normalization_stats
36
+ stats
37
+ end
38
+
39
+ private
40
+
41
+ def extract_bytes
42
+ stats[SRC_BYTES] = retrieve_data.count.zero? ? 0 : retrieve_data.map { |d| d[BYTES] }
43
+ end
44
+
45
+ def calculate_retrieve_stats
46
+ stats[BPMS_RETR] = calculate_bytes_per_ms(retrieve_data)
47
+ stats[MSPB_RETR] = calculate_ms_per_byte(retrieve_data)
48
+ end
49
+
50
+ def calculate_graph_load_stats
51
+ stats[BPMS_GRPH] = calculate_bytes_per_ms(graph_load_data)
52
+ stats[MSPB_GRPH] = calculate_ms_per_byte(graph_load_data)
53
+ end
54
+
55
+ def calculate_normalization_stats
56
+ stats[BPMS_NORM] = calculate_bytes_per_ms(norm_data)
57
+ stats[MSPB_NORM] = calculate_ms_per_byte(norm_data)
58
+ end
59
+
60
+ def calculate_bytes_per_ms(data)
61
+ return 0 if data.count.zero?
62
+ return data[0][BYTES] / d[0][TIME] if data.count == 1
63
+ data.map { |d| d[BYTES] / d[TIME] }
64
+ end
65
+
66
+ def calculate_ms_per_byte(data)
67
+ return 0 if data.count.zero?
68
+ return data[0][TIME] / d[0][BYTES] if data.count == 1
69
+ data.map { |d| d[TIME] / d[BYTES] }
70
+ end
71
+
72
+ def data(column)
73
+ records.where.not(column => nil).order(dt_stamp: :desc).limit(n).pluck(column, :size_bytes)
74
+ end
75
+
76
+ def retrieve_data
77
+ @retrieve_data ||= data(:retrieve_time_ms)
78
+ end
79
+
80
+ def graph_load_data
81
+ @graph_data ||= data(:graph_load_time_ms)
82
+ end
83
+
84
+ def norm_data
85
+ @norm_data ||= data(:normalization_time_ms)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ # This class calculates performance stats based on size of data.
3
+ module QaServer
4
+ class PerformancePerByteDataService
5
+ class << self
6
+ include QaServer::PerformanceHistoryDataKeys
7
+
8
+ class_attribute :stats_calculator_class, :performance_data_class
9
+ self.stats_calculator_class = QaServer::PerformancePerByteCalculatorService
10
+ self.performance_data_class = QaServer::PerformanceHistory
11
+
12
+ # Performance data based on size of data.
13
+ # @param authority_name [String] name of an authority
14
+ # @param action [Symbol] :search, :fetch, or :all_actions
15
+ # @param n [Integer] calculate stats for last n records
16
+ # @returns [Hash] performance statistics based on size of data
17
+ # @example returns for n=2
18
+ # { data_raw_bytes_from_source: [16271, 16271],
19
+ # retrieve_bytes_per_ms: [67.24433786890475, 55.51210410757532],
20
+ # retrieve_ms_per_byte: [0.014871140555351083, 0.018014089288745542]
21
+ # graph_load_bytes_per_ms_ms: [86.74089418722461, 54.97464153778724],
22
+ # graph_load_ms_per_byte: [0.011528587632974647, 0.018190205011389522],
23
+ # normalization_bytes_per_ms: [64.70169466560836, 89.25337465693322],
24
+ # normalization_ms_per_byte: [0.01530700843338457, 0.015455545718983178]
25
+ # }
26
+ def calculate(authority_name:, action:, n: 10)
27
+ records = records_by(authority_name, action)
28
+ stats_calculator_class.new(records: records, n: n).calculate
29
+ end
30
+
31
+ private
32
+
33
+ def records_by(authority_name, action)
34
+ where_clause = {}
35
+ where_clause[:authority] = authority_name unless authority_name.nil? || authority_name == ALL_AUTH
36
+ where_clause[:action] = action unless action.nil? || action == ALL_ACTIONS
37
+ performance_data_class.where(where_clause)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -32,7 +32,7 @@ module QaServer
32
32
 
33
33
  def self.load_config(authority_name, status_log)
34
34
  scenarios_config = YAML.load_file(scenario_path(authority_name))
35
- unless scenarios_config.present?
35
+ if scenarios_config.blank?
36
36
  status_log.add(authority_name: authority_name,
37
37
  status: QaServer::ScenarioValidator::FAIL,
38
38
  error_message: "Unable to load scenarios for authority '#{authority_name}'; cause: UNKNOWN")
@@ -63,31 +63,31 @@ module QaServer
63
63
  where_with_authority(where_clause, auth_name, auth_table)
64
64
  end
65
65
 
66
- private
66
+ private
67
67
 
68
- def where_for_dt_stamp(dt_table, dt_column, time_period)
69
- end_range = QaServer::TimeService.current_time
70
- start_range = end_range - time_period
71
- where_clause = { dt_column => start_range..end_range }
72
- where_clause = { dt_table => where_clause } unless dt_table.nil?
73
- where_clause
74
- end
68
+ def where_for_dt_stamp(dt_table, dt_column, time_period)
69
+ end_range = QaServer::TimeService.current_time
70
+ start_range = end_range - time_period
71
+ where_clause = { dt_column => start_range..end_range }
72
+ where_clause = { dt_table => where_clause } unless dt_table.nil?
73
+ where_clause
74
+ end
75
75
 
76
- def where_with_authority(where_clause, auth_name, auth_table)
77
- return where_clause if auth_name.nil?
78
- if auth_table.nil?
79
- where_clause[:authority] = auth_name
80
- else
81
- where_clause[auth_table] = { authority: auth_name }
82
- end
83
- where_clause
76
+ def where_with_authority(where_clause, auth_name, auth_table)
77
+ return where_clause if auth_name.nil?
78
+ if auth_table.nil?
79
+ where_clause[:authority] = auth_name
80
+ else
81
+ where_clause[auth_table] = { authority: auth_name }
84
82
  end
83
+ where_clause
84
+ end
85
85
 
86
- def validate_params(auth_name, auth_table, dt_table)
87
- raise ArgumentError, "Do not specify auth_table when auth_name is not specified" if auth_table.present? && auth_name.nil?
88
- return if auth_name.nil?
89
- raise ArgumentError, "Either both table names need to be specified or neither" if auth_table.present? ^ dt_table.present?
90
- end
86
+ def validate_params(auth_name, auth_table, dt_table)
87
+ raise ArgumentError, "Do not specify auth_table when auth_name is not specified" if auth_table.present? && auth_name.nil?
88
+ return if auth_name.nil?
89
+ raise ArgumentError, "Either both table names need to be specified or neither" if auth_table.present? ^ dt_table.present?
90
+ end
91
91
  end
92
92
  end
93
93
  end