naf 1.1.4 → 2.0.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 (118) hide show
  1. data/Gemfile +4 -2
  2. data/app/assets/images/{papertrail_job.png → job.png} +0 -0
  3. data/app/assets/images/{papertrail_machine.png → machine.png} +0 -0
  4. data/app/assets/images/{papertrail_machine_runner.png → machine_runner.png} +0 -0
  5. data/app/assets/javascripts/col_reorder_with_resize.js +1228 -0
  6. data/app/assets/javascripts/dataTablesTemplates/applications.js +2 -1
  7. data/app/assets/javascripts/dataTablesTemplates/jobs.js +2 -1
  8. data/app/assets/javascripts/dataTablesTemplates/machine_runner_invocations.js +2 -1
  9. data/app/assets/javascripts/dataTablesTemplates/machine_runners.js +2 -1
  10. data/app/assets/javascripts/dataTablesTemplates/machines.js +2 -1
  11. data/app/assets/javascripts/jquery.dataTables.js +10339 -5103
  12. data/app/assets/javascripts/naf.js +1 -0
  13. data/app/assets/stylesheets/jquery_ui/jquery-ui-1.8.5.custom.css.erb +6 -6
  14. data/app/assets/stylesheets/min_naf/layout.css.scss +94 -43
  15. data/app/assets/stylesheets/naf/layout.css.scss +94 -43
  16. data/app/controllers/naf/affinities_controller.rb +1 -1
  17. data/app/controllers/naf/applications_controller.rb +3 -0
  18. data/app/controllers/naf/historical_job_affinity_tabs_controller.rb +1 -1
  19. data/app/controllers/naf/historical_jobs_controller.rb +2 -5
  20. data/app/controllers/naf/log_parsers_controller.rb +16 -0
  21. data/app/controllers/naf/log_viewer_controller.rb +19 -0
  22. data/app/controllers/naf/machine_affinity_slots_controller.rb +1 -1
  23. data/app/controllers/naf/machine_runners_controller.rb +12 -0
  24. data/app/controllers/naf/machines_controller.rb +8 -10
  25. data/app/controllers/naf/status_controller.rb +12 -0
  26. data/app/helpers/naf/application_helper.rb +19 -38
  27. data/app/helpers/naf/time_helper.rb +37 -0
  28. data/app/models/logical/naf/application.rb +13 -19
  29. data/app/models/logical/naf/construction_zone/boss.rb +1 -1
  30. data/app/models/logical/naf/construction_zone/foreman.rb +1 -1
  31. data/app/models/logical/naf/job.rb +39 -34
  32. data/app/models/logical/naf/job_creator.rb +19 -23
  33. data/app/models/logical/naf/job_fetcher.rb +36 -6
  34. data/app/models/logical/naf/log_file.rb +70 -0
  35. data/app/models/logical/naf/log_parser/base.rb +272 -0
  36. data/app/models/logical/naf/log_parser/job.rb +65 -0
  37. data/app/models/logical/naf/log_parser/machine.rb +64 -0
  38. data/app/models/logical/naf/log_parser/runner.rb +72 -0
  39. data/app/models/logical/naf/log_reader.rb +85 -0
  40. data/app/models/logical/naf/machine.rb +39 -1
  41. data/app/models/naf/affinity.rb +18 -0
  42. data/app/models/naf/application_schedule_affinity_tab.rb +1 -0
  43. data/app/models/naf/application_type.rb +2 -1
  44. data/app/models/naf/historical_job.rb +9 -29
  45. data/app/models/naf/machine.rb +8 -0
  46. data/app/models/naf/machine_runner.rb +11 -2
  47. data/app/models/naf/machine_runner_invocation.rb +9 -1
  48. data/app/models/naf/running_job.rb +40 -1
  49. data/app/models/process/naf/application.rb +3 -3
  50. data/app/models/process/naf/log_archiver.rb +78 -0
  51. data/app/models/process/naf/machine_manager.rb +3 -1
  52. data/app/models/process/naf/runner.rb +286 -162
  53. data/app/models/process/naf/runner_log.rb +26 -0
  54. data/app/views/naf/application_schedule_affinity_tabs/_form.html.erb +1 -5
  55. data/app/views/naf/applications/show.html.erb +1 -1
  56. data/app/views/naf/historical_job_affinity_tabs/_form.html.erb +1 -5
  57. data/app/views/naf/historical_jobs/_form.html.erb +1 -1
  58. data/app/views/naf/historical_jobs/_runners.html.erb +21 -12
  59. data/app/views/naf/historical_jobs/_search_container.html.erb +1 -2
  60. data/app/views/naf/historical_jobs/index.html.erb +0 -1
  61. data/app/views/naf/historical_jobs/index.json.erb +4 -4
  62. data/app/views/naf/historical_jobs/show.html.erb +57 -51
  63. data/app/views/naf/log_viewer/_job_logs.html.erb +65 -0
  64. data/app/views/naf/log_viewer/_log_display.html.erb +259 -0
  65. data/app/views/naf/log_viewer/_log_layout.html.erb +59 -0
  66. data/app/views/naf/log_viewer/_machine_logs.html.erb +62 -0
  67. data/app/views/naf/log_viewer/_runner_logs.html.erb +62 -0
  68. data/app/views/naf/log_viewer/_search_options.html.erb +36 -0
  69. data/app/views/naf/log_viewer/_update_page_title.html.erb +9 -0
  70. data/app/views/naf/log_viewer/index.html.erb +1 -0
  71. data/app/views/naf/logger_names/_form.html.erb +1 -2
  72. data/app/views/naf/machine_affinity_slots/_form.html.erb +1 -5
  73. data/app/views/naf/machine_runner_invocations/show.html.erb +4 -0
  74. data/app/views/naf/machine_runners/show.html.erb +44 -34
  75. data/app/views/naf/machines/index.json.erb +14 -6
  76. data/app/views/naf/machines/show.html.erb +44 -40
  77. data/app/views/naf/shared/_auto_resize_width.html.erb +7 -0
  78. data/app/views/naf/shared/_date_select.html.erb +65 -0
  79. data/app/views/naf/shared/_select_per_page.html.erb +48 -13
  80. data/app/views/naf/status/index.html.erb +27 -0
  81. data/bin/naf +26 -0
  82. data/config/initializers/naf.rb +13 -1
  83. data/config/routes.rb +16 -2
  84. data/db/migrate/20131106162436_add_uuid_column_to_machine_runner_invocations.rb +15 -0
  85. data/db/migrate/20131121185222_move_tabs_column_from_historical_jobs_to_running_jobs.rb +15 -0
  86. data/lib/generators/templates/config/logging/naf.yml +0 -8
  87. data/lib/generators/templates/config/logging/nafjob.yml +0 -8
  88. data/lib/generators/templates/config/logging/nafrunner.yml +0 -8
  89. data/lib/generators/templates/naf.rb +0 -8
  90. data/lib/naf.rb +0 -8
  91. data/lib/naf/configuration.rb +0 -4
  92. data/lib/naf/version.rb +1 -1
  93. data/lib/tasks/naf_tasks.rake +18 -0
  94. data/naf.gemspec +3 -1
  95. data/spec/controllers/naf/affinities_controller_spec.rb +0 -1
  96. data/spec/controllers/naf/applications_controller_spec.rb +3 -2
  97. data/spec/controllers/naf/machine_affinity_slots_controller_spec.rb +0 -1
  98. data/spec/controllers/naf/machines_controller_spec.rb +1 -1
  99. data/spec/dummy/config/logging/naf.yml +0 -8
  100. data/spec/dummy/config/logging/nafjob.yml +0 -9
  101. data/spec/dummy/config/logging/nafrunner.yml +0 -10
  102. data/spec/factories/naf.rb +4 -0
  103. data/spec/models/logical/naf/application_spec.rb +3 -4
  104. data/spec/models/logical/naf/job_creator_spec.rb +91 -21
  105. data/spec/models/logical/naf/job_spec.rb +19 -6
  106. data/spec/models/logical/naf/log_file_spec.rb +105 -0
  107. data/spec/models/logical/naf/machine_runner_invocation_spec.rb +41 -0
  108. data/spec/models/logical/naf/machine_runner_spec.rb +42 -0
  109. data/spec/models/logical/naf/machine_spec.rb +98 -28
  110. data/spec/models/naf/affinity_classification_spec.rb +20 -0
  111. data/spec/models/naf/affinity_spec.rb +21 -0
  112. data/spec/models/naf/historical_job_spec.rb +2 -44
  113. data/spec/models/naf/machine_runner_invocation_spec.rb +17 -1
  114. data/spec/models/naf/running_job_spec.rb +64 -1
  115. metadata +40 -9
  116. data/app/models/log4r/papertrail_outputter.rb +0 -19
  117. data/app/views/naf/historical_jobs/edit.html.erb +0 -11
  118. data/app/views/naf/machines/_show.html.erb +0 -169
