central_logger 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm 1.9.2@central_logger
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rake"
4
+ gem "bundler", "~> 1.0.0"
5
+ gem "mongo"
6
+ gem "bson_ext"
7
+
8
+ group :production do
9
+ # don't want to force development to have this requirement, because every
10
+ # Rails dependency is mocked
11
+ gem "rails",">= 2.3.8"
12
+ end
13
+
14
+ group :development do
15
+ # adds Bundler support for gemspec generation
16
+ gem "jeweler", "~> 1.5.0.pre5"
17
+ gem "shoulda"
18
+ gem "i18n"
19
+ gem "activesupport"
20
+ gem "mocha"
21
+ gem (RUBY_VERSION =~ /^1\.9/ ? "ruby-debug19" : "ruby-debug")
22
+ end
@@ -0,0 +1,108 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.1)
6
+ actionpack (= 3.0.1)
7
+ mail (~> 2.2.5)
8
+ actionpack (3.0.1)
9
+ activemodel (= 3.0.1)
10
+ activesupport (= 3.0.1)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4.1)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.12)
16
+ rack-test (~> 0.5.4)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.1)
19
+ activesupport (= 3.0.1)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4.1)
22
+ activerecord (3.0.1)
23
+ activemodel (= 3.0.1)
24
+ activesupport (= 3.0.1)
25
+ arel (~> 1.0.0)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.1)
28
+ activemodel (= 3.0.1)
29
+ activesupport (= 3.0.1)
30
+ activesupport (3.0.1)
31
+ archive-tar-minitar (0.5.2)
32
+ arel (1.0.1)
33
+ activesupport (~> 3.0.0)
34
+ bson (1.1.1)
35
+ bson_ext (1.1.1)
36
+ builder (2.1.2)
37
+ columnize (0.3.1)
38
+ erubis (2.6.6)
39
+ abstract (>= 1.0.0)
40
+ git (1.2.5)
41
+ i18n (0.4.2)
42
+ jeweler (1.5.0.pre5)
43
+ bundler (~> 1.0.0)
44
+ git (>= 1.2.5)
45
+ rake
46
+ linecache19 (0.5.11)
47
+ ruby_core_source (>= 0.1.4)
48
+ mail (2.2.9)
49
+ activesupport (>= 2.3.6)
50
+ i18n (~> 0.4.1)
51
+ mime-types (~> 1.16)
52
+ treetop (~> 1.4.8)
53
+ mime-types (1.16)
54
+ mocha (0.9.9)
55
+ rake
56
+ mongo (1.1.1)
57
+ bson (>= 1.1.1)
58
+ polyglot (0.3.1)
59
+ rack (1.2.1)
60
+ rack-mount (0.6.13)
61
+ rack (>= 1.0.0)
62
+ rack-test (0.5.6)
63
+ rack (>= 1.0)
64
+ rails (3.0.1)
65
+ actionmailer (= 3.0.1)
66
+ actionpack (= 3.0.1)
67
+ activerecord (= 3.0.1)
68
+ activeresource (= 3.0.1)
69
+ activesupport (= 3.0.1)
70
+ bundler (~> 1.0.0)
71
+ railties (= 3.0.1)
72
+ railties (3.0.1)
73
+ actionpack (= 3.0.1)
74
+ activesupport (= 3.0.1)
75
+ rake (>= 0.8.4)
76
+ thor (~> 0.14.0)
77
+ rake (0.8.7)
78
+ ruby-debug-base19 (0.11.24)
79
+ columnize (>= 0.3.1)
80
+ linecache19 (>= 0.5.11)
81
+ ruby_core_source (>= 0.1.4)
82
+ ruby-debug19 (0.11.6)
83
+ columnize (>= 0.3.1)
84
+ linecache19 (>= 0.5.11)
85
+ ruby-debug-base19 (>= 0.11.19)
86
+ ruby_core_source (0.1.4)
87
+ archive-tar-minitar (>= 0.5.2)
88
+ shoulda (2.11.3)
89
+ thor (0.14.3)
90
+ treetop (1.4.8)
91
+ polyglot (>= 0.3.1)
92
+ tzinfo (0.3.23)
93
+
94
+ PLATFORMS
95
+ ruby
96
+
97
+ DEPENDENCIES
98
+ activesupport
99
+ bson_ext
100
+ bundler (~> 1.0.0)
101
+ i18n
102
+ jeweler (~> 1.5.0.pre5)
103
+ mocha
104
+ mongo
105
+ rails (>= 2.3.8)
106
+ rake
107
+ ruby-debug19
108
+ shoulda
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,97 @@
1
+ # CentralLogger
2
+
3
+ Log to a central MongoDB from Rails apps.
4
+
5
+ ## Usage
6
+
7
+ 1. Install the gem:
8
+
9
+ gem install central_logger
10
+
11
+ 1. Add the following line to your ApplicationController:
12
+
13
+ include CentralLogger::Filter
14
+
15
+ 1. If using Rails < 3, configure environment.rb as shown below (in config/environment.rb). Otherwise, the logger is
16
+ automatically initialized for all environments.
17
+
18
+ require 'central_logger'
19
+ CentralLogger::Initializer.initialize_deprecated_logger(config)
20
+
21
+ 1. Add mongo settings to database.yml for each environment in which you want to use MongoDB for logging. The values below are defaults:
22
+
23
+ development:
24
+ adapter: mysql
25
+ database: my_app_development
26
+ user: root
27
+ mongo:
28
+ database: my_app # required
29
+ capsize: <%= 10.megabytes %> # default: 250MB for production; 100MB otherwise
30
+ host: localhost # default: localhost
31
+ port: 27017 # default: 27017
32
+
33
+ With that in place, a new MongoDB document (record) will be created for each request and,
34
+ by default will record the following information: Runtime, IP Address, Request Time, Controller,
35
+ Action, Params, Application Name and All messages sent to the logger. The structure of the Mongo document looks like this:
36
+
37
+ {
38
+ 'action' : action_name,
39
+ 'application_name' : action_name,
40
+ 'controller' : controller_name,
41
+ 'ip' : ip_address,
42
+ 'messages' : {
43
+ 'info' : [ ],
44
+ 'debug' : [ ],
45
+ 'error' : [ ],
46
+ 'warn' : [ ],
47
+ 'fatal' : [ ]
48
+ },
49
+ 'params' : { },
50
+ 'path' : path,
51
+ 'request_time' : date_of_request,
52
+ 'runtime' : elapsed_execution_time_in_seconds,
53
+ 'url' : full_url
54
+ }
55
+
56
+ Beyond that, if you want to add extra information to the base of the document
57
+ (let's say something like user_guid on every request that it's available),
58
+ you can just call the Rails.logger.add_metadata method on your logger like so
59
+ (for example from a before_filter):
60
+
61
+ # make sure we're using the CentralLogger in this environment
62
+ if Rails.logger.respond_to?(:add_metadata)
63
+ Rails.logger.add_metadata(:user_guid =&gt; @user_guid)
64
+ end
65
+
66
+ ## Examples
67
+
68
+ And now, for a couple quick examples on getting ahold of this log data...
69
+ First, here's how to get a handle on the MongoDB from within a Rails console:
70
+
71
+ >> db = Rails.logger.mongo_connection
72
+ => #&lt;Mongo::DB:0x102f19ac0 @slave_ok=nil, @name="my_app" ... &gt;
73
+
74
+ >> collection = db[Rails.logger.mongo_collection_name]
75
+ => #&lt;Mongo::Collection:0x1031b3ee8 @name="development_log" ... &gt;
76
+
77
+ Once you've got the collection, you can find all requests for a specific user (with guid):
78
+
79
+ >> cursor = collection.find(:user_guid => '12355')
80
+ => #&lt;Mongo::Cursor:0x1031a3e30 ... &gt;
81
+ >> cursor.count
82
+ => 5
83
+
84
+ Find all requests that took more that one second to complete:
85
+
86
+ >> collection.find({:runtime => {'$gt' => 1000}}).count
87
+ => 3
88
+
89
+ Find all order#show requests with a particular order id (id=order_id):
90
+
91
+ >> collection.find({"controller" => "order", "action"=> "show", "params.id" => order_id})
92
+
93
+ Find all requests with an exception that contains "RoutingError" in the message or stack trace:
94
+
95
+ >> collection.find({"messages.error" => /RoutingError/})
96
+
97
+ Copyright (c) 2009 Phil Burrows, released under the MIT license
@@ -0,0 +1,47 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ require 'jeweler'
7
+
8
+ desc 'Default: run unit tests.'
9
+ task :default => :test
10
+ task :test => :check_dependencies
11
+
12
+ begin
13
+ Bundler.setup(:default, :development)
14
+ rescue Bundler::BundlerError => e
15
+ $stderr.puts e.message
16
+ $stderr.puts "Run `bundle install` to install missing gems"
17
+ exit e.status_code
18
+ end
19
+
20
+ Jeweler::Tasks.new do |gem|
21
+ gem.name = "central_logger"
22
+ gem.summary = %Q{Central Logger for Rails}
23
+ gem.description = %Q{Centralized logging for rails apps using MongoDB. The idea and the core code is from http://github.com/peburrows/central_logger}
24
+ gem.email = "astupka@customink.com"
25
+ gem.homepage = "http://github.com/customink/central_logger"
26
+ gem.authors = ["Phil Burrows", "Alex Stupka"]
27
+ gem.rubyforge_project = "central_logger"
28
+ end
29
+ Jeweler::RubyforgeTasks.new do |rubyforge|
30
+ rubyforge.doc_task = "rdoc"
31
+ end
32
+ # dependencies defined in Gemfile
33
+
34
+ Rake::TestTask.new(:test) do |test|
35
+ test.libs << 'lib' << 'test'
36
+ test.pattern = 'test/**/*_test.rb'
37
+ test.verbose = true
38
+ end
39
+
40
+ Rake::RDocTask.new do |rdoc|
41
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+
43
+ rdoc.rdoc_dir = 'rdoc'
44
+ rdoc.title = "central_logger #{version}"
45
+ rdoc.rdoc_files.include('README*')
46
+ rdoc.rdoc_files.include('lib/**/*.rb')
47
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,93 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{central_logger}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Phil Burrows", "Alex Stupka"]
12
+ s.date = %q{2010-11-01}
13
+ s.description = %q{Centralized logging for rails apps using MongoDB. The idea and the core code is from http://github.com/peburrows/central_logger}
14
+ s.email = %q{astupka@customink.com}
15
+ s.extra_rdoc_files = [
16
+ "README.md"
17
+ ]
18
+ s.files = [
19
+ ".rvmrc",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "MIT-LICENSE",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "central_logger.gemspec",
27
+ "lib/central_logger.rb",
28
+ "lib/central_logger/filter.rb",
29
+ "lib/central_logger/initializer.rb",
30
+ "lib/central_logger/initializer_mixin.rb",
31
+ "lib/central_logger/mongo_logger.rb",
32
+ "lib/railtie.rb",
33
+ "test/active_record.rb",
34
+ "test/config/database.yml",
35
+ "test/rails.rb",
36
+ "test/shoulda_macros/log_macros.rb",
37
+ "test/test_helper.rb",
38
+ "test/unit/central_logger_test.rb"
39
+ ]
40
+ s.homepage = %q{http://github.com/customink/central_logger}
41
+ s.require_paths = ["lib"]
42
+ s.rubyforge_project = %q{central_logger}
43
+ s.rubygems_version = %q{1.3.7}
44
+ s.summary = %q{Central Logger for Rails}
45
+ s.test_files = [
46
+ "test/active_record.rb",
47
+ "test/rails.rb",
48
+ "test/shoulda_macros/log_macros.rb",
49
+ "test/test_helper.rb",
50
+ "test/unit/central_logger_test.rb"
51
+ ]
52
+
53
+ if s.respond_to? :specification_version then
54
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
55
+ s.specification_version = 3
56
+
57
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
+ s.add_runtime_dependency(%q<rake>, [">= 0"])
59
+ s.add_runtime_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_runtime_dependency(%q<mongo>, [">= 0"])
61
+ s.add_runtime_dependency(%q<bson_ext>, [">= 0"])
62
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
63
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
64
+ s.add_development_dependency(%q<i18n>, [">= 0"])
65
+ s.add_development_dependency(%q<activesupport>, [">= 0"])
66
+ s.add_development_dependency(%q<mocha>, [">= 0"])
67
+ s.add_development_dependency(%q<ruby-debug19>, [">= 0"])
68
+ else
69
+ s.add_dependency(%q<rake>, [">= 0"])
70
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
71
+ s.add_dependency(%q<mongo>, [">= 0"])
72
+ s.add_dependency(%q<bson_ext>, [">= 0"])
73
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
74
+ s.add_dependency(%q<shoulda>, [">= 0"])
75
+ s.add_dependency(%q<i18n>, [">= 0"])
76
+ s.add_dependency(%q<activesupport>, [">= 0"])
77
+ s.add_dependency(%q<mocha>, [">= 0"])
78
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
79
+ end
80
+ else
81
+ s.add_dependency(%q<rake>, [">= 0"])
82
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
83
+ s.add_dependency(%q<mongo>, [">= 0"])
84
+ s.add_dependency(%q<bson_ext>, [">= 0"])
85
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre5"])
86
+ s.add_dependency(%q<shoulda>, [">= 0"])
87
+ s.add_dependency(%q<i18n>, [">= 0"])
88
+ s.add_dependency(%q<activesupport>, [">= 0"])
89
+ s.add_dependency(%q<mocha>, [">= 0"])
90
+ s.add_dependency(%q<ruby-debug19>, [">= 0"])
91
+ end
92
+ end
93
+
@@ -0,0 +1,8 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'mongo'
4
+ require 'central_logger/mongo_logger'
5
+ require 'central_logger/filter'
6
+ require 'central_logger/initializer'
7
+ require 'railtie'
8
+
@@ -0,0 +1,22 @@
1
+ module CentralLogger
2
+ module Filter
3
+ def self.included(base)
4
+ base.class_eval { around_filter :enable_central_logger }
5
+ end
6
+
7
+ def enable_central_logger
8
+ return yield unless Rails.logger.respond_to?(:mongoize)
9
+
10
+ # make sure the controller knows how to filter its parameters
11
+ f_params = respond_to?(:filter_parameters) ? filter_parameters(params) : params
12
+ Rails.logger.mongoize({
13
+ :action => action_name,
14
+ :controller => controller_name,
15
+ :path => request.path,
16
+ :url => request.url,
17
+ :params => f_params,
18
+ :ip => request.remote_ip
19
+ }) { yield }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ if Rails::VERSION::MAJOR == 2
2
+ require 'central_logger/initializer_mixin'
3
+
4
+ module CentralLogger
5
+ class Initializer
6
+ extend CentralLogger::InitializerMixin
7
+
8
+ # mirrors code in Rails 2 initializer.rb#initialize_logger
9
+ def self.initialize_deprecated_logger(config)
10
+ logger = config.logger = create_logger(config, config.log_path)
11
+
12
+ silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ module CentralLogger
2
+ module InitializerMixin
3
+ # initialization common to Rails 2.3.8 and 3.0
4
+ def create_logger(config, path)
5
+ level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase)
6
+ logger = MongoLogger.new(:path => path, :level => level)
7
+ logger.auto_flushing = false if Rails.env.production?
8
+ logger
9
+ rescue StandardError => e
10
+ logger = ActiveSupport::BufferedLogger.new(STDERR)
11
+ logger.level = ActiveSupport::BufferedLogger::WARN
12
+ logger.warn(
13
+ "CentralLogger Initializer Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666. " +
14
+ "The log level has been raised to WARN and the output directed to STDERR until the problem is fixed." + "\n" +
15
+ e.message + "\n" + e.backtrace.join("\n")
16
+ )
17
+ logger
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,131 @@
1
+ require 'erb'
2
+ require 'mongo'
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
5
+
6
+ module CentralLogger
7
+ class MongoLogger < ActiveSupport::BufferedLogger
8
+ PRODUCTION_COLLECTION_SIZE = 250.megabytes
9
+ DEFAULT_COLLECTION_SIZE = 100.megabytes
10
+
11
+ attr_reader :db_configuration, :mongo_connection, :mongo_collection_name
12
+
13
+ def initialize(options={})
14
+ path = options[:path] || File.join(Rails.root, "log/#{Rails.env}.log")
15
+ level = options[:level] || DEBUG
16
+ super(path, level)
17
+ internal_initialize
18
+ rescue => e
19
+ # in case the logger is fouled up use stdout
20
+ puts "=> !! A connection to mongo could not be established - the logger will function like a normal ActiveSupport::BufferedLogger !!"
21
+ puts e.message + "\n" + e.backtrace.join("\n")
22
+ end
23
+
24
+ def add_metadata(options={})
25
+ options.each_pair do |key, value|
26
+ unless [:messages, :request_time, :ip, :runtime, :application_name].include?(key.to_sym)
27
+ @mongo_record[key] = value
28
+ else
29
+ raise ArgumentError, ":#{key} is a reserved key for the central logger. Please choose a different key"
30
+ end
31
+ end
32
+ end
33
+
34
+ def add(severity, message = nil, progname = nil, &block)
35
+ if @level <= severity && message.present? && @mongo_record.present?
36
+ # remove Rails colorization to get the actual message
37
+ message.gsub!(/(\e(\[([\d;]*[mz]?))?)?/, '').strip! if logging_colorized?
38
+ @mongo_record[:messages][level_to_sym(severity)] << message
39
+ end
40
+ super
41
+ end
42
+
43
+ # Drop the capped_collection and recreate it
44
+ def reset_collection
45
+ @mongo_connection[@mongo_collection_name].drop
46
+ create_collection
47
+ end
48
+
49
+ def mongoize(options={})
50
+ @mongo_record = options.merge({
51
+ :messages => Hash.new { |hash, key| hash[key] = Array.new },
52
+ :request_time => Time.now.getutc,
53
+ :application_name => @application_name
54
+ })
55
+ # In case of exception, make sure it's set
56
+ runtime = 0
57
+ runtime = Benchmark.measure do
58
+ yield
59
+ end
60
+ rescue Exception => e
61
+ add(3, e.message + "\n" + e.backtrace.join("\n"))
62
+ # Reraise the exception for anyone else who cares
63
+ raise e
64
+ ensure
65
+ insert_log_record(runtime)
66
+ end
67
+
68
+ private
69
+ # facilitate testing
70
+ def internal_initialize
71
+ configure
72
+ connect
73
+ check_for_collection
74
+ end
75
+
76
+ def configure
77
+ default_capsize = Rails.env.production? ? PRODUCTION_COLLECTION_SIZE : DEFAULT_COLLECTION_SIZE
78
+ user_config = YAML::load(ERB.new(IO.read(File.join(Rails.root, 'config/database.yml'))).result)[Rails.env]['mongo'] || {}
79
+ @application_name = Rails.root.basename.to_s
80
+
81
+ @mongo_collection_name = "#{Rails.env}_log"
82
+
83
+ @db_configuration = {
84
+ 'host' => 'localhost',
85
+ 'port' => 27017,
86
+ 'capsize' => default_capsize}.merge(user_config)
87
+ end
88
+
89
+ def connect
90
+ @mongo_connection ||= Mongo::Connection.new(@db_configuration['host'],
91
+ @db_configuration['port'],
92
+ :auto_reconnect => true).db(@db_configuration['database'])
93
+ end
94
+
95
+ def create_collection
96
+ @mongo_connection.create_collection(@mongo_collection_name,
97
+ {:capped => true, :size => @db_configuration['capsize']})
98
+ end
99
+
100
+ def check_for_collection
101
+ # setup the capped collection if it doesn't already exist
102
+ unless @mongo_connection.collection_names.include?(@mongo_collection_name)
103
+ create_collection
104
+ end
105
+ end
106
+
107
+ def insert_log_record(runtime)
108
+ @mongo_record[:runtime] = (runtime.real * 1000).ceil
109
+ @mongo_connection[@mongo_collection_name].insert(@mongo_record) rescue nil
110
+ end
111
+
112
+ def level_to_sym(level)
113
+ case level
114
+ when 0 then :debug
115
+ when 1 then :info
116
+ when 2 then :warn
117
+ when 3 then :error
118
+ when 4 then :fatal
119
+ when 5 then :unknown
120
+ end
121
+ end
122
+
123
+ def logging_colorized?
124
+ # Cache it since these ActiveRecord attributes are assigned after logger initialization occurs
125
+ @colorized ||= Object.const_defined?(:ActiveRecord) &&
126
+ (Rails::VERSION::MAJOR >= 3 ?
127
+ ActiveRecord::LogSubscriber.colorize_logging :
128
+ ActiveRecord::Base.colorize_logging)
129
+ end
130
+ end # class MongoLogger
131
+ end
@@ -0,0 +1,16 @@
1
+ if Rails::VERSION::MAJOR == 3
2
+ require 'central_logger/initializer_mixin'
3
+
4
+ class Railtie < Rails::Railtie
5
+ include CentralLogger::InitializerMixin
6
+
7
+ # load earlier than bootstrap.rb initializer loads the default logger. bootstrap
8
+ # initializer will then skip its own initialization once Rails.logger is defined
9
+ initializer :initialize_central_logger, :before => :initialize_logger do
10
+ app_config = Rails.application.config
11
+ Rails.logger = config.logger = create_logger(app_config,
12
+ app_config.paths.log.to_a.first)
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,13 @@
1
+ module ActiveRecord
2
+ class LogSubscriber
3
+ def self.colorize_logging
4
+ true
5
+ end
6
+ end
7
+
8
+ class Base
9
+ def self.colorize_logging
10
+ true
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ test:
2
+ adapter: mysql
3
+ username: user
4
+ database: database
5
+ mongo:
6
+ database: system_log
@@ -0,0 +1,13 @@
1
+ class Rails
2
+ module VERSION
3
+ MAJOR = 3
4
+ end
5
+
6
+ def self.env
7
+ ActiveSupport::StringInquirer.new("test")
8
+ end
9
+
10
+ def self.root
11
+ Pathname.new(File.dirname(__FILE__))
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ module LogMacros
2
+ def should_contain_one_log_record
3
+ should "contain a log record" do
4
+ assert_equal 1, @con[@central_logger.mongo_collection_name].count
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,34 @@
1
+ require 'test/unit'
2
+ require 'shoulda'
3
+ require 'mocha'
4
+ # mock rails class
5
+ require 'pathname'
6
+ require 'rails'
7
+
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+
11
+ Shoulda.autoload_macros("#{File.dirname(__FILE__)}/..")
12
+
13
+ class Test::Unit::TestCase
14
+ def log(msg)
15
+ @central_logger.mongoize({"id" => 1}) do
16
+ @central_logger.debug(msg)
17
+ end
18
+ end
19
+
20
+ def log_metadata(options)
21
+ @central_logger.mongoize({"id" => 1}) do
22
+ @central_logger.add_metadata(options)
23
+ end
24
+ end
25
+
26
+ def require_bogus_active_record
27
+ require 'active_record'
28
+ end
29
+
30
+ def common_setup
31
+ @con = @central_logger.mongo_connection
32
+ @collection = @con[@central_logger.mongo_collection_name]
33
+ end
34
+ end
@@ -0,0 +1,107 @@
1
+ require 'test_helper'
2
+ require 'central_logger/mongo_logger'
3
+
4
+ # test the basic stuff
5
+ class CentralLogger::MongoLoggerTest < Test::Unit::TestCase
6
+ extend LogMacros
7
+
8
+ context "A CentralLogger::MongoLogger" do
9
+ context "during configuration in instantiation" do
10
+ setup do
11
+ CentralLogger::MongoLogger.any_instance.stubs(:internal_initialize).returns(nil)
12
+ @central_logger = CentralLogger::MongoLogger.new
13
+ @central_logger.send(:configure)
14
+ end
15
+
16
+ should "set the default host, port, and capsize if not configured" do
17
+ assert_equal 'localhost', @central_logger.db_configuration['host']
18
+ assert_equal 27017, @central_logger.db_configuration['port']
19
+ assert_equal CentralLogger::MongoLogger::DEFAULT_COLLECTION_SIZE, @central_logger.db_configuration['capsize']
20
+ end
21
+
22
+ should "set the mongo collection name depending on the Rails environment" do
23
+ assert_equal "#{Rails.env}_log", @central_logger.mongo_collection_name
24
+ end
25
+
26
+ context "upon connecting to an empty database" do
27
+ setup do
28
+ @central_logger.send(:connect)
29
+ common_setup
30
+ @collection.drop
31
+ end
32
+
33
+ should "expose a valid mongo connection" do
34
+ assert_instance_of Mongo::DB, @central_logger.mongo_connection
35
+ end
36
+
37
+ should "create a capped collection in the database with the configured size" do
38
+ @central_logger.send(:check_for_collection)
39
+ assert @con.collection_names.include?(@central_logger.mongo_collection_name)
40
+ # new capped collections are X MB + 5888 bytes, but don't be too strict in case that changes
41
+ assert @collection.stats["storageSize"] < CentralLogger::MongoLogger::DEFAULT_COLLECTION_SIZE + 1.megabyte
42
+ end
43
+ end
44
+ end
45
+
46
+ context "after instantiation" do
47
+ setup do
48
+ @central_logger = CentralLogger::MongoLogger.new
49
+ common_setup
50
+ end
51
+
52
+ context "upon insertion of a log record when active record is not used" do
53
+ # mock ActiveRecord has not been included
54
+ setup do
55
+ log("Test")
56
+ end
57
+
58
+ should_contain_one_log_record
59
+
60
+ should "allow recreation of the capped collection to remove all records" do
61
+ @central_logger.reset_collection
62
+ assert_equal 0, @collection.count
63
+ end
64
+ end
65
+
66
+ context "upon insertion of a colorized log record when ActiveRecord is used" do
67
+ setup do
68
+ @log_message = "TESTING"
69
+ require_bogus_active_record
70
+ @central_logger.reset_collection
71
+ log("\e[31m #{@log_message} \e[0m")
72
+ end
73
+
74
+ should "detect logging is colorized" do
75
+ assert @central_logger.send(:logging_colorized?)
76
+ end
77
+
78
+ should_contain_one_log_record
79
+
80
+ should "strip out colorization from log messages" do
81
+ assert_equal 1, @collection.find({"messages.debug" => @log_message}).count
82
+ end
83
+ end
84
+
85
+ should "add application metadata to the log record" do
86
+ options = {"application" => self.class.name}
87
+ log_metadata(options)
88
+ assert_equal 1, @collection.find({"application" => self.class.name}).count
89
+ end
90
+ end
91
+
92
+ context "logging at INFO level" do
93
+ setup do
94
+ @central_logger = CentralLogger::MongoLogger.new(:level => CentralLogger::MongoLogger::INFO)
95
+ @central_logger.reset_collection
96
+ common_setup
97
+ log("INFO")
98
+ end
99
+
100
+ should_contain_one_log_record
101
+
102
+ should "not log DEBUG messages" do
103
+ assert_equal 0, @collection.find_one({}, :fields => ["messages"])["messages"].count
104
+ end
105
+ end
106
+ end
107
+ end
metadata ADDED
@@ -0,0 +1,222 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: central_logger
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - Phil Burrows
13
+ - Alex Stupka
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-01 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: rake
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: bundler
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 0
45
+ - 0
46
+ version: 1.0.0
47
+ type: :runtime
48
+ version_requirements: *id002
49
+ - !ruby/object:Gem::Dependency
50
+ name: mongo
51
+ prerelease: false
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :runtime
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: bson_ext
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ type: :runtime
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: jeweler
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ~>
82
+ - !ruby/object:Gem::Version
83
+ segments:
84
+ - 1
85
+ - 5
86
+ - 0
87
+ - pre5
88
+ version: 1.5.0.pre5
89
+ type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: shoulda
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ segments:
100
+ - 0
101
+ version: "0"
102
+ type: :development
103
+ version_requirements: *id006
104
+ - !ruby/object:Gem::Dependency
105
+ name: i18n
106
+ prerelease: false
107
+ requirement: &id007 !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ segments:
113
+ - 0
114
+ version: "0"
115
+ type: :development
116
+ version_requirements: *id007
117
+ - !ruby/object:Gem::Dependency
118
+ name: activesupport
119
+ prerelease: false
120
+ requirement: &id008 !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ segments:
126
+ - 0
127
+ version: "0"
128
+ type: :development
129
+ version_requirements: *id008
130
+ - !ruby/object:Gem::Dependency
131
+ name: mocha
132
+ prerelease: false
133
+ requirement: &id009 !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ segments:
139
+ - 0
140
+ version: "0"
141
+ type: :development
142
+ version_requirements: *id009
143
+ - !ruby/object:Gem::Dependency
144
+ name: ruby-debug19
145
+ prerelease: false
146
+ requirement: &id010 !ruby/object:Gem::Requirement
147
+ none: false
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ segments:
152
+ - 0
153
+ version: "0"
154
+ type: :development
155
+ version_requirements: *id010
156
+ description: Centralized logging for rails apps using MongoDB. The idea and the core code is from http://github.com/peburrows/central_logger
157
+ email: astupka@customink.com
158
+ executables: []
159
+
160
+ extensions: []
161
+
162
+ extra_rdoc_files:
163
+ - README.md
164
+ files:
165
+ - .rvmrc
166
+ - Gemfile
167
+ - Gemfile.lock
168
+ - MIT-LICENSE
169
+ - README.md
170
+ - Rakefile
171
+ - VERSION
172
+ - central_logger.gemspec
173
+ - lib/central_logger.rb
174
+ - lib/central_logger/filter.rb
175
+ - lib/central_logger/initializer.rb
176
+ - lib/central_logger/initializer_mixin.rb
177
+ - lib/central_logger/mongo_logger.rb
178
+ - lib/railtie.rb
179
+ - test/active_record.rb
180
+ - test/config/database.yml
181
+ - test/rails.rb
182
+ - test/shoulda_macros/log_macros.rb
183
+ - test/test_helper.rb
184
+ - test/unit/central_logger_test.rb
185
+ has_rdoc: true
186
+ homepage: http://github.com/customink/central_logger
187
+ licenses: []
188
+
189
+ post_install_message:
190
+ rdoc_options: []
191
+
192
+ require_paths:
193
+ - lib
194
+ required_ruby_version: !ruby/object:Gem::Requirement
195
+ none: false
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ segments:
200
+ - 0
201
+ version: "0"
202
+ required_rubygems_version: !ruby/object:Gem::Requirement
203
+ none: false
204
+ requirements:
205
+ - - ">="
206
+ - !ruby/object:Gem::Version
207
+ segments:
208
+ - 0
209
+ version: "0"
210
+ requirements: []
211
+
212
+ rubyforge_project: central_logger
213
+ rubygems_version: 1.3.7
214
+ signing_key:
215
+ specification_version: 3
216
+ summary: Central Logger for Rails
217
+ test_files:
218
+ - test/active_record.rb
219
+ - test/rails.rb
220
+ - test/shoulda_macros/log_macros.rb
221
+ - test/test_helper.rb
222
+ - test/unit/central_logger_test.rb