tomlobato/dns_one

View on GitHub
lib/dns_one/req_log/account.rb

Summary

Maintainability
A
1 hr
Test Coverage
module DnsOne; module ReqLog; class Account

    def initialize
        @conf = Global.conf       

        @stat = {}
        @stat_mutex = Mutex.new
        
        @last_stat = nil
        @last_stat_mutex = Mutex.new

        Thread.new { open_socket }
        Thread.new { reap }
    end

    def on_response ip_address, domain_name, res_class, rcode, resp_log, from_cache
        @stat_mutex.synchronize {
            @stat[:requests] ||= 0
            @stat[:requests] += 1
            
            @stat[:cache] ||= 0
            @stat[:cache] += 1 if from_cache
            
            rcode_uc = Util.const_underscore rcode
            @stat[:rcode] ||= {}
            @stat[:rcode][rcode_uc] ||= 0
            @stat[:rcode][rcode_uc] += 1

            req_resource = Util.last_mod(res_class).downcase
            @stat[:req_resource] ||= {}
            @stat[:req_resource][req_resource] ||= 0
            @stat[:req_resource][req_resource] += 1        
        }
    rescue => e
        Global.logger.error e.desc
    end

    def update_last_stat stat
        if !@allow_update_last_stat
            @allow_update_last_stat = true
            return
        end
        @last_stat_mutex.synchronize {
            @last_stat = stat
        }
    end

    def reap
        loop do
            sleep (300 - Time.now.to_f % 300)
            stat = nil
            @stat_mutex.synchronize { 
                stat = @stat.deep_dup 
                reset @stat
            }
            update_last_stat stat
        rescue => e
            Global.logger.error e.desc
            sleep 10
        end
    end

    def write_socket sock
        last_stat = @last_stat_mutex.synchronize{ @last_stat.deep_dup }
        sock.puts last_stat.to_json
    rescue => e
        Global.logger.error e.desc
    end

    def open_socket
        sleep 1 # wait for UID change before create the socket file
        Socket.unix_server_loop(Global.conf.log_req_socket_file) do |sock, addr|
            Thread.new do
                write_socket sock
            end
        end
    rescue => e
        Global.logger.error e.desc
    end

    def reset hash
        hash.each_key do |k|
            if hash[k].is_a? Hash
                reset hash[k]
            else
                hash[k] = 0
            end
        end
    end

end; end; end