module Honeybadger
  module Util
    class Stats
      HAS_MEM = File.exists?("/proc/meminfo")
      HAS_LOAD = File.exists?("/proc/loadavg")

      class << self
        def all
          { :mem => memory, :load => load }
        end

        # From https://github.com/bloopletech/webstats/blob/master/server/data_providers/mem_info.rb
        def memory
          out = {}
          if HAS_MEM
            out[:total], out[:free], out[:buffers], out[:cached] = IO.readlines("/proc/meminfo")[0..4].map { |l| l =~ /^.*?\: +(.*?) kB$/; ($1.to_i / 1024.0).to_f }
            out[:free_total] = out[:free] + out[:buffers] + out[:cached]
          end
          out
        end

        # From https://github.com/bloopletech/webstats/blob/master/server/data_providers/cpu_info.rb
        def load
          out = {}
          out[:one], out[:five], out[:fifteen] = IO.read("/proc/loadavg").split(' ', 4).map(&:to_f) if HAS_LOAD
          out
        end
      end
    end
  end
end

module Honeybadger
  module Util
    class Stats
      HAS_MEM = File.exists?("/proc/meminfo")
      HAS_LOAD = File.exists?("/proc/loadavg")

      class << self
        def all
          { :mem => memory, :load => load }
        end

        # From https://github.com/bloopletech/webstats/blob/master/server/data_providers/mem_info.rb
        def memory
          out = {}
          if HAS_MEM && (meminfo = run_meminfo)
            out[:total], out[:free], out[:buffers], out[:cached] = meminfo[0..4].map { |l| l =~ /^.*?\: +(.*?) kB$/; ($1.to_i / 1024.0).to_f }
            out[:free_total] = out[:free] + out[:buffers] + out[:cached]
          end
          out
        end

        # From https://github.com/bloopletech/webstats/blob/master/server/data_providers/cpu_info.rb
        def load
          out = {}
          if HAS_LOAD && (loadavg = run_loadavg)
            out[:one], out[:five], out[:fifteen] = loadavg.split(' ', 4).map(&:to_f)
          end
          out
        end
        
        def run_meminfo
          run { IO.readlines("/proc/meminfo") }
        end
        
        def run_loadavg
          run { IO.read("/proc/loadavg") }
        end
        
        def run
          yield
        rescue Errno::ENFILE
          # catch issues like 'Too many open files in system'
        end
      end
    end
  end
end

Fix issue with Too many open files in system
Fix issue with Too many open files in system

In our system we had an error 'too many open files in system', and it wasn't pushed to the honeybadger server because it was raisen in exceptional tracker. It's possible to catch Errno::ENFILE and prevent from raising an error while sending an exception to the server.