Re: Raised exceptions are not logged when USR2
El Lunes, 4 de Enero de 2010, Eric Wong escribió: > Iñaki Baz Castillo wrote: > > El Domingo, 3 de Enero de 2010, Eric Wong escribió: > > > # Totally untested, stick this in your Unicorn config file and let > > > # us know if it works or blows up badly: > > > > > > require 'syslog_logger' > > > > > > class MySyslogLogger < SyslogLogger > > > alias puts error > > > alias write error > > > def flush; self; end > > > end > > > > > > $stderr = MySyslogLogger.new('foo') > > > > Unfortunatelly it doesn'w work very well. First of all Sysloglogger > > relies on a constant called SYSLOG created in "initialize" method so it's > > required to add the above methods to SyslogLogger class rather than > > subclass. > > > > Anyhow, the main problem is that by doing "$stderr = > > SyslogLogger.new('foo')" the std error is not redirected as /proc/PID/fd > > still shows: > > > > 2 -> /dev/pts/2 > > Yup, that's expected. _Assigning_ $stderr does not do a redirect at the > OS-level, only at th Ruby level (sufficient for env["rack.errors"], > Kernel#warn). > > > Of course by calling $stderr.puts "error" the above works, but when a > > real error raised it's is printed in the screen (/dev/pts/2). > > > > I strongly think that IO#reopen is required. IO#reopen accepts a string > > (file path) or other IO, so "converting" SyslogLogger into a IO is > > required. > > > > I'll try to achieve it. > > Yes, you need to do something that'll dup()/dup2() internally like > IO#reopen to replace fd=2. But when you have the raw file descriptor, > you won't get syslog formatting... > > The only way I can think of is to redirect fd=2 to the stdin of a > separate process to add formatting in... > > r, w = IO.pipe > fork { > $stdin.reopen(r) > w.close > exec('ruby', '-rsyslog', '-ane', > 'BEGIN{Syslog.open("foo")}; Syslog.warning $_') > } > r.close > $stderr.reopen(w) > > Not pretty... Thanks. Definitively it seems too much complex so I'll change myidea and will use a normal text file for stderr when running daemonized. Thanks a lot. -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
Iñaki Baz Castillo wrote: > El Domingo, 3 de Enero de 2010, Eric Wong escribió: > > > # Totally untested, stick this in your Unicorn config file and let > > # us know if it works or blows up badly: > > > > require 'syslog_logger' > > > > class MySyslogLogger < SyslogLogger > > alias puts error > > alias write error > > def flush; self; end > > end > > > > $stderr = MySyslogLogger.new('foo') > > Unfortunatelly it doesn'w work very well. First of all Sysloglogger relies on > a constant called SYSLOG created in "initialize" method so it's required to > add the above methods to SyslogLogger class rather than subclass. > > Anyhow, the main problem is that by doing "$stderr = SyslogLogger.new('foo')" > the std error is not redirected as /proc/PID/fd still shows: > > 2 -> /dev/pts/2 Yup, that's expected. _Assigning_ $stderr does not do a redirect at the OS-level, only at th Ruby level (sufficient for env["rack.errors"], Kernel#warn). > Of course by calling $stderr.puts "error" the above works, but when a real > error raised it's is printed in the screen (/dev/pts/2). > I strongly think that IO#reopen is required. IO#reopen accepts a string (file > path) or other IO, so "converting" SyslogLogger into a IO is required. > > I'll try to achieve it. Yes, you need to do something that'll dup()/dup2() internally like IO#reopen to replace fd=2. But when you have the raw file descriptor, you won't get syslog formatting... The only way I can think of is to redirect fd=2 to the stdin of a separate process to add formatting in... r, w = IO.pipe fork { $stdin.reopen(r) w.close exec('ruby', '-rsyslog', '-ane', 'BEGIN{Syslog.open("foo")}; Syslog.warning $_') } r.close $stderr.reopen(w) Not pretty... -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
El Domingo, 3 de Enero de 2010, Eric Wong escribió: > # Totally untested, stick this in your Unicorn config file and let > # us know if it works or blows up badly: > > require 'syslog_logger' > > class MySyslogLogger < SyslogLogger > alias puts error > alias write error > def flush; self; end > end > > $stderr = MySyslogLogger.new('foo') Unfortunatelly it doesn'w work very well. First of all Sysloglogger relies on a constant called SYSLOG created in "initialize" method so it's required to add the above methods to SyslogLogger class rather than subclass. Anyhow, the main problem is that by doing "$stderr = SyslogLogger.new('foo')" the std error is not redirected as /proc/PID/fd still shows: 2 -> /dev/pts/2 Of course by calling $stderr.puts "error" the above works, but when a real error raised it's is printed in the screen (/dev/pts/2). I strongly think that IO#reopen is required. IO#reopen accepts a string (file path) or other IO, so "converting" SyslogLogger into a IO is required. I'll try to achieve it. Regards. -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
El Domingo, 3 de Enero de 2010, Eric Wong escribió: > If you really want to, you may be able to subclass SyslogLogger and give > it IO-like methods (write/puts/flush) are require for Rack::Lint > compatibility and then set $stderr: > > # Totally untested, stick this in your Unicorn config file and let > # us know if it works or blows up badly: > > require 'syslog_logger' > > class MySyslogLogger < SyslogLogger > alias puts error > alias write error > def flush; self; end > end > > $stderr = MySyslogLogger.new('foo') > They would be also needed these methods: def reopen(v); true; end def sync=(v); v; end -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
El Domingo, 3 de Enero de 2010, Eric Wong escribió: > Unfortunately, the stock Syslog module isn't compatible with the Ruby > Logger implementation. Try grabbing the "SyslogLogger" gem and using > that instead. I haven't had any experience with SyslogLogger, but a > cursory look says it's OK. Yes, in fact I already use a "bit" customized SyslogLogger :) > If you really want to, you may be able to subclass SyslogLogger and give > it IO-like methods (write/puts/flush) are require for Rack::Lint > compatibility and then set $stderr: > > # Totally untested, stick this in your Unicorn config file and let > # us know if it works or blows up badly: > > require 'syslog_logger' > > class MySyslogLogger < SyslogLogger > alias puts error > alias write error > def flush; self; end > end > > $stderr = MySyslogLogger.new('foo') Really great! It works fine :) > > BTW, how to reset the $stderr so it points again to the default one (the > > terminal)? > > You would've had to dup stderr in the config file and keep it referenced > before it got redirected. But a daemonized process shouldn't be holding > onto terminals... Really thanks a lot. -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
Iñaki Baz Castillo wrote: > El Sábado, 2 de Enero de 2010, Iñaki Baz Castillo escribió: > > A simpler approach would be removing this line at the end of launcher.rb: > > > > Unicorn::Configurator::DEFAULTS[:stderr_path] = "/dev/null" > > > > With this, errors would be displayed in stderr. Of course for workers > > stderr should be reopened to point to /dev/null, but IMHO not for master > > process. > > > > Perhaps errors preventing the master process to start should be displayed > > to stderr instead of to the logger (as it could be not set yet). > > And the other already available workaround is setting the "stderr_path". > Unfortunatelly $stderr.reopen requires a file as parameter so is not possible > to use Syslog or any other logger, is it? Hi Iñaki, Unfortunately, the stock Syslog module isn't compatible with the Ruby Logger implementation. Try grabbing the "SyslogLogger" gem and using that instead. I haven't had any experience with SyslogLogger, but a cursory look says it's OK. I would always keep stderr_path set somewhere in your config file since by default "rack.errors" points to it, and it's the default place for Kernel#warn to output to. If you really want to, you may be able to subclass SyslogLogger and give it IO-like methods (write/puts/flush) are require for Rack::Lint compatibility and then set $stderr: # Totally untested, stick this in your Unicorn config file and let # us know if it works or blows up badly: require 'syslog_logger' class MySyslogLogger < SyslogLogger alias puts error alias write error def flush; self; end end $stderr = MySyslogLogger.new('foo') > BTW, how to reset the $stderr so it points again to the default one (the > terminal)? You would've had to dup stderr in the config file and keep it referenced before it got redirected. But a daemonized process shouldn't be holding onto terminals... -- Eric Wong ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
El Sábado, 2 de Enero de 2010, Iñaki Baz Castillo escribió: > A simpler approach would be removing this line at the end of launcher.rb: > > Unicorn::Configurator::DEFAULTS[:stderr_path] = "/dev/null" > > With this, errors would be displayed in stderr. Of course for workers > stderr should be reopened to point to /dev/null, but IMHO not for master > process. > > Perhaps errors preventing the master process to start should be displayed > to stderr instead of to the logger (as it could be not set yet). And the other already available workaround is setting the "stderr_path". Unfortunatelly $stderr.reopen requires a file as parameter so is not possible to use Syslog or any other logger, is it? BTW, how to reset the $stderr so it points again to the default one (the terminal)? -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Re: Raised exceptions are not logged when USR2
El Sábado, 2 de Enero de 2010, Iñaki Baz Castillo escribió: > Hi, I use the ready_pipe branch. I set "logger" to log into Syslog, but the > issue I'll explain here is the same even if I log to a file. > > I runned Unicorn daemonized. Now imagine I do a typo in my Rack config.ru > (I use preload=true). When sending USR2 to the master it fails (ok) but > the raised exception is not shown in the logger, instead it's lost as > $stderr is /dev/null. > > Even worse, imagine Unicorn is not running and I start it daemonized (with > a init script). Due to the typo in config.ru I see: > > "master failed to start, check stderr log for details" > > But the message is useless since stderr is /dev/null so I se nothing in > Syslog. > > > So I suggest the following: > > If the process fails after setting the logger, then rescue any exception, > log it to the logger and raise it as normal: > > rescue => err > logger.fatal "#{err.class}: > #{err.message}\n#{err.backtrace.join("\n")}" raise err > end > > I'm trying to figure where exactly to include such code but it seems a bit > complex. Any tip please? > > Thanks a lot. A simpler approach would be removing this line at the end of launcher.rb: Unicorn::Configurator::DEFAULTS[:stderr_path] = "/dev/null" With this, errors would be displayed in stderr. Of course for workers stderr should be reopened to point to /dev/null, but IMHO not for master process. Perhaps errors preventing the master process to start should be displayed to stderr instead of to the logger (as it could be not set yet). Opinnions? -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying
Raised exceptions are not logged when USR2
Hi, I use the ready_pipe branch. I set "logger" to log into Syslog, but the issue I'll explain here is the same even if I log to a file. I runned Unicorn daemonized. Now imagine I do a typo in my Rack config.ru (I use preload=true). When sending USR2 to the master it fails (ok) but the raised exception is not shown in the logger, instead it's lost as $stderr is /dev/null. Even worse, imagine Unicorn is not running and I start it daemonized (with a init script). Due to the typo in config.ru I see: "master failed to start, check stderr log for details" But the message is useless since stderr is /dev/null so I se nothing in Syslog. So I suggest the following: If the process fails after setting the logger, then rescue any exception, log it to the logger and raise it as normal: rescue => err logger.fatal "#{err.class}: #{err.message}\n#{err.backtrace.join("\n")}" raise err end I'm trying to figure where exactly to include such code but it seems a bit complex. Any tip please? Thanks a lot. -- Iñaki Baz Castillo ___ Unicorn mailing list - mongrel-unicorn@rubyforge.org http://rubyforge.org/mailman/listinfo/mongrel-unicorn Do not quote signatures (like this one) or top post when replying