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.
- data/Gemfile +4 -2
- data/app/assets/images/{papertrail_job.png → job.png} +0 -0
- data/app/assets/images/{papertrail_machine.png → machine.png} +0 -0
- data/app/assets/images/{papertrail_machine_runner.png → machine_runner.png} +0 -0
- data/app/assets/javascripts/col_reorder_with_resize.js +1228 -0
- data/app/assets/javascripts/dataTablesTemplates/applications.js +2 -1
- data/app/assets/javascripts/dataTablesTemplates/jobs.js +2 -1
- data/app/assets/javascripts/dataTablesTemplates/machine_runner_invocations.js +2 -1
- data/app/assets/javascripts/dataTablesTemplates/machine_runners.js +2 -1
- data/app/assets/javascripts/dataTablesTemplates/machines.js +2 -1
- data/app/assets/javascripts/jquery.dataTables.js +10339 -5103
- data/app/assets/javascripts/naf.js +1 -0
- data/app/assets/stylesheets/jquery_ui/jquery-ui-1.8.5.custom.css.erb +6 -6
- data/app/assets/stylesheets/min_naf/layout.css.scss +94 -43
- data/app/assets/stylesheets/naf/layout.css.scss +94 -43
- data/app/controllers/naf/affinities_controller.rb +1 -1
- data/app/controllers/naf/applications_controller.rb +3 -0
- data/app/controllers/naf/historical_job_affinity_tabs_controller.rb +1 -1
- data/app/controllers/naf/historical_jobs_controller.rb +2 -5
- data/app/controllers/naf/log_parsers_controller.rb +16 -0
- data/app/controllers/naf/log_viewer_controller.rb +19 -0
- data/app/controllers/naf/machine_affinity_slots_controller.rb +1 -1
- data/app/controllers/naf/machine_runners_controller.rb +12 -0
- data/app/controllers/naf/machines_controller.rb +8 -10
- data/app/controllers/naf/status_controller.rb +12 -0
- data/app/helpers/naf/application_helper.rb +19 -38
- data/app/helpers/naf/time_helper.rb +37 -0
- data/app/models/logical/naf/application.rb +13 -19
- data/app/models/logical/naf/construction_zone/boss.rb +1 -1
- data/app/models/logical/naf/construction_zone/foreman.rb +1 -1
- data/app/models/logical/naf/job.rb +39 -34
- data/app/models/logical/naf/job_creator.rb +19 -23
- data/app/models/logical/naf/job_fetcher.rb +36 -6
- data/app/models/logical/naf/log_file.rb +70 -0
- data/app/models/logical/naf/log_parser/base.rb +272 -0
- data/app/models/logical/naf/log_parser/job.rb +65 -0
- data/app/models/logical/naf/log_parser/machine.rb +64 -0
- data/app/models/logical/naf/log_parser/runner.rb +72 -0
- data/app/models/logical/naf/log_reader.rb +85 -0
- data/app/models/logical/naf/machine.rb +39 -1
- data/app/models/naf/affinity.rb +18 -0
- data/app/models/naf/application_schedule_affinity_tab.rb +1 -0
- data/app/models/naf/application_type.rb +2 -1
- data/app/models/naf/historical_job.rb +9 -29
- data/app/models/naf/machine.rb +8 -0
- data/app/models/naf/machine_runner.rb +11 -2
- data/app/models/naf/machine_runner_invocation.rb +9 -1
- data/app/models/naf/running_job.rb +40 -1
- data/app/models/process/naf/application.rb +3 -3
- data/app/models/process/naf/log_archiver.rb +78 -0
- data/app/models/process/naf/machine_manager.rb +3 -1
- data/app/models/process/naf/runner.rb +286 -162
- data/app/models/process/naf/runner_log.rb +26 -0
- data/app/views/naf/application_schedule_affinity_tabs/_form.html.erb +1 -5
- data/app/views/naf/applications/show.html.erb +1 -1
- data/app/views/naf/historical_job_affinity_tabs/_form.html.erb +1 -5
- data/app/views/naf/historical_jobs/_form.html.erb +1 -1
- data/app/views/naf/historical_jobs/_runners.html.erb +21 -12
- data/app/views/naf/historical_jobs/_search_container.html.erb +1 -2
- data/app/views/naf/historical_jobs/index.html.erb +0 -1
- data/app/views/naf/historical_jobs/index.json.erb +4 -4
- data/app/views/naf/historical_jobs/show.html.erb +57 -51
- data/app/views/naf/log_viewer/_job_logs.html.erb +65 -0
- data/app/views/naf/log_viewer/_log_display.html.erb +259 -0
- data/app/views/naf/log_viewer/_log_layout.html.erb +59 -0
- data/app/views/naf/log_viewer/_machine_logs.html.erb +62 -0
- data/app/views/naf/log_viewer/_runner_logs.html.erb +62 -0
- data/app/views/naf/log_viewer/_search_options.html.erb +36 -0
- data/app/views/naf/log_viewer/_update_page_title.html.erb +9 -0
- data/app/views/naf/log_viewer/index.html.erb +1 -0
- data/app/views/naf/logger_names/_form.html.erb +1 -2
- data/app/views/naf/machine_affinity_slots/_form.html.erb +1 -5
- data/app/views/naf/machine_runner_invocations/show.html.erb +4 -0
- data/app/views/naf/machine_runners/show.html.erb +44 -34
- data/app/views/naf/machines/index.json.erb +14 -6
- data/app/views/naf/machines/show.html.erb +44 -40
- data/app/views/naf/shared/_auto_resize_width.html.erb +7 -0
- data/app/views/naf/shared/_date_select.html.erb +65 -0
- data/app/views/naf/shared/_select_per_page.html.erb +48 -13
- data/app/views/naf/status/index.html.erb +27 -0
- data/bin/naf +26 -0
- data/config/initializers/naf.rb +13 -1
- data/config/routes.rb +16 -2
- data/db/migrate/20131106162436_add_uuid_column_to_machine_runner_invocations.rb +15 -0
- data/db/migrate/20131121185222_move_tabs_column_from_historical_jobs_to_running_jobs.rb +15 -0
- data/lib/generators/templates/config/logging/naf.yml +0 -8
- data/lib/generators/templates/config/logging/nafjob.yml +0 -8
- data/lib/generators/templates/config/logging/nafrunner.yml +0 -8
- data/lib/generators/templates/naf.rb +0 -8
- data/lib/naf.rb +0 -8
- data/lib/naf/configuration.rb +0 -4
- data/lib/naf/version.rb +1 -1
- data/lib/tasks/naf_tasks.rake +18 -0
- data/naf.gemspec +3 -1
- data/spec/controllers/naf/affinities_controller_spec.rb +0 -1
- data/spec/controllers/naf/applications_controller_spec.rb +3 -2
- data/spec/controllers/naf/machine_affinity_slots_controller_spec.rb +0 -1
- data/spec/controllers/naf/machines_controller_spec.rb +1 -1
- data/spec/dummy/config/logging/naf.yml +0 -8
- data/spec/dummy/config/logging/nafjob.yml +0 -9
- data/spec/dummy/config/logging/nafrunner.yml +0 -10
- data/spec/factories/naf.rb +4 -0
- data/spec/models/logical/naf/application_spec.rb +3 -4
- data/spec/models/logical/naf/job_creator_spec.rb +91 -21
- data/spec/models/logical/naf/job_spec.rb +19 -6
- data/spec/models/logical/naf/log_file_spec.rb +105 -0
- data/spec/models/logical/naf/machine_runner_invocation_spec.rb +41 -0
- data/spec/models/logical/naf/machine_runner_spec.rb +42 -0
- data/spec/models/logical/naf/machine_spec.rb +98 -28
- data/spec/models/naf/affinity_classification_spec.rb +20 -0
- data/spec/models/naf/affinity_spec.rb +21 -0
- data/spec/models/naf/historical_job_spec.rb +2 -44
- data/spec/models/naf/machine_runner_invocation_spec.rb +17 -1
- data/spec/models/naf/running_job_spec.rb +64 -1
- metadata +40 -9
- data/app/models/log4r/papertrail_outputter.rb +0 -19
- data/app/views/naf/historical_jobs/edit.html.erb +0 -11
- 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
|
-
|
|
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
|
|
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
|
|
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.
|
|
22
|
-
running_job.
|
|
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
|
-
|
|
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
|
-
|
|
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
|