fluentd-ui 0.3.14 → 0.3.15
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.
Potentially problematic release.
This version of fluentd-ui might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/ChangeLog +5 -0
- data/Gemfile.lock +2 -2
- data/app/controllers/concerns/setting_concern.rb +1 -1
- data/app/controllers/concerns/setting_history_concern.rb +1 -1
- data/app/controllers/fluentd/agents_controller.rb +3 -3
- data/app/controllers/fluentd/settings_controller.rb +1 -1
- data/app/controllers/fluentd_controller.rb +2 -2
- data/app/controllers/misc_controller.rb +1 -1
- data/app/controllers/tutorials_controller.rb +1 -1
- data/app/models/fluentd/agent/common.rb +72 -37
- data/app/models/fluentd/agent/fluentd_gem.rb +4 -1
- data/app/models/fluentd/agent/process_operation.rb +61 -0
- data/app/models/fluentd/agent/td_agent.rb +0 -1
- data/app/models/fluentd/setting/out_mongo.rb +3 -2
- data/app/models/fluentd/setting/out_s3.rb +6 -7
- data/app/models/fluentd/setting/out_td.rb +1 -0
- data/app/models/fluentd_log.rb +123 -0
- data/lib/fluentd-ui/version.rb +1 -1
- data/spec/controllers/fluentd/agents_controller_spec.rb +6 -2
- data/spec/controllers/misc_controller_spec.rb +2 -2
- data/spec/models/fluentd/agent/{local_common_spec.rb → common_spec.rb} +2 -2
- data/spec/models/fluentd_log_spec.rb +171 -0
- data/spec/support/fluentd_agent_common_behavior.rb +5 -5
- metadata +52 -95
- data/app/models/fluentd/agent/local_common.rb +0 -201
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6bc6e3afc054e9c31d53f4cbcdf624a5747b86b8
|
4
|
+
data.tar.gz: 92a4781f7b6ee8a42f44e99bd7ce1b52a74c2c63
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 989ffd56a8d254b321a3b7c267fff4876a0e1ae35dee49181074799866f3b4d17b61a5532f18f72acb13ef7539729a4899693ffc8a4985d8edee68087895e1cb
|
7
|
+
data.tar.gz: b781c709a136ab244b0d117977935e92790ed11860ec949ecaf688def91689ea6f8161724f07d4e569d3ba1f449d5a62bda41946f4c1f46b082a75e181573590
|
data/ChangeLog
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
Release 0.3.15 - 2015/03/11
|
2
|
+
* [fixed] #159 Fix latest out_s3 plugin compatibility
|
3
|
+
* [fixed] #160 Add validation that `buffer_path` required if `buffer_type` is file
|
4
|
+
* [maintenance] Minor refactors
|
5
|
+
|
1
6
|
Release 0.3.14 - 2015/02/04
|
2
7
|
* [maintenance] #150, #151 minor fix in README.md.
|
3
8
|
* [maintenance] #149 Make circle-ci result stable.
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fluentd-ui (0.3.
|
4
|
+
fluentd-ui (0.3.15)
|
5
5
|
addressable
|
6
6
|
bundler
|
7
7
|
diff-lcs
|
@@ -141,7 +141,7 @@ GEM
|
|
141
141
|
mime-types (2.4.3)
|
142
142
|
mini_portile (0.6.2)
|
143
143
|
minitest (5.5.1)
|
144
|
-
msgpack (0.5.
|
144
|
+
msgpack (0.5.11)
|
145
145
|
multi_json (1.10.1)
|
146
146
|
net-http-digest_auth (1.4)
|
147
147
|
net-http-persistent (2.9.4)
|
@@ -22,7 +22,7 @@ module SettingConcern
|
|
22
22
|
@fluentd.agent.config_append @setting.to_config
|
23
23
|
if @fluentd.agent.running?
|
24
24
|
unless @fluentd.agent.restart
|
25
|
-
@setting.errors.add(:base, @fluentd.agent.
|
25
|
+
@setting.errors.add(:base, @fluentd.agent.log.tail(1).first)
|
26
26
|
return render "shared/settings/show"
|
27
27
|
end
|
28
28
|
end
|
@@ -26,7 +26,7 @@ module SettingHistoryConcern
|
|
26
26
|
if @fluentd.agent.dryrun
|
27
27
|
flash = { success: t('messages.dryrun_is_passed') }
|
28
28
|
else
|
29
|
-
flash = { danger: @fluentd.agent.
|
29
|
+
flash = { danger: @fluentd.agent.log.tail(1).first }
|
30
30
|
end
|
31
31
|
redirect_to :back, flash: flash
|
32
32
|
end
|
@@ -2,7 +2,7 @@ class Fluentd::AgentsController < ApplicationController
|
|
2
2
|
before_action :find_fluentd
|
3
3
|
|
4
4
|
def start
|
5
|
-
run_action(__method__) { @fluentd.agent.
|
5
|
+
run_action(__method__) { @fluentd.agent.log.tail(1).first }
|
6
6
|
redirect_to daemon_path(@fluentd), status: 303 # 303 is change HTTP Verb GET
|
7
7
|
end
|
8
8
|
|
@@ -12,12 +12,12 @@ class Fluentd::AgentsController < ApplicationController
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def restart
|
15
|
-
run_action(__method__) { @fluentd.agent.
|
15
|
+
run_action(__method__) { @fluentd.agent.log.tail(1).first }
|
16
16
|
redirect_to daemon_path(@fluentd), status: 303 # 303 is change HTTP Verb GET
|
17
17
|
end
|
18
18
|
|
19
19
|
def log_tail
|
20
|
-
@logs = @fluentd.agent.
|
20
|
+
@logs = @fluentd.agent.log.tail(params[:limit]).reverse if @fluentd
|
21
21
|
render json: @logs
|
22
22
|
end
|
23
23
|
|
@@ -39,7 +39,7 @@ class Fluentd::SettingsController < ApplicationController
|
|
39
39
|
if dryrun(params[:config])
|
40
40
|
flash.now[:success] = I18n.t('messages.dryrun_is_passed')
|
41
41
|
else
|
42
|
-
flash.now[:danger] = @fluentd.agent.last_error_message
|
42
|
+
flash.now[:danger] = @fluentd.agent.log.last_error_message
|
43
43
|
end
|
44
44
|
@config = params[:config]
|
45
45
|
render "edit"
|
@@ -41,11 +41,11 @@ class FluentdController < ApplicationController
|
|
41
41
|
|
42
42
|
def errors
|
43
43
|
@error_duration_days = 5
|
44
|
-
@errors = @fluentd.agent.errors_since(@error_duration_days.days.ago)
|
44
|
+
@errors = @fluentd.agent.log.errors_since(@error_duration_days.days.ago)
|
45
45
|
end
|
46
46
|
|
47
47
|
def raw_log
|
48
|
-
send_data @fluentd.agent.log, type: "application/octet-stream", filename: File.basename(@fluentd.log_file)
|
48
|
+
send_data @fluentd.agent.log.read, type: "application/octet-stream", filename: File.basename(@fluentd.log_file)
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
@@ -38,7 +38,7 @@ class MiscController < ApplicationController
|
|
38
38
|
File.unlink(path) if File.exists?(path)
|
39
39
|
|
40
40
|
Zip::File.open(path, Zip::File::CREATE) do |zip|
|
41
|
-
zip.get_output_stream('fluentd.log') {|f| f.puts fluentd.agent.log }
|
41
|
+
zip.get_output_stream('fluentd.log') {|f| f.puts fluentd.agent.log.read }
|
42
42
|
zip.add("fluentd-ui.log", log_path)
|
43
43
|
|
44
44
|
add_env_file_to(zip)
|
@@ -19,34 +19,19 @@ class Fluentd
|
|
19
19
|
module Common
|
20
20
|
attr_reader :extra_options
|
21
21
|
|
22
|
-
def
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
def wait_process_starting_seconds
|
27
|
-
10.seconds # wait time for fluentd pidfile created
|
28
|
-
end
|
29
|
-
|
30
|
-
def errors_since(since = 1.day.ago)
|
31
|
-
errors = []
|
32
|
-
logged_errors do |error|
|
33
|
-
break if Time.parse(error[:subject]) < since
|
34
|
-
errors << error
|
35
|
-
end
|
36
|
-
errors
|
22
|
+
def self.included(base)
|
23
|
+
base.send(:include, Fluentd::Agent::ProcessOperation)
|
37
24
|
end
|
38
25
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
break if errors.length >= limit
|
26
|
+
# define these methods on each Agent class
|
27
|
+
%w(start stop restart version).each do |method|
|
28
|
+
define_method(method) do
|
29
|
+
raise NotImplementedError, "'#{method}' method is required to be defined"
|
44
30
|
end
|
45
|
-
errors
|
46
31
|
end
|
47
32
|
|
48
|
-
def
|
49
|
-
|
33
|
+
def initialize(options = {})
|
34
|
+
@extra_options = options
|
50
35
|
end
|
51
36
|
|
52
37
|
def pid_file
|
@@ -57,16 +42,59 @@ class Fluentd
|
|
57
42
|
extra_options[:log_file] || self.class.default_options[:log_file]
|
58
43
|
end
|
59
44
|
|
45
|
+
def log
|
46
|
+
@log ||= FluentdLog.new(log_file)
|
47
|
+
end
|
48
|
+
|
60
49
|
def config_file
|
61
50
|
extra_options[:config_file] || self.class.default_options[:config_file]
|
62
51
|
end
|
63
52
|
|
53
|
+
# -- config
|
54
|
+
def config
|
55
|
+
File.read(config_file)
|
56
|
+
end
|
57
|
+
|
58
|
+
def config_write(content)
|
59
|
+
backup_config
|
60
|
+
File.open(config_file, "w") do |f|
|
61
|
+
f.write content
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def config_append(content)
|
66
|
+
backup_config
|
67
|
+
File.open(config_file, "a") do |f|
|
68
|
+
f.write "\n"
|
69
|
+
f.write content
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def configuration
|
74
|
+
if File.exists? config_file
|
75
|
+
::Fluentd::Agent::Configuration.new(config_file)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# -- backup methods
|
64
80
|
def config_backup_dir
|
65
81
|
dir = File.join(FluentdUI.data_dir, "#{Rails.env}_confg_backups")
|
66
82
|
FileUtils.mkdir_p(dir)
|
67
83
|
dir
|
68
84
|
end
|
69
85
|
|
86
|
+
def backup_files
|
87
|
+
Dir.glob(File.join("#{config_backup_dir}", "*.conf"))
|
88
|
+
end
|
89
|
+
|
90
|
+
def backup_files_in_old_order
|
91
|
+
backup_files.sort
|
92
|
+
end
|
93
|
+
|
94
|
+
def backup_files_in_new_order
|
95
|
+
backup_files_in_old_order.reverse
|
96
|
+
end
|
97
|
+
|
70
98
|
def running_config_backup_dir
|
71
99
|
dir = File.join(FluentdUI.data_dir, "#{Rails.env}_running_confg_backup")
|
72
100
|
FileUtils.mkdir_p(dir)
|
@@ -77,20 +105,7 @@ class Fluentd
|
|
77
105
|
File.join(running_config_backup_dir, "running.conf")
|
78
106
|
end
|
79
107
|
|
80
|
-
#
|
81
|
-
|
82
|
-
%w(start stop restart).each do |method|
|
83
|
-
define_method(method) do
|
84
|
-
raise NotImplementedError, "'#{method}' method is required to be defined"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
%w(running? version log config config_write config_append log_tail configuration).each do |method|
|
89
|
-
define_method(method) do
|
90
|
-
raise NotImplementedError, "'#{method}' method is required to be defined"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
108
|
+
# -------------- private --------------
|
94
109
|
private
|
95
110
|
|
96
111
|
def backup_running_config
|
@@ -103,6 +118,26 @@ class Fluentd
|
|
103
118
|
|
104
119
|
true
|
105
120
|
end
|
121
|
+
|
122
|
+
def backup_config
|
123
|
+
return unless File.exists? config_file
|
124
|
+
|
125
|
+
FileUtils.cp config_file, File.join(config_backup_dir, "#{Time.zone.now.strftime('%Y%m%d_%H%M%S')}.conf")
|
126
|
+
|
127
|
+
remove_over_backup_files
|
128
|
+
end
|
129
|
+
|
130
|
+
def remove_over_backup_files
|
131
|
+
over_file_count = backup_files.size - ::Settings.max_backup_files_count
|
132
|
+
|
133
|
+
return if over_file_count <= 0
|
134
|
+
|
135
|
+
backup_files_in_old_order.first(over_file_count).each do |file|
|
136
|
+
note_file_attached_backup = file.sub(/#{Regexp.escape(File.extname(file))}\z/, ::Fluentd::SettingArchive::Note::FILE_EXTENSION)
|
137
|
+
FileUtils.rm(note_file_attached_backup) if File.exist? note_file_attached_backup
|
138
|
+
FileUtils.rm(file) if File.exist? file
|
139
|
+
end
|
140
|
+
end
|
106
141
|
end
|
107
142
|
end
|
108
143
|
end
|
@@ -2,7 +2,6 @@ class Fluentd
|
|
2
2
|
class Agent
|
3
3
|
class FluentdGem
|
4
4
|
include Common
|
5
|
-
include LocalCommon
|
6
5
|
|
7
6
|
def self.default_options
|
8
7
|
{
|
@@ -103,6 +102,10 @@ class Fluentd
|
|
103
102
|
false
|
104
103
|
end
|
105
104
|
end
|
105
|
+
|
106
|
+
def wait_process_starting_seconds
|
107
|
+
10.seconds # wait time for fluentd pidfile created
|
108
|
+
end
|
106
109
|
end
|
107
110
|
end
|
108
111
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Fluentd
|
2
|
+
class Agent
|
3
|
+
module ProcessOperation
|
4
|
+
def self.included(base)
|
5
|
+
define_method(:dryrun!) do
|
6
|
+
raise NotImplementedError, "'dryrun!' method is required to be defined"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def running?
|
11
|
+
begin
|
12
|
+
pid && Process.kill(0, pid)
|
13
|
+
rescue Errno::ESRCH
|
14
|
+
File.unlink(pid_file) # no needed any more
|
15
|
+
false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def dryrun(file_path = nil)
|
20
|
+
dryrun!(file_path)
|
21
|
+
true
|
22
|
+
rescue ::Fluentd::Agent::ConfigError
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def pid
|
27
|
+
return unless File.exists?(pid_file)
|
28
|
+
return if File.zero?(pid_file)
|
29
|
+
File.read(pid_file).to_i rescue nil
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def exec_dryrun(command, file_path = nil)
|
35
|
+
Bundler.with_clean_env do
|
36
|
+
unless system("#{command} -q --dry-run #{options_to_argv(config_file: file_path)}", out: File::NULL, err: File::NULL)
|
37
|
+
raise ::Fluentd::Agent::ConfigError
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def detached_command(cmd)
|
43
|
+
thread = Bundler.with_clean_env do
|
44
|
+
pid = spawn(cmd)
|
45
|
+
Process.detach(pid)
|
46
|
+
end
|
47
|
+
thread.join
|
48
|
+
thread.value.exitstatus.zero?
|
49
|
+
end
|
50
|
+
|
51
|
+
def options_to_argv(opts = {})
|
52
|
+
argv = ""
|
53
|
+
argv << " --use-v1-config"
|
54
|
+
argv << " -c #{opts[:config_file] || config_file}"
|
55
|
+
argv << " -d #{opts[:pid_file] || pid_file}"
|
56
|
+
argv << " -o #{opts[:log_file] || log_file}"
|
57
|
+
argv
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -6,7 +6,7 @@ class Fluentd
|
|
6
6
|
KEYS = [
|
7
7
|
:match,
|
8
8
|
:host, :port, :database, :collection, :capped, :capped_size, :capped_max, :user, :password, :tag_mapped,
|
9
|
-
:buffer_type, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval, :retry_wait, :retry_limit, :max_retry_wait, :num_threads,
|
9
|
+
:buffer_type, :buffer_path, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval, :retry_wait, :retry_limit, :max_retry_wait, :num_threads,
|
10
10
|
].freeze
|
11
11
|
|
12
12
|
attr_accessor(*KEYS)
|
@@ -19,6 +19,7 @@ class Fluentd
|
|
19
19
|
validates :database, presence: true
|
20
20
|
validate :validate_capped
|
21
21
|
validate :validate_collection
|
22
|
+
validates :buffer_path, presence: true, if: ->{ buffer_type == "file" }
|
22
23
|
|
23
24
|
def validate_capped
|
24
25
|
return true if capped.blank?
|
@@ -49,7 +50,7 @@ class Fluentd
|
|
49
50
|
|
50
51
|
def advanced_options
|
51
52
|
[
|
52
|
-
:capped, :capped_size, :capped_max, :buffer_type, :buffer_queue_limit, :buffer_chunk_limit,
|
53
|
+
:capped, :capped_size, :capped_max, :buffer_type, :buffer_path, :buffer_queue_limit, :buffer_chunk_limit,
|
53
54
|
:flush_interval, :retry_wait, :retry_limit, :max_retry_wait, :num_threads,
|
54
55
|
]
|
55
56
|
end
|
@@ -8,9 +8,9 @@ class Fluentd
|
|
8
8
|
:match,
|
9
9
|
:aws_key_id, :aws_sec_key, :s3_bucket, :s3_region, :path,
|
10
10
|
# :reduced_redundancy, :check_apikey_on_start, :command_parameter, # not configurable?
|
11
|
-
:format, :include_time_key, :time_key, :delimiter, :label_delimiter,
|
11
|
+
:format, :include_time_key, :time_key, :delimiter, :label_delimiter,
|
12
12
|
:time_slice_format, :time_slice_wait, :time_format, :utc, :store_as, :proxy_uri, :use_ssl,
|
13
|
-
:buffer_type, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval,
|
13
|
+
:buffer_type, :buffer_path, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval,
|
14
14
|
:retry_wait, :retry_limit, :max_retry_wait, :num_threads,
|
15
15
|
].freeze
|
16
16
|
|
@@ -19,17 +19,16 @@ class Fluentd
|
|
19
19
|
choice :format, %w(out_file json ltsv single_value)
|
20
20
|
choice :store_as, %w(gzip lzo lzma2 json txt)
|
21
21
|
choice :buffer_type, %w(memory file)
|
22
|
-
booleans :include_time_key, :
|
22
|
+
booleans :include_time_key, :use_ssl
|
23
23
|
flags :utc
|
24
24
|
|
25
25
|
validates :match, presence: true
|
26
26
|
validates :s3_bucket, presence: true
|
27
|
+
validates :buffer_path, presence: true, if: ->{ buffer_type == "file" }
|
27
28
|
|
28
29
|
def self.initial_params
|
29
30
|
{
|
30
31
|
s3_region: "us-west-1",
|
31
|
-
output_tag: true,
|
32
|
-
output_time: true,
|
33
32
|
use_ssl: true,
|
34
33
|
}
|
35
34
|
end
|
@@ -43,9 +42,9 @@ class Fluentd
|
|
43
42
|
|
44
43
|
def advanced_options
|
45
44
|
[
|
46
|
-
:format, :
|
45
|
+
:format, :include_time_key, :time_key, :delimiter, :label_delimiter,
|
47
46
|
:utc, :time_slice_format, :time_slice_wait, :store_as, :proxy_uri,
|
48
|
-
:buffer_type, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval,
|
47
|
+
:buffer_type, :buffer_path, :buffer_queue_limit, :buffer_chunk_limit, :flush_interval,
|
49
48
|
:retry_wait, :retry_limit, :max_retry_wait, :num_threads,
|
50
49
|
]
|
51
50
|
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
class FluentdLog
|
2
|
+
attr_reader :log_file
|
3
|
+
|
4
|
+
def initialize(path)
|
5
|
+
@log_file = path
|
6
|
+
end
|
7
|
+
|
8
|
+
def read
|
9
|
+
return "" unless File.exists?(log_file)
|
10
|
+
content = File.open(log_file, "r+:ascii-8bit"){|f| f.read } # TODO: large log file
|
11
|
+
content.force_encoding('utf-8').valid_encoding? ? content : content.force_encoding('ascii-8bit')
|
12
|
+
end
|
13
|
+
|
14
|
+
def errors_since(since = 1.day.ago)
|
15
|
+
errors = []
|
16
|
+
logged_errors do |error|
|
17
|
+
break if Time.parse(error[:subject]) < since
|
18
|
+
errors << error
|
19
|
+
end
|
20
|
+
errors
|
21
|
+
end
|
22
|
+
|
23
|
+
def recent_errors(limit = 3)
|
24
|
+
errors = []
|
25
|
+
logged_errors do |error|
|
26
|
+
errors << error
|
27
|
+
break if errors.length >= limit
|
28
|
+
end
|
29
|
+
errors
|
30
|
+
end
|
31
|
+
|
32
|
+
def last_error_message
|
33
|
+
recent_errors(1).first.try(:[], :subject) || ""
|
34
|
+
end
|
35
|
+
|
36
|
+
def tail(limit = nil)
|
37
|
+
return [] unless File.exists?(log_file)
|
38
|
+
|
39
|
+
limit = limit.to_i rescue 0
|
40
|
+
limit = limit.zero? ? Settings.default_log_tail_count : limit
|
41
|
+
io = File.open(log_file)
|
42
|
+
buf = []
|
43
|
+
reader = ::FileReverseReader.new(io)
|
44
|
+
reader.each_line do |line|
|
45
|
+
buf << line
|
46
|
+
break if buf.length >= limit
|
47
|
+
end
|
48
|
+
buf
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def logged_errors(&block)
|
54
|
+
return [] unless File.exist?(log_file)
|
55
|
+
buf = []
|
56
|
+
io = File.open(log_file)
|
57
|
+
reader = ::FileReverseReader.new(io)
|
58
|
+
reader.each_line do |line|
|
59
|
+
unless line["error"]
|
60
|
+
if buf.present?
|
61
|
+
# NOTE: if a following log is given
|
62
|
+
# 2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::EADDRINUSE: Address already in use - bind(2) for 0.0.0.0:24220>
|
63
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:206:in `bind'
|
64
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:206:in `listen'
|
65
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:461:in `block in tcp_server_sockets'
|
66
|
+
# the first line become a "subject", trailing lines are "notes"
|
67
|
+
# {
|
68
|
+
# subject: "2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::EADDRINUSE: Address already in use - bind(2) for 0.0.0.0:24220>",
|
69
|
+
# notes: [
|
70
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:206:in `bind'
|
71
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:206:in `listen'
|
72
|
+
# 2014-06-30 11:24:08 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.2/lib/ruby/2.1.0/socket.rb:461:in `block in tcp_server_sockets'
|
73
|
+
# ]
|
74
|
+
# }
|
75
|
+
split_error_lines_to_error_units(buf.reverse).each do |error_unit|
|
76
|
+
block.call({
|
77
|
+
subject: error_unit[:subject],
|
78
|
+
notes: error_unit[:notes],
|
79
|
+
})
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
buf = []
|
84
|
+
next
|
85
|
+
end
|
86
|
+
buf << line
|
87
|
+
end
|
88
|
+
ensure
|
89
|
+
io && io.close
|
90
|
+
end
|
91
|
+
|
92
|
+
def split_error_lines_to_error_units(buf)
|
93
|
+
# NOTE: if a following log is given
|
94
|
+
#
|
95
|
+
#2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::#EADDRINUSE: Address already in use - bind(2) for "0.0.0.0" port 24224>
|
96
|
+
#2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::#EADDRINUSE: Address already in use - bind(2) for "0.0.0.0" port 24224>
|
97
|
+
# 2014-05-27 10:55:40 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/cool.io-1.2.4/lib/cool.io/server.rb:57:in `initialize'
|
98
|
+
# 2014-05-27 10:55:40 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/cool.io-1.2.4/lib/cool.io/server.rb:57:in `new'
|
99
|
+
#
|
100
|
+
#the first line and second line must be each "error_unit". and after third lines lines are "notes" of second error unit of .
|
101
|
+
# [
|
102
|
+
# { subject: "2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::#EADDRINUSE: Address already in use - bind(2) for "0.0.0.0" port 24224> ",
|
103
|
+
# notes: [] },
|
104
|
+
# { subject: "2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#<Errno::#EADDRINUSE: Address already in use - bind(2) for "0.0.0.0" port 24224> ",
|
105
|
+
# notes: [
|
106
|
+
# "2014-05-27 10:55:40 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/cool.io-1.2.4/lib/cool.io/server.rb:57:in `initialize'",
|
107
|
+
# "2014-05-27 10:55:40 +0900 [error]: /Users/uu59/.rbenv/versions/2.1.0/lib/ruby/gems/2.1.0/gems/cool.io-1.2.4/lib/cool.io/server.rb:57:in `new'"
|
108
|
+
# ]
|
109
|
+
# },
|
110
|
+
# ]
|
111
|
+
#
|
112
|
+
return_array = []
|
113
|
+
buf.each_with_index do |b, i|
|
114
|
+
if b.match(/\A /)
|
115
|
+
return_array[-1][:notes] << b
|
116
|
+
else
|
117
|
+
return_array << { subject: b, notes: [] }
|
118
|
+
end
|
119
|
+
end
|
120
|
+
return return_array.reverse
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|