module What
  class Monitor
    # don't worry, this method name is ironic
    def go!
      # For now, use a hash as the centralized collection point for data. We
      # can't use a method on the module because Celluloid will block that call
      # until after whatever method is currently running, which could be
      # unacceptably slow. We could use a fancy thread-safe data structure
      # instead of a hash, but the GIL means hash assignment and reading are
      # safe as long as we're on MRI.
      @results = {}
      @modules = Config['modules'].map do |config_hash|
        name     = Helpers.camelize(config_hash.delete('type'))
        klass    = Modules.const_get(name)
        instance = klass.new(config_hash, @results)
        {
          class: klass,
          config_hash: config_hash,
          module: instance,
          failures: 0,
          id: instance.identifier
        }
      end

      @modules.each do |mod|
        mod[:module].async.start_monitoring
      end
    end

    def status
      statuses = []
      healths = []

      @modules.each do |mod|
        status = @results[mod[:id]] || {"health" => nil}
        healths << status['health']
        statuses << status

        if status["error"]
          status["failures"] = mod[:failures]

          if mod[:failures] < 6
            mod[:failures] += 1
            mod[:module].async.start_monitoring
          end
        end
      end

      {"health" => Helpers.overall_health(healths), "details" => statuses}
    end
  end
end

module What
  class Monitor
    # don't worry, this method name is ironic
    def go!
      # For now, use a hash as the centralized collection point for data. We
      # can't use a method on the module because Celluloid will block that call
      # until after whatever method is currently running, which could be
      # unacceptably slow. We could use a fancy thread-safe data structure
      # instead of a hash, but the GIL means hash assignment and reading are
      # safe as long as we're on MRI.
      @results = {}
      @modules = Config['modules'].map do |config_hash|
        name     = Helpers.camelize(config_hash.delete('type'))
        klass    = Modules.const_get(name)
        instance = klass.new(config_hash, @results)
        {
          class: klass,
          config_hash: config_hash,
          module: instance,
          failures: 0,
          id: instance.identifier
        }
      end

      @modules.each do |mod|
        mod[:module].async.start_monitoring
      end
    end

    def status
      statuses = []
      healths = []

      @modules.each do |mod|
        status = @results[mod[:id]] || {"health" => nil}
        healths << status['health']
        statuses << status

        if status["error"]
          status["failures"] = mod[:failures]

          puts "Error in module:\n#{YAML.dump(status)}"

          if mod[:failures] < 6
            mod[:failures] += 1
            mod[:module].async.start_monitoring
          end
        end
      end

      {"health" => Helpers.overall_health(healths), "details" => statuses}
    end
  end
end

Add logging on module error
Add logging on module error