@@ -14,17 +14,8 @@ module Logical
14
14
  # jobs (running/queued) is equal to or greater than the application
15
15
  # run group limit, or if enqueue_backlogs is set to false. If so,
16
16
  # do not add the job to the queue
17
- running_jobs = ::Naf::RunningJob.
18
- select('application_run_group_limit, MAX(created_at) AS created_at, count(*)').
19
- where('command = ? AND application_run_group_name = ?',
20
- application.command, application_run_group_name).
21
- group('application_run_group_name, application_run_group_limit').first
22
-
23
- queued_jobs = ::Naf::QueuedJob.
24
- select('application_run_group_limit, MAX(created_at) AS created_at, count(*)').
25
- where('command = ? AND application_run_group_name = ?',
26
- application.command, application_run_group_name).
27
- group('application_run_group_name, application_run_group_limit').first
17
+ running_jobs = retrieve_jobs(::Naf::RunningJob, application.command, application_run_group_name)
18
+ queued_jobs = retrieve_jobs(::Naf::QueuedJob, application.command, application_run_group_name)
28
19
 
29
20
  if enqueue == false && (running_jobs.present? || queued_jobs.present?)
30
21
  group_limit = running_jobs.try(:application_run_group_limit).to_i + queued_jobs.try(:application_run_group_limit).to_i
