yell 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .idea
5
+
6
+ # bundler
7
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yell.gemspec
4
+ gemspec
5
+
6
+
7
+ group :development do
8
+ gem "rake"
9
+
10
+ gem "rspec", "~> 2"
11
+ gem "timecop"
12
+ end
data/Rakefile ADDED
@@ -0,0 +1,26 @@
1
+ $LOAD_PATH.unshift( 'lib' )
2
+
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ # === RSpec
7
+ require 'rspec/core/rake_task'
8
+
9
+ desc "Run specs"
10
+ RSpec::Core::RakeTask.new do |t|
11
+ t.rspec_opts = %w(-fs --color)
12
+ end
13
+
14
+ task :default => :spec
15
+
16
+
17
+ # === Rdoc
18
+ require 'rake/rdoctask'
19
+ Rake::RDocTask.new do |rdoc|
20
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
21
+
22
+ rdoc.rdoc_dir = 'rdoc'
23
+ rdoc.title = "inventory #{version}"
24
+ rdoc.rdoc_files.include('README*')
25
+ rdoc.rdoc_files.include('lib/**/*.rb')
26
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'yell'
@@ -0,0 +1,72 @@
1
+ module Yell::Adapters
2
+ class Base
3
+
4
+ attr_reader :name # name of the logger this adapter belongs to
5
+
6
+ # Initialize a new base adapter. Other adapters should inherit from it.
7
+ def initialize ( options = {}, &block )
8
+ @block = block
9
+
10
+ @name = options[:name] || Yell.config.env
11
+ @level, @data = '', '' # default
12
+ end
13
+
14
+ def call ( level, msg )
15
+ reset!(true) if reset? # connect / get a file handle or whatever
16
+
17
+ @level, @message = level, msg
18
+
19
+ # self.instance_eval &@block if @block
20
+ @block.call( self ) if @block
21
+ end
22
+
23
+ def message
24
+ return @message if @message.is_a?( String )
25
+
26
+ @message.inspect
27
+ end
28
+
29
+ # Convenience method for resetting the processor.
30
+ #
31
+ # @param [true, false] now Perform the reset immediately? (default false)
32
+ def reset!( now = false )
33
+ close
34
+ open if now
35
+ end
36
+
37
+ # Opens the logfile or connection (in case of a database adapter)
38
+ def open
39
+ open! unless opened?
40
+ end
41
+
42
+ # Closes the file handle or connection (in case of a database adapter)
43
+ def close
44
+ close! unless closed?
45
+ end
46
+
47
+
48
+ private
49
+
50
+ def reset?; closed?; end
51
+
52
+ # stub
53
+ def open!
54
+ raise "Not implemented"
55
+ end
56
+
57
+ def opened?; false; end
58
+
59
+ # stub
60
+ def close!
61
+ raise "Not implemented"
62
+ end
63
+
64
+ def closed?; !opened?; end
65
+
66
+ # stub
67
+ def write
68
+ raise 'Not implemented'
69
+ end
70
+
71
+ end
72
+ end
@@ -0,0 +1,39 @@
1
+ module Yell::Adapters
2
+ class Datefile < Yell::Adapters::File
3
+
4
+ DefaultDatePattern = "%Y%m%d"
5
+
6
+ def initialize ( options = {}, &block )
7
+ @date_pattern = options[:date_pattern] || DefaultDatePattern
8
+ @date = nil # default; do not override --R
9
+
10
+ @file_basename = options[:filename] || default_filename
11
+ options[:filename] = @file_basename
12
+
13
+ super( options, &block )
14
+ end
15
+
16
+ def reset!( now )
17
+ @filename = new_filename
18
+ super( now )
19
+ end
20
+
21
+
22
+ private
23
+
24
+ def reset?
25
+ _date = Time.now.strftime( @date_pattern )
26
+ unless opened? && _date == @date
27
+ @date = _date
28
+ return true
29
+ end
30
+
31
+ false
32
+ end
33
+
34
+ def new_filename
35
+ @file_basename.sub( /(\.\w+)?$/, ".#{@date}\\1" )
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,95 @@
1
+ module Yell::Adapters
2
+ class File < Yell::Adapters::Base
3
+
4
+ Colors = {
5
+ 'DEBUG' => "\e[32;1m", # green;bold
6
+ # 'INFO' => "\e[0m", # white
7
+ 'WARN' => "\e[33;1m", # yello;bold
8
+ 'ERROR' => "\e[31;1m", # red;bold
9
+ 'FATAL' => "\e[35;1m", # magenta;bold
10
+ 'UNKNOWN' => "\e[36m", # cyan
11
+ 'DEFAULT' => "\e[0m" # NONE
12
+ }
13
+
14
+ def initialize ( options = {}, &block )
15
+ super
16
+
17
+ @formatter = formatter_from( options )
18
+
19
+ @colorize = options[:colorize]
20
+ @filename = options[:filename] || default_filename
21
+
22
+ @file_prefix, @file_suffix = options[:file_prefix], options[:file_suffix]
23
+
24
+ # validate the filename
25
+ unless @filename.is_a?( String )
26
+ raise( TypeError, "Argument :filename must be a string." )
27
+ end
28
+ end
29
+
30
+ def call ( level, msg )
31
+ super # Base call
32
+
33
+ msg = @formatter.format( @level, message )
34
+ msg = colorize( @level, msg ) if @colorize
35
+ msg << "\n" unless msg[-1] == ?\n # add new line if there is none
36
+
37
+ write( msg )
38
+ end
39
+
40
+
41
+ private
42
+
43
+ def write ( msg )
44
+ @file.print( msg )
45
+ @file.flush
46
+ rescue Exception => e
47
+ close # make sure the file gets closed
48
+ raise( e ) # re-raise the error
49
+ end
50
+
51
+ def close!
52
+ @file.close
53
+ @file = nil
54
+ end
55
+
56
+ def open!
57
+ # create directory if not exists
58
+ dirname = ::File.dirname( @filename )
59
+ FileUtils.mkdir_p( dirname ) unless ::File.directory?( dirname )
60
+
61
+ # open file for appending if exists, or create a new
62
+ filename = [ dirname, "#{@file_prefix}#{::File.basename(@filename)}#{@file_suffix}" ].join( '/' )
63
+ @file = ::File.open( filename, ::File::WRONLY|::File::APPEND|::File::CREAT )
64
+ end
65
+
66
+ def opened?; !@file.nil?; end
67
+
68
+ # Returns the right formatter from the given options
69
+ def formatter_from( options )
70
+ if options.key?(:formatter)
71
+ # this is done, so we can set :formatter => false to just output the given message
72
+ options[:formatter] || Yell::Formatter.new( "%m" )
73
+ elsif options[:formatter]
74
+ # the options :formatter was given
75
+ Yell::Formatter.new(
76
+ options[:formatter][:pattern],
77
+ options[:formatter][:date_pattern]
78
+ )
79
+ else
80
+ # Standard formatter
81
+ Yell::Formatter.new
82
+ end
83
+ end
84
+
85
+ def colorize( level, msg )
86
+ return msg unless color = Colors[level.upcase]
87
+ color + msg + Colors['DEFAULT']
88
+ end
89
+
90
+ def default_filename
91
+ "#{Yell.config.env}.log"
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,19 @@
1
+ module Yell
2
+ module Adapters
3
+
4
+ Dir[ ::File.dirname(__FILE__) + '/adapters/*.rb' ].each do |file|
5
+ autoload ::File.basename(file, '.rb').capitalize, file
6
+ end
7
+
8
+ # returns an instance of the given processor type
9
+ def self.new( type, options = {}, &block )
10
+ klass = case type
11
+ when String, Symbol then const_get( type.to_s.capitalize )
12
+ else type
13
+ end
14
+
15
+ klass.new( options, &block )
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ module Yell
2
+ class Config
3
+
4
+ def initialize( yaml_file = nil )
5
+ @yaml_file = yaml_file
6
+
7
+ reload!
8
+ end
9
+
10
+ def reload!; @options = nil; end
11
+
12
+ def []( key ); options[key]; end
13
+
14
+ def options
15
+ @options ||= begin
16
+ if yaml_file_defined?
17
+ require 'yaml'
18
+ require 'erb'
19
+
20
+ (YAML.load( ERB.new( File.read( yaml_file ) ).result ) || {})[ env ] || {}
21
+ else
22
+ {} # default
23
+ end
24
+ end
25
+ end
26
+
27
+ def env
28
+ ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'default'
29
+ end
30
+
31
+ def root
32
+ return ENV['RAILS_ROOT'] if ENV['RAILS_ROOT']
33
+ return RAILS_ROOT if defined?( RAILS_ROOT )
34
+
35
+ '.'
36
+ end
37
+
38
+
39
+ private
40
+
41
+ def yaml_file_defined?
42
+ yaml_file && File.exist?( yaml_file )
43
+ end
44
+
45
+ # Locates the yell.yml file. The file can end in .yml or .yaml,
46
+ # and be located in the current directory (eg. project root) or
47
+ # in a .config/ or config/ subdirectory of the current directory.
48
+ def yaml_file
49
+ @yaml_file || Dir.glob( "#{root}/{,.config/,config/}yell{.yml,.yaml}" ).first
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,58 @@
1
+ module Yell
2
+ class Formatter
3
+
4
+ PatternTable = {
5
+ "m" => "message",
6
+ "d" => "date",
7
+ "l" => "level.downcase",
8
+ "L" => "level.upcase",
9
+ "p" => "$$", # pid
10
+ "h" => "hostname"
11
+ }
12
+ PatternRegexp = /([^%]*)(%\d*)?([dlLphm])?(.*)/
13
+
14
+ DefaultPattern = "%d [%5L] %p %h: %m"
15
+ DefaultDatePattern = "%Y-%m-%d %H:%M:%S" # ISO8601
16
+
17
+
18
+ def initialize ( pattern = nil, date_pattern = nil )
19
+ @pattern = pattern || DefaultPattern
20
+ @date_pattern = date_pattern || DefaultDatePattern
21
+
22
+ define_format_method
23
+ end
24
+
25
+
26
+ private
27
+
28
+ def define_format_method
29
+ buff, args, _pattern = "", [], @pattern.dup
30
+
31
+ while true
32
+ match = PatternRegexp.match( _pattern )
33
+
34
+ buff << match[1] unless match[1].empty?
35
+ break if match[2].nil?
36
+
37
+ buff << match[2] + 's' # '%s'
38
+ args << PatternTable[ match[3] ]
39
+
40
+ _pattern = match[4]
41
+ end
42
+
43
+ instance_eval %-
44
+ def format ( level, message )
45
+ sprintf( "#{buff}", #{args.join(',')} )
46
+ end
47
+ -
48
+ end
49
+
50
+ def date; Time.now.strftime( @date_pattern ); end
51
+
52
+ def hostname
53
+ return @hostname if defined?( @hostname )
54
+ @hostname = Socket.gethostname rescue nil
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,82 @@
1
+ module Yell
2
+ class Logger
3
+ Levels = [ 'debug', 'info', 'warn', 'error', 'fatal', 'unknown' ]
4
+
5
+
6
+ def initialize( *args, &block )
7
+ @adapters = []
8
+
9
+ # extract options
10
+ @options = args.last.is_a?(Hash) ? args.pop : {}
11
+
12
+ # check if filename was given as argument and put it into the @options
13
+ if args.last.is_a?( String )
14
+ @options[:filename] = args.pop unless @options[:filename]
15
+ end
16
+
17
+ @default_adapter = args.last.is_a?( Symbol ) ? args.pop : :file
18
+
19
+ # eval the given block if any
20
+ instance_eval( &block ) if block
21
+
22
+ build
23
+ end
24
+
25
+ # === the following methods are used for the logger setup
26
+ def adapter ( type, options = {}, &block )
27
+ @adapters << Yell::Adapters.new( type, @options.merge(options), &block )
28
+ rescue LoadError => e
29
+
30
+ end
31
+
32
+ def level ( val )
33
+ @level = case val
34
+ when Integer then val
35
+ when String, Symbol then Levels.index( val.to_s )
36
+ else nil
37
+ end
38
+ end
39
+
40
+ # Convenience method for resetting all adapters of the Logger.
41
+ #
42
+ # @param [true, false] now Perform the reset immediately? (default false)
43
+ def reset!( now = false )
44
+ close
45
+ open if now
46
+ end
47
+
48
+ def close; @adapters.each(&:close); end
49
+ def open; @adapters.each(&:open); end
50
+
51
+
52
+ private
53
+
54
+ def build
55
+ adapter @default_adapter if @adapters.empty? # default adapter when none defined
56
+
57
+ define_log_methods
58
+ end
59
+
60
+ def define_log_methods
61
+ Levels.each_with_index do |name, index|
62
+ instance_eval %-
63
+ def #{name}?; #{@level.nil? || index >= @level}; end
64
+
65
+ def #{name} ( data = '' )
66
+ return unless #{name}?
67
+
68
+ data = yield if block_given?
69
+ process( "#{name}", data )
70
+
71
+ data
72
+ end
73
+ -
74
+ end
75
+ end
76
+
77
+ def process ( level, data )
78
+ @adapters.each { |a| a.call( level, data ) }
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,4 @@
1
+ module Yell
2
+ VERSION = "0.0.1"
3
+
4
+ end
data/lib/yell.rb ADDED
@@ -0,0 +1,21 @@
1
+ module Yell
2
+
3
+ autoload :Config, File.dirname(__FILE__) + '/yell/config'
4
+ autoload :Formatter, File.dirname(__FILE__) + '/yell/formatter'
5
+ autoload :Logger, File.dirname(__FILE__) + '/yell/logger'
6
+ autoload :Adapters, File.dirname(__FILE__) + '/yell/adapters'
7
+
8
+ # custom errors
9
+ class NoAdaptersDefined < StandardError; end
10
+ class NoSuchAdapter < StandardError; end
11
+
12
+
13
+ def self.new( *args, &block )
14
+ Yell::Logger.new( *args, &block )
15
+ end
16
+
17
+ def self.config
18
+ @@config ||= Yell::Config.new
19
+ end
20
+
21
+ end
data/yell.gemspec ADDED
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "yell/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "yell"
7
+ s.version = Yell::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rudolf Schmidt"]
10
+
11
+ s.homepage = "http://rubygems.org/gems/yell"
12
+ s.summary = %q{Logging library to log into files and databases}
13
+ s.description = %q{Logging library to log into files and databases}
14
+
15
+ s.rubyforge_project = "d_log"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yell
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rudolf Schmidt
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-23 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: Logging library to log into files and databases
15
+ email:
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - .gitignore
21
+ - Gemfile
22
+ - Rakefile
23
+ - init.rb
24
+ - lib/yell.rb
25
+ - lib/yell/adapters.rb
26
+ - lib/yell/adapters/base.rb
27
+ - lib/yell/adapters/datefile.rb
28
+ - lib/yell/adapters/file.rb
29
+ - lib/yell/config.rb
30
+ - lib/yell/formatter.rb
31
+ - lib/yell/logger.rb
32
+ - lib/yell/version.rb
33
+ - yell.gemspec
34
+ homepage: http://rubygems.org/gems/yell
35
+ licenses: []
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ requirements: []
53
+ rubyforge_project: d_log
54
+ rubygems_version: 1.8.10
55
+ signing_key:
56
+ specification_version: 3
57
+ summary: Logging library to log into files and databases
58
+ test_files: []