Custom report handler runs multiple times

Hi - I created a very simple report handler, which works but runs multiple times via the chef-client daemon. It appears to run once for each successful chef-client run. If I tail the log and wait or send a USR1 signal to the chef-client process to force a run I will see one more report_handler log line than the time before. I have tested the config below on chef-client 16.10.17

The top of my client.rb is as follows:

require "/etc/chef/testthingy_handler.rb"
report_handlers << Chef::Handler::TestThingy.new

The testtingy_handler.rb file as the following:

require 'chef/handler'

class Chef
  class Handler
    class TestThingy < Chef::Handler
      def report
      end
    end
  end
end

Yes, right now the report function does nothing, I have added something simple to make sure it wasn't that. After adding the above, restarting chef-client and waiting until two runs have completed I will see the following at the bottom of the log.

INFO: Running report handlers
  - Chef::Handler::TestThingy
  - Chef::Handler::TestThingy
Running handlers complete
INFO: Report handlers complete

When a third run completes another '- Chef::Handler::TestThingy' line will join the two above and so on until there are many. Only restarting the daemon resets it. Does anyone know why this might be? Am I creating the handler incorrectly? Is there anything you can suggest to debug the issue?

Thanks for reading.

The client.rb is getting parsed by the daemon every time and this line is appending yet another handler every single time:

report_handlers << Chef::Handler::TestThingy.new

This is then forked off to the child process which "inherits" the ever-extending config.

We don't recommend using the daemon process at all now. It is generally better to use systemd timers, or a scheduled task or just run one shot chef-client runs out of cron. It causes issues like this and will also cause problems on upgrades where the daemon is often left un-upgraded by the chef_client_updater cookbook.

To fix it in the short term just setting it rather than appending it will probably work:

report_handlers [ Chef::Handler::TestThingy.new ]

Otherwise:

report_handlers << Chef::Handler::TestThingy.new
  unless report_handlers.any? { |x| x.is_a?(Chef::Handler::TestThingy) }

or something like that.

1 Like

Thank you for the explanation and example fixes. It gives me a couple of options moving forward.