@@ -42,7 +33,6 @@ module Logical
42
33
  application_run_group_limit: application_run_group_limit,
43
34
  priority: priority,
44
35
  log_level: application.log_level)
45
- historical_job.add_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:pre_work]])
46
36
 
47
37
  # Create historical job affinity tabs for each affinity associated with the historical job
48
38
  affinities.each do |affinity|
@@ -55,12 +45,7 @@ module Logical
55
45
  affinity_parameter: affinity_parameter)
56
46
  end
57
47
 
58
- historical_job.verify_prerequisites(prerequisites)
59
- # Create historical job prerequisites for each prerequisite associated with the historical job
60
- prerequisites.each do |prerequisite|
61
- ::Naf::HistoricalJobPrerequisite.create(historical_job_id: historical_job.id,
62
- prerequisite_historical_job_id: prerequisite.id)
63
- end
48
+ verify_and_create_prerequisites(historical_job, prerequisites)
64
49
 
65
50
  create_queue_job(historical_job)
66
51
 
@@ -68,6 +53,12 @@ module Logical
68
53
  end
69
54
  end
70
55
 
56
+ def retrieve_jobs(klass, command, application_run_group_name)
57
+ klass.select('application_run_group_limit, MAX(created_at) AS created_at, count(*)').
58
+ where('command = ? AND application_run_group_name = ?', command, application_run_group_name).
59
+ group('application_run_group_name, application_run_group_limit').first
60
+ end
61
+
71
62
  def queue_application_schedule(application_schedule, schedules_queued_already = [])
72
63
  prerequisite_jobs = []
