Async logging doesn't work out of the box with application servers that prefork #122

Closed
fcheung opened this Issue Sep 11, 2012 · 3 comments

Comments

Projects
None yet
5 participants

fcheung commented Sep 11, 2012

If you put

Airbrake.configure do |config|
  config.api_key = 'xxx'
  config.async = true
end

in an initializer, as the docs suggest and your setup preloads the apps and then forks workers (unicorn, passenger) then error notifications aren't sent. This is because Airbrake.configure sets up the girl friday work queue, which spawns a thread. When the app server forks, only the main thread is copied over to the child process, so the thread servicing the girl friday queue doesn't exist in the new thread and the exceptions are silently dropped

There are a few workarounds to this, for example configuring in after_for block or creating the girl friday queue on demand (There is an example of this on the girl friday issues page)

Given that what are probably the 2 most popular rails deployment solutions (95% according to the recent survey) require one of these workarounds it should at very least be mentioned in the docs. Preferably airbrake would take care of this by itself

@ghost ghost assigned shime Oct 23, 2012

jeyb commented Mar 27, 2013

Does this issue still exist? Any resolution?

Contributor

ericcj commented Jun 24, 2014

we ran into this issue with girl_friday today and it took forever to hunt down. the airbrake gem should deprecate support for girl_friday since the failure mode silently disables the reporting of exceptions on very commonly used application servers. there's no sense in supporting a deprecated dependency that when used often prevents your own gem from doing its job.

Owner

kyrylo commented Oct 3, 2015

My only advice here is to use the synchronous mode, because fork kills all background threads.

worker = Thread.new do
  loop do
    sleep 10
  end
end

puts "Current pid (pre-fork): #{Process.pid} | worker.alive? #=> #{worker.alive?}" #=> true
puts "---"
fork
puts "Current pid (after-fork): #{Process.pid} | worker.alive? #=> #{worker.alive?}" #=> false

Output:

Current pid (pre-fork): 7973 | worker.alive? #=> true
---
Current pid (after-fork): 7973 | worker.alive? #=> true
Current pid (after-fork): 7976 | worker.alive? #=> false

As you can see, our original worker thread (on master process) is alive. However, when we fork the child process kills it. That's why async delivery doesn't work: the workers are dead.

@kyrylo kyrylo closed this Oct 3, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment