#################################### # USAGE # # in your rack.rb file # require this file and then: # # couch = CouchRest.new # LOG_DB = couch.database!('couchrest-logger') # use CouchRest::Logger, LOG_DB # # Note: # to require just this middleware, if you have the gem installed do: # require 'couchrest/middlewares/logger' # # For log processing examples, see examples at the bottom of this file module CouchRest class Logger def self.log Thread.current["couchrest.logger"] ||= {:queries => []} end def initialize(app, db=nil) @app = app @db = db end def self.record(log_info) log[:queries] << log_info end def log Thread.current["couchrest.logger"] ||= {:queries => []} end def reset_log Thread.current["couchrest.logger"] = nil end def call(env) reset_log log['started_at'] = Time.now log['env'] = env log['url'] = 'http://' + env['HTTP_HOST'] + env['REQUEST_URI'] response = @app.call(env) log['ended_at'] = Time.now log['duration'] = log['ended_at'] - log['started_at'] # let's report the log in a different thread so we don't slow down the app @db ? Thread.new(@db, log){|db, rlog| db.save_doc(rlog);} : p(log.inspect) response end end end # inject our logger into CouchRest HTTP abstraction layer module HttpAbstraction def self.get(uri, headers=nil) start_query = Time.now log = {:method => :get, :uri => uri, :headers => headers} response = super(uri, headers=nil) end_query = Time.now log[:duration] = (end_query - start_query) CouchRest::Logger.record(log) response end def self.post(uri, payload, headers=nil) start_query = Time.now log = {:method => :post, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers} response = super(uri, payload, headers=nil) end_query = Time.now log[:duration] = (end_query - start_query) CouchRest::Logger.record(log) response end def self.put(uri, payload, headers=nil) start_query = Time.now log = {:method => :put, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers} response = super(uri, payload, headers=nil) end_query = Time.now log[:duration] = (end_query - start_query) CouchRest::Logger.record(log) response end def self.delete(uri, headers=nil) start_query = Time.now log = {:method => :delete, :uri => uri, :headers => headers} response = super(uri, headers=nil) end_query = Time.now log[:duration] = (end_query - start_query) CouchRest::Logger.record(log) response end end # Advanced usage example # # # # DB VIEWS # by_url = { # :map => # "function(doc) { # if(doc['url']){ emit(doc['url'], 1) }; # }", # :reduce => # 'function (key, values, rereduce) { # return(sum(values)); # };' # } # req_duration = { # :map => # "function(doc) { # if(doc['duration']){ emit(doc['url'], doc['duration']) }; # }", # :reduce => # 'function (key, values, rereduce) { # return(sum(values)/values.length); # };' # } # # query_duration = { # :map => # "function(doc) { # if(doc['queries']){ # doc.queries.forEach(function(query){ # if(query['duration'] && query['method']){ # emit(query['method'], query['duration']) # } # }); # }; # }" , # :reduce => # 'function (key, values, rereduce) { # return(sum(values)/values.length); # };' # } # # action_queries = { # :map => # "function(doc) { # if(doc['queries']){ # emit(doc['url'], doc['queries'].length) # }; # }", # :reduce => # 'function (key, values, rereduce) { # return(sum(values)/values.length); # };' # } # # action_time_spent_in_db = { # :map => # "function(doc) { # if(doc['queries']){ # var totalDuration = 0; # doc.queries.forEach(function(query){ # totalDuration += query['duration'] # }) # emit(doc['url'], totalDuration) # }; # }", # :reduce => # 'function (key, values, rereduce) { # return(sum(values)/values.length); # };' # } # # show_queries = %Q~function(doc, req) { # var body = "" # body += "