73
64
 
@@ -114,11 +105,7 @@ module Logical
114
105
  ::Naf::HistoricalJobAffinityTab.create(historical_job_id: historical_job.id, affinity_id: affinity.id)
115
106
  end
116
107
 
117
- historical_job.verify_prerequisites(prerequisites)
118
- prerequisites.each do |prerequisite|
119
- ::Naf::HistoricalJobPrerequisite.create(historical_job_id: historical_job.id,
120
- prerequisite_historical_job_id: prerequisite.id)
121
- end
108
+ verify_and_create_prerequisites(historical_job, prerequisites)
122
109
 
123
110
  create_queue_job(historical_job)
124
111
 
@@ -126,6 +113,15 @@ module Logical
126
113
  end
127
114
  end
128
115
 
116
+ def verify_and_create_prerequisites(job, prerequisites)
117
+ job.verify_prerequisites(prerequisites)
118
+ # Create historical job prerequisites for each prerequisite associated with the historical job
119
+ prerequisites.each do |prerequisite|
120
+ ::Naf::HistoricalJobPrerequisite.create(historical_job_id: job.id,
121
+ prerequisite_historical_job_id: prerequisite.id)
122
+ end
123
+ end
124
+
129
125
  def create_queue_job(historical_job)
130
126
  queued_job = ::Naf::QueuedJob.new(application_id: historical_job.application_id,
131
127
  application_type_id: historical_job.application_type_id,
@@ -18,8 +18,8 @@ module Logical
18
18
 
19
19
  if running_job.present?
20
20
  # Update tags
21
- running_job.historical_job.remove_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:pre_work]])
22
- running_job.historical_job.add_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:work]])
21
+ running_job.remove_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:pre_work]])
22
+ running_job.add_tags([::Naf::HistoricalJob::SYSTEM_TAGS[:work]])
23
23
 
24
24
  # found a job
25
25
  parse_log_level(running_job)
@@ -142,8 +142,7 @@ module Logical
142
142
  log_levels = {}
143
143
  unless machine.log_level.blank?
144
144
  begin
145
- log_level_hash = JSON.parse(machine.log_level)
146
- log_levels.merge!(log_level_hash)
145
+ log_levels.merge!(retrieve_log_levels(machine.log_level))
147
146
  rescue StandardError => e
148
147
  logger.error "couldn't parse machine.log_level: #{machine.log_level}: (#{e.message})"
149
148
  end
@@ -151,17 +150,48 @@ module Logical
151
150
 
152
151
  unless running_job.application.nil? || running_job.application.log_level.blank?
153
152
  begin
154
- log_level_hash = JSON.parse(running_job.application.log_level)
155
- log_levels.merge!(log_level_hash)
153
+ log_levels.merge!(retrieve_log_levels(running_job.application.log_level, running_job.application.command))
156
154
  rescue StandardError => e
157
155
  logger.error "couldn't parse running_job.application.log_level: #{running_job.application.log_level}: (#{e.message})"
158
156
  end
159
157
  end
160
158
 
161
159
  running_job.log_level = log_levels.to_json
160
+ running_job.historical_job.log_level = log_levels.to_json
161
+ running_job.historical_job.save!
162
162
  running_job.save!
163
163
  end
164
164
 
165
+ def retrieve_log_levels(log_level, command = nil)
166
+ log_level_hash = {}
167
+
168
+ if log_level[0] == '{'
169
+ # String is in JSON format
170
+ log_level_hash = JSON.parse(log_level)
171
+ else
172
+ if log_level.include?('=')
173
+ # Pairs of logger_name=logger_level were given
174
+ log_level.split(',').each do |elem|
175
+ name, level = elem.split('=')
176
+ log_level_hash[name.strip.to_sym] = level.strip
177
+ end
178
+ else
179
+ # Only log level threshold was given
180
+ if command.present?
181
+ key = command.split('.').first
182
+ if key[0..1] == '::'
183
+ key = key[2..-1]
184
+ end
185
+ log_level_hash[key] = log_level
186
+ else
187
+ log_level_hash[:default] = log_level
188
+ end
189
+ end
190
+ end
191
+
192
+ log_level_hash
193
+ end
194
+
165
195
  end
