Permalink
Browse files

brought submodules into the main repo [heroku]

  • Loading branch information...
1 parent e60aab4 commit 0704006894e7edd22b82353adc758da8f25559a9 @duien committed Oct 10, 2010
View
3 .gitmodules
@@ -1,3 +0,0 @@
-[submodule "vendor/plugins/mongo_db_logger"]
- path = vendor/plugins/mongo_db_logger
- url = git@github.com:duien/mongo_db_logger.git
1 vendor/plugins/mongo_db_logger
@@ -1 +0,0 @@
-Subproject commit 1b0197910a56facc25bc4f6974c8cabbe38c7c56
View
20 vendor/plugins/mongo_db_logger/MIT-LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009 [name of plugin creator]
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
View
112 vendor/plugins/mongo_db_logger/README.md
@@ -0,0 +1,112 @@
+MongoDbLogger
+=============
+
+Log to MongoDB from a Rails app
+
+
+Usage:
+======
+
+1) add the following line to your ApplicationController:
+
+<code>include MongoDBLogging</code>
+
+2) configure specific environments to use the MongoLogger (in config/#{environment}.rb):
+
+<code>config.logger = MongoLogger.new</code>
+
+3) add mongo settings for each environment in which you want to use MongoDB for logging:
+
+<pre><code>
+development:
+ adapter: mysql
+ database: my_app_development
+ user: root
+ mongo:
+ database: my_app
+ capsize: &lt;%= 10.megabytes %&gt;
+ host: localhost
+ port: 27017
+</code></pre>
+
+With that in place, a new MongoDB document (record) will be created for each request and,
+by default will record the following information: Runtime, IP Address, Request Time, Controller,
+Action, Params and All messages sent to the logger. The structure of the Mongo document looks something like this:
+
+<pre><code>
+{
+ 'controller' : controller_name,
+ 'action' : action_name,
+ 'ip' : ip_address,
+ 'runtime' : runtime,
+ 'request_time' : time_of_request,
+ 'params' : { }
+ 'messages' : [
+ { 'message' : message, 'level' : log_level },
+ { 'message' : message, 'level' : log_level }
+ ]
+}
+</code></pre>
+
+Beyond that, if you want to add extra information to the base of the document
+(let’s say something like user_guid on every request that it’s available),
+you can just call the Rails.logger.add_metadata method on your logger like so
+(for example from a before_filter):
+
+<pre><code>
+# make sure we're using the MongoLogger in this environment
+if Rails.logger.respond_to?(:add_metadata)
+ Rails.logger.add_metadata(:user_guid =&gt; @user_guid)
+end
+</code></pre>
+
+This will add a 'metadata' key to the log document, with <code>{ 'user_guid' : user_guid }</code> as the value.
+If you metadata is a more complex data type, it will attempt to save it directly to mongo, letting you do deep
+queries into it.
+
+4) And optionally, and PLEASE be sure to protect this behind a login, you can add a basic
+logging view by adding the following to your routes:
+
+<pre><code>
+map.add_mongo_logger_resources!
+</code></pre>
+
+With that you can then visit "/mongo" to view log entries (latest first). You can add
+parameters like "page=3" to page through to older entries, or "count=30" to change the
+number of log entries per page.
+
+And now, for a couple quick examples on getting ahold of this log data…
+First, here’s how to get a handle on the MongoDB from within a Rails console:
+
+<pre><code>
+>> db = MongoLogger.mongo_connection
+=> #&lt;Mongo::DB:0x102f19ac0 @slave_ok=nil, @name="my_app" ... &gt;
+
+>> collection = db[MongoLogger.mongo_collection_name]
+=> #&lt;Mongo::Collection:0x1031b3ee8 @name="development_log" ... &gt;
+</code></pre>
+
+Once you’ve got the collection, you can find all requests for a specific user (with guid):
+
+<pre><code>
+>> cursor = collection.find('metadata.user_guid' => '12355')
+=> #&lt;Mongo::Cursor:0x1031a3e30 ... &gt;
+>> cursor.count
+=> 5
+</code></pre>
+
+Find all requests that took more that one second to complete:
+
+<pre><code>
+>> collection.find({:runtime => {'$gt' => 1000}}).count
+=> 3
+</code></pre>
+
+Find all requests that passed a parameter with a certain value:
+
+<pre><code>
+>> collection.find({'params.currency' => 'USD'}).count
+=> 22
+</code></pre>
+
+Copyright (c) 2010 Emily Price, released under the MIT license
View
23 vendor/plugins/mongo_db_logger/Rakefile
@@ -0,0 +1,23 @@
+require 'rake'
+require 'rake/testtask'
+require 'rake/rdoctask'
+
+desc 'Default: run unit tests.'
+task :default => :test
+
+desc 'Test the mongo_db_logger plugin.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib'
+ t.libs << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+desc 'Generate documentation for the mongo_db_logger plugin.'
+Rake::RDocTask.new(:rdoc) do |rdoc|
+ rdoc.rdoc_dir = 'rdoc'
+ rdoc.title = 'MongoDbLogger'
+ rdoc.options << '--line-numbers' << '--inline-source'
+ rdoc.rdoc_files.include('README')
+ rdoc.rdoc_files.include('lib/**/*.rb')
+end
View
1 vendor/plugins/mongo_db_logger/init.rb
@@ -0,0 +1 @@
+ActionController::Routing::RouteSet::Mapper.send(:include, MongoDBLogging::RoutingExtensions)
View
0 vendor/plugins/mongo_db_logger/install.rb
No changes.
View
20 vendor/plugins/mongo_db_logger/lib/mongo_db_logging.rb
@@ -0,0 +1,20 @@
+module MongoDBLogging
+ def self.included(base)
+ base.class_eval { around_filter :enable_mongo_logging }
+ end
+
+ def enable_mongo_logging
+ return yield unless Rails.logger.respond_to?(:mongoize)
+
+ # make sure the controller knows how to filter its parameters
+ f_params = respond_to?(:filter_parameters) ? filter_parameters(params) : params
+ Rails.logger.mongoize({
+ :action => action_name,
+ :controller => controller_name,
+ :path => request.path,
+ :url => request.url,
+ :params => f_params,
+ :ip => request.remote_ip
+ }) { yield }
+ end
+end
View
45 vendor/plugins/mongo_db_logger/lib/mongo_db_logging/mongo_controller.rb
@@ -0,0 +1,45 @@
+# please, please, please protect this controller behind a login
+class MongoDBLogging::MongoController < ActionController::Base
+ append_view_path(File.join(File.dirname(__FILE__), "../../views"))
+
+ helper_method :format_messages
+ helper_method :print_detail
+
+ def index
+ count = (params[:count] || 50).to_i
+ @page = (params[:page] || 1).to_i
+ offset = (@page - 1) * count
+ db = MongoLogger.mongo_connection
+ collection = db[MongoLogger.mongo_collection_name]
+ @records = collection.find({}, :skip => offset, :limit => count, :sort => [[ '_id', :desc ]])
+ end
+
+ def show
+ end
+
+protected
+ def format_messages(messages, css_class)
+ return nil if messages.blank?
+ css_class ||= ''
+ css_class << ' messages'
+ output = %{<ul class="#{css_class}">\n}
+ messages.each do |mess|
+ output << "<li>#{mess}</li>\n"
+ end
+ output << "</ul>"
+ end
+
+ def print_detail( object, indent = 0 )
+ output = ""
+ if object.kind_of? Hash
+ output << "{\n"
+ output << object.collect { |key, value|
+ " " * indent + " #{print_detail key} => #{print_detail value, indent+1}"
+ }.join(",\n") << "\n"
+ output << " " * indent + "}"
+ else
+ output << object.inspect
+ end
+ output
+ end
+end
View
7 vendor/plugins/mongo_db_logger/lib/mongo_db_logging/routing_extensions.rb
@@ -0,0 +1,7 @@
+module MongoDBLogging
+ module RoutingExtensions
+ def add_mongo_logger_resources!
+ resources :mongo, :controller => "MongoDBLogging/Mongo", :only => [:show, :index, :destroy]
+ end
+ end
+end
View
77 vendor/plugins/mongo_db_logger/lib/mongo_logger.rb
@@ -0,0 +1,77 @@
+require 'erb'
+require 'mongo'
+
+class MongoLogger < ActiveSupport::BufferedLogger
+ default_capsize = (Rails.env == 'production') ? 250.megabytes : 100.megabytes
+
+ user_config = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config/database.yml'))).result)[Rails.env]['mongo'] || {}
+
+ db_configuration = {
+ 'host' => 'localhost',
+ 'port' => 27017,
+ 'capsize' => default_capsize}.merge(user_config)
+
+ begin
+ @mongo_collection_name = "#{Rails.env}_log"
+ @mongo_connection ||= Mongo::Connection.new(db_configuration['host'], db_configuration['port'], :auto_reconnect => true).db(db_configuration['database'])
+
+ # setup the capped collection if it doesn't already exist
+ unless @mongo_connection.collection_names.include?(@mongo_collection_name)
+ @mongo_connection.create_collection(@mongo_collection_name, {:capped => true, :size => db_configuration['capsize']})
+ end
+ rescue => e
+ puts "=> !! A connection to mongo could not be established - the logger will function like a normal ActiveSupport::BufferedLogger !!"
+ end
+
+ class << self
+ attr_reader :mongo_collection_name, :mongo_connection
+ end
+
+ def initialize(level=DEBUG)
+ super(File.join(Rails.root, "log/#{Rails.env}.log"), level)
+ end
+
+ def level_to_sym(level)
+ case level
+ when 0 then :debug
+ when 1 then :info
+ when 2 then :warn
+ when 3 then :error
+ when 4 then :fatal
+ when 5 then :unknown
+ end
+ end
+
+ def mongoize(options={})
+ @mongo_record = options.merge({
+ :messages => [],
+ :request_time => Time.now.utc
+ })
+ runtime = Benchmark.measure do
+ yield
+ end
+ @mongo_record[:runtime] = (runtime.real * 1000).ceil
+ self.class.mongo_connection[self.class.mongo_collection_name].insert(@mongo_record) rescue nil
+ end
+
+ def add_metadata(options={})
+ options.each_pair do |key, value|
+ if @mongo_record[:metadata]
+ @mongo_record[:metadata][key] = value
+ else
+ @mongo_record[:metadata] = { key, value }
+ end
+ end
+ end
+
+ def add(severity, message = nil, progname = nil, &block)
+ super and return unless @mongo_record
+ unless @level > severity
+ message.gsub!(/(\e(\[([\d;]*[mz]?))?)?/, '').strip! if message and defined?(ActiveRecord) and ActiveRecord::Base.colorize_logging
+ # remove colorization done by rails and just save the actual message
+ @mongo_record[:messages] << { :level => level_to_sym(severity), :message => message }
+ end
+
+ super
+ end
+end # class MongoLogger
View
4 vendor/plugins/mongo_db_logger/tasks/mongo_db_logger_tasks.rake
@@ -0,0 +1,4 @@
+# desc "Explaining what the task does"
+# task :mongo_db_logger do
+# # Task goes here
+# end
View
1 vendor/plugins/mongo_db_logger/uninstall.rb
@@ -0,0 +1 @@
+# Uninstall hook code here
View
58 vendor/plugins/mongo_db_logger/views/mongo_db_logging/mongo/index.html.erb
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Mongo Logs</title>
+ <style>
+ td { vertical-align: top; }
+ tr.record td { border-top: 1px dotted black; }
+ .messages { font-family: monospace;}
+ .messages .error { color: red; }
+ .messages .warn { color: DarkOrange; }
+ .messages .debug { color: gray; }
+ </style>
+</head>
+<body>
+ <p>Log records (latest/newest entries first), page <%= @page %></p>
+ <table id="mongo_list">
+ <thead>
+ <tr class="header">
+ <th>Controller</th>
+ <th>Action</th>
+ <th>ID, Timestamp</th>
+ <th>Messages</th>
+ </tr>
+ <tr>
+ <th colspan="3">Params</th>
+ <th>Metadata</th>
+ </thead>
+ <tbody>
+ <% @records.each do |record| -%>
+ <tr class="record">
+ <td class="controller"><%= record['controller'] %></td>
+ <td class="action"><%= record['action'] %></td>
+ <td class="id"><%= record['_id'] %><br/><%= record['request_time'].strftime("%d-%b-%Y %H:%M:%S %Z") %></td>
+ <td class="messages">
+ <%- if record['messages'].kind_of? Hash %>
+ <%= format_messages(record['messages']['error'], 'error') %>
+ <%= format_messages(record['messages']['warning'], 'warning') %>
+ <%= format_messages(record['messages']['info'], 'info') %>
+ <%= format_messages(record['messages']['debug'], 'debug') %>
+ <%- elsif record['messages'].kind_of? Array %>
+ <ul>
+ <%- record['messages'].each do |message| %>
+ <li class=<%= message['level'] %>><%= message['message'] %></li>
+ <%- end %>
+ </ul>
+ <%- end %>
+ </td>
+ </tr>
+ <tr>
+ <td class="params" colspan="3"><pre><%= record['params'] ? print_detail(record['params']) : '' %></pre></td>
+ <td class="metadata"><pre><%= record['metadata'] ? print_detail(record['metadata']) : '' %></pre></td>
+ </tr>
+ <% end -%>
+ </tbody>
+ </table>
+
+</body>
+</html>

0 comments on commit 0704006

Please sign in to comment.