diff --git a/lib/couchrest/middlewares/logger.rb b/lib/couchrest/middlewares/logger.rb new file mode 100644 index 0000000..11035b8 --- /dev/null +++ b/lib/couchrest/middlewares/logger.rb @@ -0,0 +1,263 @@ +#################################### +# 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 += "