├── .gitignore ├── CHANGES.md ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── lib ├── multi_logger.rb ├── multi_logger │ └── version.rb └── railties │ └── lib │ └── rails.rb ├── multi_logger.gemspec └── spec ├── helper.rb ├── log └── .gitkeep └── multi_logger_spec.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /CHANGES.md: -------------------------------------------------------------------------------- 1 | # Change log 2 | 3 | ## 0.2.0 - 2020/07/14 4 | 5 | * [Enhancement] Accept `STDOUT` as log path - Konstantin 6 | 7 | ## 0.1.0 - 2013/09/13 8 | 9 | * [Enhancement] Accept `shift_age` and `shift size` as an argument to the `Logger.new` - Keisuke KITA 10 | 11 | ## 0.0.1 - 2013/05/30 12 | 13 | * Initial publication 14 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Specify your gem's dependencies in multi_logger.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013 lulalala 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MultiLogger 2 | 3 | Makes it easier to create multiple log files in Rails. 4 | 5 | ## Installation 6 | 7 | Add this line to your Rails application's Gemfile: 8 | 9 | gem 'multi_logger' 10 | 11 | And then execute: 12 | 13 | $ bundle install 14 | 15 | Or install it yourself as: 16 | 17 | $ gem install multi_logger 18 | 19 | ## Usage 20 | 21 | To setup a logger, create an initializer script such as `[Rails.root]/config/initializers/logger.rb` with: 22 | 23 | MultiLogger.add_logger('mail') 24 | 25 | This will create a log file located at `log/mail.log`. 26 | 27 | Then In Rails, you can log by calling the following: 28 | 29 | Rails.logger.mail.debug('42') 30 | 31 | The `Rails.` reference can be omitted at the usual places in Rails (e.g. controllers and views). 32 | 33 | Note that log_name must not collide with existing method names in Rails logger, so names such as 'debug' or 'info' can not be used. You should try calling `add_logger` in Rails console to test if it is ok or raises an error. 34 | 35 | ## Advanced 36 | 37 | You can assign formatter to loggers directly, or pass the formatter during setup: 38 | 39 | formatter = Proc.new{|severity, time, progname, msg| 40 | formatted_severity = sprintf("%-5s",severity.to_s) 41 | formatted_time = time.strftime("%Y-%m-%d %H:%M:%S") 42 | "[#{formatted_severity} #{formatted_time} #{$$}] #{msg.to_s.strip}\n" 43 | } 44 | MultiLogger.add_logger('mail', formatter:formatter) 45 | MultiLogger.add_logger('user', formatter:formatter) 46 | 47 | To set a different path to the log file, use `:path` option. 48 | For example, for setting a different file to each environment use: 49 | 50 | MultiLogger.add_logger('mail', formatter:formatter, path:"mail_#{Rails.env}") 51 | 52 | 53 | ## Contributing 54 | 55 | 1. Fork it 56 | 2. Create your feature branch (`git checkout -b my-new-feature`) 57 | 3. Commit your changes (`git commit -am 'Add some feature'`) 58 | 4. Push to the branch (`git push origin my-new-feature`) 59 | 5. Create new Pull Request 60 | 61 | ## License 62 | 63 | MIT License (See LICENSE.txt) 64 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require "bundler/gem_tasks" 2 | 3 | require 'rake/testtask' 4 | Rake::TestTask.new do |t| 5 | t.libs.push "lib" 6 | t.libs.push "spec" 7 | t.test_files = FileList['spec/**/*_spec.rb'] 8 | t.verbose = true 9 | end 10 | -------------------------------------------------------------------------------- /lib/multi_logger.rb: -------------------------------------------------------------------------------- 1 | require "multi_logger/version" 2 | 3 | module MultiLogger 4 | class << self 5 | def add_logger(name, options={}) 6 | name = name.to_s 7 | rails_logger_class = get_rails_logger_class() 8 | 9 | raise "'#{name}' is reserved in #{rails_logger_class} and can not be used as a log accessor name." if rails_logger_class.method_defined?(name) 10 | 11 | logger = Logger.new(*extract_options(name, options)) 12 | rails_logger_class.class_eval do 13 | define_method name.to_sym do 14 | logger 15 | end 16 | end 17 | 18 | logger.formatter = options[:formatter] if options[:formatter] 19 | logger 20 | end 21 | 22 | # Computes log file path 23 | def get_path(name, path=nil) 24 | return path if path == STDOUT 25 | 26 | if path.nil? 27 | path = name.underscore 28 | end 29 | if !path.include?('/') 30 | path = Rails.root.join('log',path).to_s 31 | end 32 | if !path.end_with?('.log') 33 | path += '.log' 34 | end 35 | path 36 | end 37 | 38 | def get_rails_logger_class 39 | if defined?(ActiveSupport::BufferedLogger) 40 | ActiveSupport::BufferedLogger 41 | elsif defined?(ActiveSupport::Logger) 42 | ActiveSupport::Logger 43 | else 44 | raise 'Rails logger not found' 45 | end 46 | end 47 | 48 | def extract_options(name, options) 49 | path = get_path(name, options[:path]) 50 | 51 | if options[:shift_age] && options[:shift_size] 52 | [path, options[:shift_age], options[:shift_size]] 53 | elsif options[:shift_age] 54 | # options[:shift_age] => 'daily', 'weekly' 55 | [path, options[:shift_age]] 56 | else 57 | [path] 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /lib/multi_logger/version.rb: -------------------------------------------------------------------------------- 1 | module MultiLogger 2 | VERSION = "0.2.0" 3 | end 4 | -------------------------------------------------------------------------------- /lib/railties/lib/rails.rb: -------------------------------------------------------------------------------- 1 | module Rails 2 | class << self 3 | def loggers 4 | MultiLogger 5 | end 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /multi_logger.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'multi_logger/version' 5 | 6 | Gem::Specification.new do |gem| 7 | gem.name = "multi_logger" 8 | gem.version = MultiLogger::VERSION 9 | gem.authors = ["lulalala"] 10 | gem.email = ["mark@goodlife.tw"] 11 | gem.description = %q{Create multiple loggers in Rails.} 12 | gem.summary = %q{Provide helper to define loggers and access them. Each logger will log into a different file under the log folder.} 13 | 14 | gem.homepage = "https://github.com/lulalala/multi_logger" 15 | 16 | gem.files = `git ls-files`.split($/) 17 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 18 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 19 | gem.require_paths = ["lib"] 20 | 21 | gem.add_dependency 'railties' 22 | gem.add_development_dependency "activesupport" 23 | gem.add_development_dependency "mocha" 24 | end 25 | -------------------------------------------------------------------------------- /spec/helper.rb: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | 3 | begin 4 | require 'bundler' 5 | rescue LoadError => e 6 | STDERR.puts e.message 7 | STDERR.puts "Run `gem install bundler` to install Bundler." 8 | exit e.status_code 9 | end 10 | 11 | begin 12 | Bundler.setup(:default, :development, :test) 13 | rescue Bundler::BundlerError => e 14 | STDERR.puts e.message 15 | STDERR.puts "Run `bundle install` to install missing gems." 16 | exit e.status_code 17 | end 18 | 19 | require 'minitest/autorun' 20 | require 'minitest/spec' 21 | require "mocha/mini_test" 22 | -------------------------------------------------------------------------------- /spec/log/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lulalala/multi_logger/03b2c7a78e7d1a65f596b6706bc298450924c3d0/spec/log/.gitkeep -------------------------------------------------------------------------------- /spec/multi_logger_spec.rb: -------------------------------------------------------------------------------- 1 | require 'helper' 2 | require 'multi_logger' 3 | 4 | require 'logger' 5 | require 'active_support/core_ext/string' 6 | 7 | # Dummy class to avoid loading Rails 8 | module Rails 9 | def self.root 10 | Pathname.new('./spec/') 11 | end 12 | end 13 | 14 | describe MultiLogger do 15 | it 'has version' do 16 | MultiLogger.const_get('VERSION').wont_be_empty 17 | end 18 | 19 | describe '.add_logger' do 20 | it 'raises error if name already in use as method name' do 21 | lambda { MultiLogger.add_logger('object_id') }.must_raise RuntimeError 22 | end 23 | it 'defines a instance method in Rails Logger class linking to custom logger' do 24 | rails_logger_klass = Class.new 25 | MultiLogger.stubs(:get_rails_logger_class).returns(rails_logger_klass) 26 | 27 | logger = Logger.new('test') 28 | Logger.stubs(:new).returns(logger) 29 | 30 | MultiLogger.add_logger('payment').must_equal logger 31 | 32 | rails_logger_klass.new.payment.must_equal logger 33 | end 34 | it 'assigns formatter to custom logger' do 35 | rails_logger_klass = Class.new 36 | MultiLogger.stubs(:get_rails_logger_class).returns(rails_logger_klass) 37 | 38 | logger = Logger.new('test') 39 | Logger.stubs(:new).returns(logger) 40 | 41 | formatter = mock('formatter') 42 | MultiLogger.add_logger('fb',{formatter:formatter}).must_equal logger 43 | 44 | rails_logger_klass.new.fb.must_equal logger 45 | logger.formatter.must_equal formatter 46 | end 47 | end 48 | 49 | describe '.get_path' do 50 | it '' do 51 | MultiLogger.send(:get_path,'parser').to_s.must_equal './spec/log/parser.log' 52 | end 53 | it 'uses path as file path different to name' do 54 | MultiLogger.send(:get_path,'fb','facebook').to_s.must_equal './spec/log/facebook.log' 55 | end 56 | it 'uses path as file path (relative to Rails root) different to name' do 57 | MultiLogger.send(:get_path,'fb','facebook').to_s.must_equal './spec/log/facebook.log' 58 | end 59 | it 'uses path as file path as is if it contains slash' do 60 | MultiLogger.send(:get_path,'fb','./facebook').to_s.must_equal './facebook.log' 61 | end 62 | it 'does not append .log if path already ends with it' do 63 | MultiLogger.send(:get_path,'fb','./facebook.log').to_s.must_equal './facebook.log' 64 | end 65 | end 66 | end 67 | --------------------------------------------------------------------------------