From d6f9992a48fcf5cdbf4dee7b5b21b2901eaf7fd4 Mon Sep 17 00:00:00 2001 From: uu59 Date: Tue, 10 Feb 2015 15:49:56 +0900 Subject: [PATCH] Rename: FluentdUiLog -> FluentdLog --- app/models/fluentd/agent/common.rb | 2 +- app/models/fluentd/agent/log.rb | 126 ----------------------------- app/models/fluentd_log.rb | 123 ++++++++++++++++++++++++++++ 3 files changed, 124 insertions(+), 127 deletions(-) delete mode 100644 app/models/fluentd/agent/log.rb create mode 100644 app/models/fluentd_log.rb diff --git a/app/models/fluentd/agent/common.rb b/app/models/fluentd/agent/common.rb index 99fa970..a0c7d6c 100644 --- a/app/models/fluentd/agent/common.rb +++ b/app/models/fluentd/agent/common.rb @@ -43,7 +43,7 @@ class Fluentd end def log - @log ||= Fluentd::Agent::Log.new(log_file) + @log ||= FluentdLog.new(log_file) end def config_file diff --git a/app/models/fluentd/agent/log.rb b/app/models/fluentd/agent/log.rb deleted file mode 100644 index 15bf1b9..0000000 --- a/app/models/fluentd/agent/log.rb +++ /dev/null @@ -1,126 +0,0 @@ -class Fluentd - class Agent - class Log - attr_reader :log_file - - def initialize(path) - @log_file = path - end - - def to_s - return "" unless File.exists?(log_file) - File.read(log_file) # TODO: large log file - end - - def errors_since(since = 1.day.ago) - errors = [] - logged_errors do |error| - break if Time.parse(error[:subject]) < since - errors << error - end - errors - end - - def recent_errors(limit = 3) - errors = [] - logged_errors do |error| - errors << error - break if errors.length >= limit - end - errors - end - - def last_error_message - recent_errors(1).first.try(:[], :subject) || "" - end - - def tail(limit = nil) - return [] unless File.exists?(log_file) - - limit = limit.to_i rescue 0 - limit = limit.zero? ? Settings.default_log_tail_count : limit - io = File.open(log_file) - buf = [] - reader = ::FileReverseReader.new(io) - reader.each_line do |line| - buf << line - break if buf.length >= limit - end - buf - end - - private - - def logged_errors(&block) - return [] unless File.exist?(log_file) - buf = [] - io = File.open(log_file) - reader = ::FileReverseReader.new(io) - reader.each_line do |line| - unless line["error"] - if buf.present? - # NOTE: if a following log is given - # 2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# - # 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' - # 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' - # 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' - # the first line become a "subject", trailing lines are "notes" - # { - # subject: "2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#", - # notes: [ - # 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' - # 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' - # 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' - # ] - # } - split_error_lines_to_error_units(buf.reverse).each do |error_unit| - block.call({ - subject: error_unit[:subject], - notes: error_unit[:notes], - }) - end - end - - buf = [] - next - end - buf << line - end - ensure - io && io.close - end - - def split_error_lines_to_error_units(buf) - # NOTE: if a following log is given - # - #2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# - #2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# - # 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' - # 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' - # - #the first line and second line must be each "error_unit". and after third lines lines are "notes" of second error unit of . - # [ - # { subject: "2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# ", - # notes: [] }, - # { subject: "2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# ", - # notes: [ - # "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'", - # "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'" - # ] - # }, - # ] - # - return_array = [] - buf.each_with_index do |b, i| - if b.match(/\A /) - return_array[-1][:notes] << b - else - return_array << { subject: b, notes: [] } - end - end - return return_array.reverse - end - end - end -end - diff --git a/app/models/fluentd_log.rb b/app/models/fluentd_log.rb new file mode 100644 index 0000000..7708962 --- /dev/null +++ b/app/models/fluentd_log.rb @@ -0,0 +1,123 @@ +class FluentdLog + attr_reader :log_file + + def initialize(path) + @log_file = path + end + + def read + return "" unless File.exists?(log_file) + content = File.open(log_file, "r+:ascii-8bit"){|f| f.read } # TODO: large log file + content.force_encoding('utf-8').valid_encoding? ? content : content.force_encoding('ascii-8bit') + end + + def errors_since(since = 1.day.ago) + errors = [] + logged_errors do |error| + break if Time.parse(error[:subject]) < since + errors << error + end + errors + end + + def recent_errors(limit = 3) + errors = [] + logged_errors do |error| + errors << error + break if errors.length >= limit + end + errors + end + + def last_error_message + recent_errors(1).first.try(:[], :subject) || "" + end + + def tail(limit = nil) + return [] unless File.exists?(log_file) + + limit = limit.to_i rescue 0 + limit = limit.zero? ? Settings.default_log_tail_count : limit + io = File.open(log_file) + buf = [] + reader = ::FileReverseReader.new(io) + reader.each_line do |line| + buf << line + break if buf.length >= limit + end + buf + end + + private + + def logged_errors(&block) + return [] unless File.exist?(log_file) + buf = [] + io = File.open(log_file) + reader = ::FileReverseReader.new(io) + reader.each_line do |line| + unless line["error"] + if buf.present? + # NOTE: if a following log is given + # 2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# + # 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' + # 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' + # 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' + # the first line become a "subject", trailing lines are "notes" + # { + # subject: "2014-06-30 11:24:08 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=#", + # notes: [ + # 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' + # 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' + # 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' + # ] + # } + split_error_lines_to_error_units(buf.reverse).each do |error_unit| + block.call({ + subject: error_unit[:subject], + notes: error_unit[:notes], + }) + end + end + + buf = [] + next + end + buf << line + end + ensure + io && io.close + end + + def split_error_lines_to_error_units(buf) + # NOTE: if a following log is given + # + #2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# + #2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# + # 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' + # 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' + # + #the first line and second line must be each "error_unit". and after third lines lines are "notes" of second error unit of . + # [ + # { subject: "2014-05-27 10:54:37 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# ", + # notes: [] }, + # { subject: "2014-05-27 10:55:40 +0900 [error]: unexpected error error_class=Errno::EADDRINUSE error=# ", + # notes: [ + # "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'", + # "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'" + # ] + # }, + # ] + # + return_array = [] + buf.each_with_index do |b, i| + if b.match(/\A /) + return_array[-1][:notes] << b + else + return_array << { subject: b, notes: [] } + end + end + return return_array.reverse + end +end +