166
196
  end
167
197
  end
@@ -0,0 +1,70 @@
1
+ module Logical
2
+ module Naf
3
+ class LogFile
4
+ LOG_MAX_SIZE = 50_000
5
+
6
+ attr_reader :file_line_number,
7
+ :line_number,
8
+ :file,
9
+ :log_area,
10
+ :lines_cache
11
+
12
+ def initialize(log_area)
13
+ @file_line_number = @line_number = 1
14
+ @file = nil
15
+ @log_area = log_area
16
+ @lines_cache = ''
17
+ end
18
+
19
+ def <<(message)
20
+ log_line = JSON.pretty_generate({
21
+ line_number: line_number,
22
+ output_time: Time.zone.now.strftime("%Y-%m-%d %H:%M:%S.%L"),
23
+ message: message
24
+ })
25
+ @lines_cache << log_line
26
+ @line_number += 1
27
+ end
28
+
29
+ def write
30
+ check_file_size
31
+ output = lines_cache
32
+ unless output.blank?
33
+ file.write(output)
34
+ @lines_cache = ''
35
+ flush
36
+ end
37
+ end
38
+
39
+ def flush
40
+ file.flush
41
+ end
42
+
43
+ def open
44
+ # Create the directory path if it doesn't exist
45
+ FileUtils.mkdir_p(log_area)
46
+
47
+ filename = Dir[log_area + "/#{file_line_number}_*"].first
48
+ if filename.blank?
49
+ @file = File.open(log_area + "/#{file_line_number}_#{Time.zone.now.strftime('%Y%m%d_%H%M%S')}.json", 'wb')
50
+ else
51
+ @file = File.open(filename, 'wb')
52
+ end
53
+ end
54
+
55
+ def close
56
+ @file.try(:close)
57
+ @file = nil
58
+ end
59
+
60
+ def check_file_size
61
+ if file.size > LOG_MAX_SIZE
62
+ @file_line_number = line_number
63
+ close
64
+ @file = File.open(log_area + "/#{file_line_number}_#{Time.zone.now.strftime('%Y%m%d_%H%M%S')}.json", 'wb')
65
+ end
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,272 @@
1
+ require 'yajl'
2
+
3
+ module Logical::Naf
4
+ module LogParser
5
+ class Base
6
+
7
+ REGEX_OPTIONS = {
8
+ 'i' => Regexp::IGNORECASE,
9
+ 'x' => Regexp::EXTENDED,
10
+ 'm' => Regexp::MULTILINE
11
+ }
12
+ DATE_REGEX = /((\d){8}_(\d){6})/
13
+ UUID_REGEX = /[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/
14
+ LOG_SIZE_CHUNKS = 500
15
+
16
+ attr_accessor :search_params,
17
+ :regex_options,
18
+ :grep,
19
+ :search_from_time,
20
+ :search_to_time,
21
+ :jsons,
22
+ :logs_size,
23
+ :log_type,
24
+ :newest_log,
25
+ :record_id,
26
+ :read_from_s3,
27
+ :s3_log_reader,
28
+ :last_file_checked,
29
+ :newest_file_checked
30
+
31
+ def initialize(params)
32
+ @search_params = params['search_params'].nil? ? '' : params['search_params']
33
+ @regex_options = get_option_value(params['regex_options'])
34
+ @grep = params['grep']
35
+ @search_from_time = params['from_time']
36
+ @search_to_time = params['to_time']
37
+ @jsons = []
38
+ @logs_size = 0
39
+ @log_type = params['log_type']
40
+ @newest_log = params['newest_log']
41
+ @record_id = params['record_id']
42
+ @read_from_s3 = params['read_from_s3']
43
+ @last_file_checked = params['last_file_checked']
44
+ @newest_file_checked = params['newest_file_checked']
45
+ end
46
+
47
+ def retrieve_logs
48
+ parse_files
49
+
50
+ check_repeated_logs
51
+
52
+ output = ''
53
+ jsons.reverse_each do |elem|
54
+ output.insert(0, insert_log_line(elem))
55
+ end
56
+
57
+ return {
58
+ logs: output.html_safe,
59
+ read_from_s3: read_from_s3,
60
+ last_file_checked: last_file_checked,
61
+ newest_file_checked: newest_file_checked,
62
+ newest_log: newest_log
63
+ }
64
+ end
65
+
66
+ def check_repeated_logs
67
+ if log_type == 'new' && newest_log.present?
68
+ @jsons.each_with_index do |elem, index|
69
+ if parse_log(elem) == parse_newest_log
70
+ @jsons = @jsons[(index + 1)..-1]
71
+ return
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ def parse_log(log)
78
+ if log['message'].scan(/\t/).present?
79
+ message = log['message'].clone
80
+ message.slice!('<top (required)>')
81
+ "#{log['output_time']} #{message}"
82
+ else
83
+ "#{log['output_time']} #{log['message']}"
84
+ end
85
+ end
86
+
87
+ def parse_files
88
+ files = filter_files
89
+
90
+ files.each do |file|
91
+ # Use Yajl JSON library to parse the log files, as they contain multiple JSON blocks
92
+ parser = Yajl::Parser.new
93
+ json = get_json_from_log_file(file)
94
+ parser.parse(json) do |log|
95
+ if self.class.to_s == 'Logical::Naf::LogParser::Runner'
96
+ log['id'] = get_invocation_id(file.scan(UUID_REGEX).first)
97
+ elsif self.class.to_s == 'Logical::Naf::LogParser::Machine'
98
+ log['job_id'] = get_job_id(file)
99
+ end
100
+ filter_log_messages(log)
101
+ end
102
+
103
+ sort_jsons
104
+
105
+ if logs_size >= LOG_SIZE_CHUNKS
106
+ update_last_file_checked(file.scan(/\d+_\d{8}_\d{6}.*/).first)
107
+ break
108
+ end
109
+ end
110
+
111
+ if logs_size < LOG_SIZE_CHUNKS && files.present?
112
+ update_last_file_checked(files.last.scan(/\d+_\d{8}_\d{6}.*/).first)
113
+ end
114
+ end
115
+
116
+ def update_last_file_checked(file)
117
+ if file.present? && last_file_checked.present? && last_file_checked != 'null'
118
+ if Time.parse(file.scan(/\d{8}_\d{6}/).first) < Time.parse(last_file_checked.scan(/\d{8}_\d{6}/).first)
119
+ @last_file_checked = file
120
+ end
121
+ elsif file.present?
122
+ @last_file_checked = file
123
+ end
124
+ end
125
+
126
+ def get_json_from_log_file(file)
127
+ if read_from_s3 == 'true' && s3_log_reader.present?
128
+ s3_log_reader.retrieve_file(file)
129
+ else
130
+ File.new(file, 'r')
131
+ end
132
+ end
133
+
134
+ def filter_files
135
+ files = get_files
136
+ original_size = files.size
137
+
138
+ files.each_with_index do |file, index|
139
+ filename = file.scan(/\d+_\d{8}_\d{6}.*/).first
140
+
141
+ if log_type == 'old'
142
+ if filename == last_file_checked
143
+ if files.size == 1
144
+ files = []
145
+ else
146
+ files = files[(index + 1)..-1]
147
+ end
148
+ end
149
+
150
+ if files.size == 0 && read_from_s3 != 'true'
151
+ get_s3_files do
152
+ @read_from_s3 = 'true'
153
+ @s3_log_reader = ::Logical::Naf::LogReader.new
154
+ return retrieve_log_files_from_s3
155
+ end
156
+ end
157
+ elsif log_type == 'new'
158
+ if filename == newest_file_checked
159
+ if files.size == 1
160
+ files = []
161
+ else
162
+ files = files[0..(index - 1)]
163
+ end
164
+ end
165
+ end
166
+
167
+ break if original_size != files.size
168
+ end
169
+
170
+ if files.present?
171
+ if newest_file_checked.blank? || newest_file_checked == 'null'
172
+ @newest_file_checked = files[0].scan(/\d+_\d{8}_\d{6}.*/).first
173
+ else
174
+ if Time.parse(newest_file_checked.scan(DATE_REGEX)[0][0]) < Time.parse(files[0].scan(DATE_REGEX)[0][0])
175
+ @newest_file_checked = files[0].scan(/\d+_\d{8}_\d{6}.*/).first
176
+ end
177
+ end
178
+ end
179
+
180
+ return files
181
+ end
182
+
183
+ def filter_log_messages(log)
184
+ # Check that the message matches the search query. Highlight the matching results
185
+ if search_params.present?
186
+ log['message'].scan(Regexp.new(search_params, regex_options)).each do |match|
187
+ log['message'].gsub!(match, "<span style='background-color:yellow;'>#{match}</span>")
188
+ end
189
+ end
190
+
191
+ # Check that the log happened within the time range specified
192
+ if log_within_time_range(log['output_time'])
193
+ # If grep is selected, only show log messages that match the
194
+ # search query. Otherwise, show all log messages.
195
+ if grep == 'false' || log['message'] =~ Regexp.new(search_params, regex_options)
196
+ @jsons << log
197
+ @logs_size += 1
198
+ end
199
+ end
200
+ end
201
+
202
+ def log_within_time_range(log_time)
203
+ return true if (search_from_time.join('').blank? && search_to_time.join('').blank?) || log_time.blank?
204
+
205
+ if search_from_time.join('').present? && search_to_time.join('').present?
206
+ Time.parse(log_time) <= Time.parse(build_time_string(search_to_time)) &&
207
+ Time.parse(log_time) >= Time.parse(build_time_string(search_from_time))
208
+ elsif search_from_time.join('').present?
209
+ Time.parse(log_time) >= Time.parse(build_time_string(search_from_time))
210
+ elsif search_to_time.join('').present?
211
+ Time.parse(log_time) <= Time.parse(build_time_string(search_to_time))
212
+ end
213
+ end
214
+
215
+ def build_time_string(search_time)
216
+ # Year
217
+ search_built_time = search_time[0] + "-"
218
+ # Month
219
+ if search_time[1].to_i < 10
220
+ search_built_time << '0' + search_time[1] + '-'
221
+ else
222
+ search_built_time << search_time[1] + '-'
223
+ end
224
+ # Day
225
+ if search_time[2].to_i < 10
226
+ search_built_time << '0' + search_time[2] + ' '
227
+ else
228
+ search_built_time << search_time[2] + ' '
229
+ end
230
+ # Hour
231
+ search_built_time << search_time[3] + ':'
232
+ # Minute
233
+ if search_time[4].to_i < 10
234
+ search_built_time << '0' + search_time[4]
235
+ else
236
+ search_built_time << search_time[4]
237
+ end
238
+ # Second
239
+ search_built_time << ':00 -0500'
240
+
241
+ search_built_time
242
+ end
243
+
244
+ def get_option_value(options)
245
+ return 0 if options.blank?
246
+
247
+ options = options.split(//)
248
+ result = 0
249
+ options.each do |opt|
250
+ result |= REGEX_OPTIONS[opt]
251
+ end
252
+
253
+ result
254
+ end
255
+
256
+ def get_s3_files
257
+ begin
258
+ yield
259
+ rescue
260
+ @jsons << {
261
+ 'line_number' => 0,
262
+ 'output_time' => Time.zone.now.strftime("%Y-%m-%d %H:%M:%S.%L"),
263
+ 'message' => 'AWS S3 Access Denied. Please check your permissions.'
264
+ }
265
+
266
+ return []
267
+ end
268
+ end
269
+
270
+ end
271
+ end
272
+ end