Skip to content

Commit

Permalink
LogTailer should be invoked after all logs in threads were flushed.
Browse files Browse the repository at this point in the history
  • Loading branch information
josevalim committed Jan 15, 2010
1 parent b4019d5 commit b0994be
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 9 deletions.
6 changes: 1 addition & 5 deletions railties/lib/rails/commands/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,22 +46,18 @@ def start
trap(:INT) { exit }
puts "=> Ctrl-C to shutdown server" unless options[:daemonize]

Rails::Subscriber.tail_log = true unless options[:daemonize]
super
ensure
puts 'Exiting' unless options[:daemonize]
end

def middleware
middlewares = []
middlewares << [Rails::Rack::LogTailer, log_path] unless options[:daemonize]
middlewares << [Rails::Rack::Debugger] if options[:debugger]
Hash.new(middlewares)
end

def log_path
"log/#{options[:environment]}.log"
end

def default_options
super.merge({
:Port => 3000,
Expand Down
4 changes: 2 additions & 2 deletions railties/lib/rails/rack/log_tailer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ def initialize(app, log = nil)

def call(env)
response = @app.call(env)
tail_log
tail!
response
end

def tail_log
def tail!
@file.seek @cursor

mod = @file.mtime.to_f
Expand Down
14 changes: 12 additions & 2 deletions railties/lib/rails/subscriber.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,9 @@ module Rails
# Subscriber also has some helpers to deal with logging and automatically flushes
# all logs when the request finishes (via action_dispatch.callback notification).
class Subscriber
cattr_accessor :colorize_logging, :instance_writer => false
mattr_accessor :colorize_logging, :tail_log
self.colorize_logging = true
self.tail_log = false

# Embed in a String to clear all previous ANSI sequences.
CLEAR = "\e[0m"
Expand All @@ -58,6 +59,12 @@ def self.subscribers
@subscribers ||= {}
end

# Use Rails::Rack::LogTailer to do the log tailing.
# TODO Leave this as middleware or move inside Subscriber?
def self.log_tailer
@log_tailer ||= Rails::Rack::LogTailer.new(nil, "log/#{Rails.env}.log")
end

def self.dispatch(args)
namespace, name = args[0].split(".")
subscriber = subscribers[namespace.to_sym]
Expand All @@ -66,7 +73,10 @@ def self.dispatch(args)
subscriber.send(name, ActiveSupport::Notifications::Event.new(*args))
end

flush_all! if args[0] == "action_dispatch.callback"
if args[0] == "action_dispatch.callback" && !subscribers.empty?
flush_all!
log_tailer.tail! if tail_log
end
end

# Flush all subscribers' logger.
Expand Down
15 changes: 15 additions & 0 deletions railties/test/subscriber_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ module SubscriberTest
def setup
super
@subscriber = MySubscriber.new
Rails::Subscriber.instance_variable_set(:@log_tailer, nil)
end

def teardown
super
Rails::Subscriber.subscribers.clear
Rails::Subscriber.instance_variable_set(:@log_tailer, nil)
end

def instrument(*args, &block)
Expand Down Expand Up @@ -103,6 +105,19 @@ def test_flushes_the_same_logger_just_once
assert_equal 1, @logger.flush_count
end

def test_tails_logs_when_action_dispatch_callback_is_received
log_tailer = mock()
log_tailer.expects(:tail!)
Rails::Rack::LogTailer.expects(:new).with(nil, "log/development.log").returns(log_tailer)

Rails::Subscriber.tail_log = true
Rails::Subscriber.add :my_subscriber, @subscriber
instrument "action_dispatch.callback"
wait
ensure
Rails::Subscriber.tail_log = false
end

class SyncSubscriberTest < ActiveSupport::TestCase
include Rails::Subscriber::SyncTestHelper
include SubscriberTest
Expand Down

0 comments on commit b0994be

Please sign in to comment.