logsly 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.log
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ .rvmrc
8
+ .rbenv-version
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'bundler', '~>1.1'
6
+ gem 'rake', '~>0.9.2'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 <TODO: copyright holders>
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.
data/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # Logsly
2
+
3
+ Logsly is a DSL and a mixin to setup and create custom logger objects. Define your color schemes and log outputs. Then mixin Logsly to make your logger classes. Create instances of your loggers specifying outputs for each, then use your loggers to log stuff to those outputs.
4
+
5
+ ## Usage
6
+
7
+ ```ruby
8
+
9
+ # define a named output for your logger to use
10
+ Logsly.stdout('my_stdout')
11
+
12
+ # define your logger
13
+ class MyLogger
14
+ include Logsly
15
+ end
16
+
17
+ # build a logger instance with a name and use it
18
+ logger = MyLogger.new(:outputs => ['my_stdout'])
19
+ logger.info "whatever"
20
+
21
+ # build another logger and use it
22
+ bg_logger = MyLogger.new('bg', :level => 'debug', :outputs => ['my_logger_stdout'])
23
+ bg_logger.debug "something"
24
+ ```
25
+
26
+ ## Implementation
27
+
28
+ Logsly creates and delegates to a [Logging logger](https://github.com/TwP/logging). When you create an instance of your logger class, Logsly sets up and configures Logging for you.
29
+
30
+ ## Settings
31
+
32
+ * `log_type`: custom string used to identify the type of the logger
33
+ * `level`: the level in use (default: `'debug'`)
34
+ * `outputs`: list of named outputs to log to (default: `[]`)
35
+
36
+ ## Outputs
37
+
38
+ ### Stdout
39
+
40
+ ```ruby
41
+ Logsly.stdout('my_stdout') do |logger|
42
+ pattern '[%d %-5l] : %m\n'
43
+ colors 'my_colors' # use the 'my_colors' color scheme
44
+ end
45
+ ```
46
+
47
+ Define a named stdout output to use with your loggers. Pass a block to customize it. The block will be lazy-eval'd when a logger using it is initialized. The block is passed the logger instance.
48
+
49
+ ### File
50
+
51
+ ```ruby
52
+ Logsly.file('my_file') do |logger|
53
+ path "development.log"
54
+
55
+ pattern '[%d %-5l] : %m\n'
56
+ # don't use a color scheme
57
+ end
58
+ ```
59
+
60
+ Define a named file output to use with your loggers. Takes the same parameters as its stdout counterpart. Specify the path (relative or absolute) to the log file using the `path` method.
61
+
62
+ ### Syslog
63
+
64
+ ```ruby
65
+ Logsly.syslog('my_syslog') do |logger|
66
+ identity "my_syslog_logger" # or whatever
67
+ facility Syslog::LOG_LOCAL0 # or whatever (default: `LOG_LOCAL0`)
68
+ log_opts Syslog::LOG_PID # or whatever (default: `(LOG_PID | LOG_CONS)`)
69
+
70
+ pattern '%m\n'
71
+ # don't use a color scheme
72
+ end
73
+ ```
74
+
75
+ Define a named syslog output to use with your loggers. Takes the same parameters as its stdout counterpart. Specify the identity and facility using the respective methods.
76
+
77
+ ### Patterns
78
+
79
+ Each output can define what pattern to format its messages with using the `pattern' method. See [Logging's patterns](https://github.com/TwP/logging/blob/master/lib/logging/layouts/pattern.rb) for details.
80
+
81
+ ### Colors
82
+
83
+ ```ruby
84
+ Logsly.colors('my_colors') do
85
+ debug :magenta
86
+ info :cyan
87
+ warn :yellow
88
+ error :red
89
+ fatal [:white, :on_red]
90
+
91
+ date :blue
92
+ message :white
93
+ end
94
+ ```
95
+
96
+ Define a named color scheme to use on your outputs. Essentially creates a [Logging::ColorScheme](https://github.com/TwP/logging/blob/master/lib/logging/color_scheme.rb) object. See that file for configuration and details.
97
+
98
+ ## Installation
99
+
100
+ Add this line to your application's Gemfile:
101
+
102
+ gem 'logsly'
103
+
104
+ And then execute:
105
+
106
+ $ bundle
107
+
108
+ Or install it yourself as:
109
+
110
+ $ gem install logsly
111
+
112
+ ## Contributing
113
+
114
+ 1. Fork it
115
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
116
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
117
+ 4. Push to the branch (`git push origin my-new-feature`)
118
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require 'assert/rake_tasks'
4
+ Assert::RakeTasks.install
5
+
6
+ require 'bundler/gem_tasks'
7
+
8
+ task :default => :build
@@ -0,0 +1,64 @@
1
+ require 'ostruct'
2
+ require 'ns-options'
3
+ require 'logging'
4
+
5
+ module Logsly
6
+
7
+ class NullOutput < OpenStruct
8
+ def to_appender(*args); nil; end
9
+ def to_layout(*args); nil; end
10
+ end
11
+
12
+ class BaseOutput
13
+
14
+ attr_reader :build
15
+
16
+ def initialize(&build)
17
+ @build = build || Proc.new {}
18
+ end
19
+
20
+ def to_appender(*args)
21
+ self.instance_exec(*args, &@build)
22
+ self.colors_obj.run_build(*args)
23
+ self
24
+ end
25
+
26
+ def to_layout(data)
27
+ Logging.layouts.pattern(data.to_pattern_opts)
28
+ end
29
+
30
+ def to_appender(*args)
31
+ raise NotImplementedError
32
+ end
33
+
34
+ end
35
+
36
+ class BaseOutputData
37
+ include NsOptions::Proxy
38
+ option :pattern, String, :default => '%m\n'
39
+ option :colors, String
40
+
41
+ def initialize(*args, &build)
42
+ @args = args
43
+ self.instance_exec(*@args, &build)
44
+ end
45
+
46
+ def to_pattern_opts
47
+ Hash.new.tap do |opts|
48
+ opts[:pattern] = self.pattern if self.pattern
49
+
50
+ if scheme_name = colors_obj.to_scheme(*@args)
51
+ opts[:color_scheme] = scheme_name
52
+ end
53
+ end
54
+ end
55
+
56
+ protected
57
+
58
+ def colors_obj
59
+ Logsly.colors(self.colors)
60
+ end
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,115 @@
1
+ require 'ostruct'
2
+ require 'ns-options'
3
+
4
+ # This class provides a DSL for setting color scheme values and lazy eval's
5
+ # the DSL to generate a Logging color scheme object.
6
+ # See https://github.com/TwP/logging/blob/master/lib/logging/color_scheme.rb
7
+ # for details on Logging color schemes.
8
+
9
+ module Logsly
10
+
11
+ class NullColors < OpenStruct
12
+ def to_scheme(*args); nil; end
13
+ end
14
+
15
+ class Colors
16
+
17
+ attr_reader :name, :build
18
+
19
+ def initialize(name, &build)
20
+ @name, @build = name, build
21
+ end
22
+
23
+ def to_scheme(*args)
24
+ "#{@name}-#{args.map{|a| a.object_id}.join('-')}".tap do |scheme_name|
25
+ Logging.color_scheme(scheme_name, ColorsData.new(*args, &@build).to_scheme_opts)
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ class ColorsData
32
+ include NsOptions::Proxy
33
+
34
+ # color for the level text only
35
+ option :debug
36
+ option :info
37
+ option :warn
38
+ option :error
39
+ option :fatal
40
+
41
+ # color for the entire log message based on the value of the log level
42
+ option :debug_line
43
+ option :info_line
44
+ option :warn_line
45
+ option :error_line
46
+ option :fatal_line
47
+
48
+ option :logger # [%c] name of the logger that generate the log event
49
+ option :date # [%d] datestamp
50
+ option :message # [%m] the user supplied log message
51
+ option :pid # [%p] PID of the current process
52
+ option :time # [%r] the time in milliseconds since the program started
53
+ option :thread # [%T] the name of the thread Thread.current[:name]
54
+ option :thread_id # [%t] object_id of the thread
55
+ option :file # [%F] filename where the logging request was issued
56
+ option :line # [%L] line number where the logging request was issued
57
+ option :method_name # [%M] method name where the logging request was issued
58
+
59
+ def initialize(*args, &build)
60
+ self.instance_exec(*args, &build)
61
+
62
+ @properties = properties.map{|p| self.send(p)}
63
+ @method = self.method_name
64
+ @level_settings = levels.map{|l| self.send(l)}
65
+ @line_settings = levels.map{|l| self.send("#{l}_line")}
66
+
67
+ if has_level_settings? && has_line_settings?
68
+ raise ArgumentError, "can't set line and level settings in the same scheme"
69
+ end
70
+ end
71
+
72
+ def to_scheme_opts
73
+ Hash.new.tap do |opts|
74
+ # set general properties
75
+ properties.each_with_index do |property, idx|
76
+ opts[property] = @properties[idx] if @properties[idx]
77
+ end
78
+
79
+ # set special properties (reserved names)
80
+ opts[:method] = @method if @method
81
+
82
+ # set level settings - only add :levels key if one exists
83
+ if has_level_settings?
84
+ opts[:levels] = {}
85
+ levels.each_with_index do |level, idx|
86
+ opts[:levels][level] = @level_settings[idx] if @level_settings[idx]
87
+ end
88
+ end
89
+
90
+ # set line-level settings - only :lines key if one exists
91
+ if has_line_settings?
92
+ opts[:lines] = {}
93
+ levels.each_with_index do |level, idx|
94
+ opts[:lines][level] = @line_settings[idx] if @line_settings[idx]
95
+ end
96
+ end
97
+ end
98
+ end
99
+
100
+ private
101
+
102
+ def has_level_settings?; !@level_settings.compact.empty?; end
103
+ def has_line_settings?; !@line_settings.compact.empty?; end
104
+
105
+ def properties
106
+ [:logger, :date, :message, :time, :pid, :thread, :thread_id, :file, :line]
107
+ end
108
+
109
+ def levels
110
+ [:debug, :info, :warn, :error, :fatal]
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,17 @@
1
+ require 'logging'
2
+ require 'logsly/base_output'
3
+
4
+ module Logsly
5
+
6
+ class FileOutput < BaseOutput
7
+ def to_appender(*args)
8
+ data = FileOutputData.new(*args, &self.build)
9
+ Logging.appenders.file(data.path, :layout => self.to_layout(data))
10
+ end
11
+ end
12
+
13
+ class FileOutputData < BaseOutputData
14
+ option :path, String
15
+ end
16
+
17
+ end
@@ -0,0 +1,45 @@
1
+ require 'ns-options'
2
+ require 'logging'
3
+ require 'logsly/colors'
4
+ require 'logsly/base_output'
5
+
6
+ module Logsly
7
+
8
+ module Settings
9
+ include NsOptions::Proxy
10
+
11
+ option :colors, ::Hash, :default => ::Hash.new(NullColors.new)
12
+ option :outputs, ::Hash, :default => ::Hash.new(NullOutput.new)
13
+ end
14
+
15
+ def self.reset
16
+ Settings.reset
17
+ Logging.reset
18
+ end
19
+
20
+ def self.colors(name, &block)
21
+ require 'logsly/colors'
22
+ Settings.colors[name.to_s] = Colors.new(name, &block) if !block.nil?
23
+ Settings.colors[name.to_s]
24
+ end
25
+
26
+ def self.stdout(name, &block)
27
+ require 'logsly/stdout_output'
28
+ Settings.outputs[name.to_s] = StdoutOutput.new(&block)
29
+ end
30
+
31
+ def self.file(name, &block)
32
+ require 'logsly/file_output'
33
+ Settings.outputs[name.to_s] = FileOutput.new(&block)
34
+ end
35
+
36
+ def self.syslog(name, &block)
37
+ require 'logsly/syslog_output'
38
+ Settings.outputs[name.to_s] = SyslogOutput.new(&block)
39
+ end
40
+
41
+ def self.outputs(name)
42
+ Settings.outputs[name.to_s]
43
+ end
44
+
45
+ end
@@ -0,0 +1,13 @@
1
+ require 'logging'
2
+ require 'logsly/base_output'
3
+
4
+ module Logsly
5
+
6
+ class StdoutOutput < BaseOutput
7
+ def to_appender(*args)
8
+ data = BaseOutputData.new(*args, &self.build)
9
+ Logging.appenders.stdout(:layout => self.to_layout(data))
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,26 @@
1
+ require 'syslog'
2
+ require 'logging'
3
+ require 'logsly/base_output'
4
+
5
+ module Logsly
6
+
7
+ class SyslogOutput < BaseOutput
8
+ def to_appender(*args)
9
+ Syslog.close if Syslog.opened?
10
+
11
+ data = SyslogOutputData.new(*args, &self.build)
12
+ Logging.appenders.syslog(data.identity, {
13
+ :logopt => data.log_opts,
14
+ :facility => data.facility,
15
+ :layout => self.to_layout(data)
16
+ })
17
+ end
18
+ end
19
+
20
+ class SyslogOutputData < BaseOutputData
21
+ option :identity, String
22
+ option :log_opts, Integer, :default => (Syslog::LOG_PID | Syslog::LOG_CONS)
23
+ option :facility, Integer, :default => Syslog::LOG_LOCAL0
24
+ end
25
+
26
+ end
@@ -0,0 +1,3 @@
1
+ module Logsly
2
+ VERSION = "1.0.0.rc1"
3
+ end
data/lib/logsly.rb ADDED
@@ -0,0 +1,69 @@
1
+ require 'ns-options'
2
+ require 'logging'
3
+ require 'logsly/settings'
4
+
5
+ module Logsly
6
+
7
+ def self.included(receiver)
8
+ receiver.class_eval do
9
+ attr_reader :log_type, :level, :outputs, :logger
10
+ include LoggerMethods
11
+ end
12
+ end
13
+
14
+ module LoggerMethods
15
+
16
+ def initialize(log_type, opts_hash=nil)
17
+ opts = NsOptions::Struct.new(opts_hash) do
18
+ option :level, String, :default => 'info'
19
+ option :outputs, Array, :default => []
20
+ end
21
+ @log_type, @level, @outputs = log_type.to_s, opts.level, opts.outputs
22
+
23
+ unique_name = "#{self.class.name}-#{@log_type}-#{self.object_id}"
24
+ @logger = Logging.logger[unique_name]
25
+ @logger.level = @level
26
+
27
+ @outputs.each do |output|
28
+ add_appender(Logsly.outputs(output).to_appender(self))
29
+ end
30
+ end
31
+
32
+ # delegate all calls to the @logger
33
+
34
+ def method_missing(method, *args, &block)
35
+ @logger.send(method, *args, &block)
36
+ end
37
+ def respond_to?(method)
38
+ super || @logger.respond_to?(method)
39
+ end
40
+
41
+ def ==(other_logger)
42
+ other_logger.log_type == @log_type &&
43
+ other_logger.level == @level &&
44
+ other_logger.outputs == @outputs
45
+ end
46
+
47
+ def inspect
48
+ reference = '0x0%x' % (self.object_id << 1)
49
+ "#<#{self.class}:#{reference} "\
50
+ "@log_type=#{@log_type.inspect} "\
51
+ "@level=#{@level.inspect} "\
52
+ "@outputs=#{@outputs.inspect}"
53
+ end
54
+
55
+ private
56
+
57
+ def add_appender(appender)
58
+ @logger.add_appenders(appender) if appender && !appender_added?(appender)
59
+ end
60
+
61
+ def appender_added?(appender)
62
+ @logger.appenders.detect do |existing|
63
+ existing.kind_of?(appender.class) && existing.name == appender.name
64
+ end
65
+ end
66
+
67
+ end
68
+
69
+ end
data/logsly.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/logsly/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "logsly"
6
+ gem.version = Logsly::VERSION
7
+ gem.description = %q{Create custom loggers.}
8
+ gem.summary = %q{Create custom loggers.}
9
+
10
+ gem.authors = ["Kelly Redding", "Collin Redding"]
11
+ gem.email = ["kelly@kellyredding.com", "collin.redding@me.com"]
12
+ gem.homepage = "http://github.com/redding/logsly"
13
+
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
16
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
17
+ gem.require_paths = ["lib"]
18
+
19
+ gem.add_development_dependency("assert", ["~> 1.0"])
20
+
21
+ gem.add_dependency("ns-options", ["~> 1.1"])
22
+ gem.add_dependency("logging", ["~> 1.8.0"])
23
+
24
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,5 @@
1
+ # this file is automatically required in when you require 'assert' in your tests
2
+ # put test helpers here
3
+
4
+ # add root dir to the load path
5
+ $LOAD_PATH.unshift(File.expand_path("../..", __FILE__))
data/test/irb.rb ADDED
@@ -0,0 +1,9 @@
1
+ require 'assert/setup'
2
+
3
+ # this file is required in when the 'irb' rake test is run.
4
+ # b/c 'assert/setup' is required above, the test helper will be
5
+ # required in as well.
6
+
7
+ # put any IRB setup code here
8
+
9
+ require 'logsly'
@@ -0,0 +1,9 @@
1
+ require 'logsly'
2
+
3
+ module Logsly
4
+
5
+ class TestLogger
6
+ include Logsly
7
+ end
8
+
9
+ end
@@ -0,0 +1,100 @@
1
+ require 'assert'
2
+ require 'logging'
3
+ require 'logsly/settings'
4
+ require 'logsly/base_output'
5
+
6
+ class Logsly::BaseOutput
7
+
8
+ class DataTests < Assert::Context
9
+ desc "the BaseOutputData handler"
10
+ setup do
11
+ Logsly.colors('a_color_scheme') do
12
+ debug :white
13
+ end
14
+ @arg = '%d : %m\n'
15
+ @lay = Logsly::BaseOutputData.new(@arg) do |*args|
16
+ pattern args.first
17
+ colors 'a_color_scheme'
18
+ end
19
+ end
20
+ subject { @lay }
21
+
22
+ should have_readers :pattern, :colors
23
+
24
+ should "know its defaults" do
25
+ lay = Logsly::BaseOutputData.new {}
26
+ assert_equal '%m\n', lay.pattern
27
+ assert_nil lay.colors
28
+ end
29
+
30
+ should "instance exec its build with args" do
31
+ assert_equal '%d : %m\n', subject.pattern
32
+ assert_equal 'a_color_scheme', subject.colors
33
+ end
34
+
35
+ should "know its layout pattern opts hash" do
36
+ expected = {
37
+ :pattern => subject.pattern,
38
+ :color_scheme => "#{subject.colors}-#{@arg.object_id}"
39
+ }
40
+ assert_equal expected, subject.to_pattern_opts
41
+
42
+ out = Logsly::BaseOutputData.new do
43
+ pattern '%m\n'
44
+ end
45
+ out_expected = {:pattern => out.pattern}
46
+ assert_equal out_expected, out.to_pattern_opts
47
+ end
48
+
49
+ end
50
+
51
+ class BaseTests < Assert::Context
52
+ desc "the BaseOutput handler"
53
+ setup do
54
+ @out = Logsly::BaseOutput.new {}
55
+ end
56
+ subject { @out }
57
+
58
+ should have_reader :build
59
+ should have_imeths :to_layout, :to_appender
60
+
61
+ should "know its build" do
62
+ build_proc = Proc.new {}
63
+ out = Logsly::BaseOutput.new &build_proc
64
+
65
+ assert_same build_proc, out.build
66
+ end
67
+
68
+ should "expect `to_appender` to be defined by subclasses" do
69
+ assert_raises NotImplementedError do
70
+ subject.to_appender
71
+ end
72
+ end
73
+
74
+ end
75
+
76
+ class BuildTests < BaseTests
77
+ desc "given a build"
78
+ setup do
79
+ Logsly.colors('a_color_scheme') do
80
+ debug :white
81
+ end
82
+ @out = Logsly::BaseOutput.new do |*args|
83
+ pattern args.to_s
84
+ colors 'a_color_scheme'
85
+ end
86
+ end
87
+
88
+ should "build a Logging pattern layout" do
89
+ data = Logsly::BaseOutputData.new('%d : %m\n', &@out.build)
90
+ lay = subject.to_layout(data)
91
+
92
+ assert_kind_of Logging::Layout, lay
93
+ assert_equal '%d : %m\n', lay.pattern
94
+ assert_kind_of Logging::ColorScheme, lay.color_scheme
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
@@ -0,0 +1,112 @@
1
+ require 'assert'
2
+ require 'logging'
3
+ require 'logsly/colors'
4
+
5
+ class Logsly::Colors
6
+
7
+ class DataTests < Assert::Context
8
+ desc "the ColorsData handler"
9
+ setup do
10
+ @data = Logsly::ColorsData.new('white') do |color|
11
+ debug color
12
+ end
13
+ end
14
+ subject { @data }
15
+
16
+ should have_imeths :to_scheme_opts
17
+ should have_imeths :debug, :info, :warn, :error, :fatal
18
+ should have_imeths :debug_line, :info_line, :warn_line, :error_line, :fatal_line
19
+ should have_imeths :logger, :date, :message, :pid, :time, :thread, :thread_id
20
+ should have_imeths :file, :line, :method_name
21
+
22
+ should "instance exec its build with args" do
23
+ assert_equal 'white', subject.debug
24
+ end
25
+
26
+ should "complain if setting both a level and a line setting" do
27
+ err = begin
28
+ Logsly::ColorsData.new do
29
+ info :blue
30
+ debug_line :white
31
+ end
32
+ nil
33
+ rescue ArgumentError => err
34
+ err
35
+ end
36
+
37
+ assert_kind_of ArgumentError, err
38
+ assert_includes "can't set line and level settings in the same scheme", err.message
39
+ end
40
+
41
+ should "know its scheme opts hash and only include specified opts" do
42
+ general_only = Logsly::ColorsData.new do
43
+ date :blue
44
+ message :cyan
45
+ method_name :white
46
+ info :blue
47
+ end
48
+ expected = {
49
+ :date => :blue,
50
+ :message => :cyan,
51
+ :method => :white,
52
+ :levels => {:info => :blue},
53
+ }
54
+
55
+ assert_equal expected, general_only.to_scheme_opts
56
+ end
57
+
58
+ should "only include :levels and :lines if at least one is set" do
59
+ no_levels_lines = Logsly::ColorsData.new { date :blue }
60
+ expected = { :date => :blue }
61
+
62
+ assert_equal expected, no_levels_lines.to_scheme_opts
63
+ end
64
+
65
+ end
66
+
67
+ class BaseTests < Assert::Context
68
+ desc "the Colors handler"
69
+ setup do
70
+ @colors = Logsly::Colors.new('test_colors') do |*args|
71
+ debug args.first
72
+ end
73
+ end
74
+ subject { @colors }
75
+
76
+ should have_readers :name, :build
77
+ should have_imeths :to_scheme
78
+
79
+ should "know its name" do
80
+ assert_equal 'test_colors', subject.name
81
+ end
82
+
83
+ should "know its build" do
84
+ build_proc = Proc.new {}
85
+ out = Logsly::Colors.new 'test', &build_proc
86
+
87
+ assert_same build_proc, out.build
88
+ end
89
+
90
+ end
91
+
92
+ class BuildTests < BaseTests
93
+ desc "given a build"
94
+ setup do
95
+ @colors = Logsly::Colors.new 'test' do |fatal_color|
96
+ fatal [fatal_color, :on_red]
97
+ date :blue
98
+ end
99
+ end
100
+
101
+ should "build a unique Logging color scheme based on called args" do
102
+ arg = 'white'
103
+ scheme_name = subject.to_scheme(arg)
104
+
105
+ assert_equal "test-#{arg.object_id}", scheme_name
106
+ assert_kind_of Logging::ColorScheme, Logging.color_scheme(scheme_name)
107
+ end
108
+
109
+ end
110
+
111
+ end
112
+
@@ -0,0 +1,56 @@
1
+ require 'assert'
2
+ require 'ostruct'
3
+ require 'logging'
4
+ require 'logsly/settings'
5
+ require 'logsly/file_output'
6
+
7
+ class Logsly::FileOutput
8
+
9
+ class DataTests < Assert::Context
10
+ desc "the FileOutputData handler"
11
+ setup do
12
+ @data = Logsly::FileOutputData.new {}
13
+ end
14
+ subject { @data }
15
+
16
+ should have_imeth :path
17
+
18
+ end
19
+
20
+ class BaseTests < Assert::Context
21
+ desc "the StdoutOutput handler"
22
+ setup do
23
+ @logger = OpenStruct.new
24
+ @logger.debug_level = :white
25
+ @logger.pattern = '%d : %m\n'
26
+ @logger.file = "dev.log"
27
+
28
+ Logsly.colors('a_color_scheme') do |logger|
29
+ debug logger.debug_level
30
+ end
31
+
32
+ @out = Logsly::FileOutput.new do |logger|
33
+ path logger.file
34
+
35
+ pattern logger.pattern
36
+ colors 'a_color_scheme'
37
+ end
38
+ end
39
+ subject { @out }
40
+
41
+ should "be an output handler" do
42
+ assert_kind_of Logsly::BaseOutput, subject
43
+ end
44
+
45
+ should "build a Logging file appender, passing args to the builds" do
46
+ appender = subject.to_appender @logger
47
+
48
+ assert_kind_of Logging::Appenders::File, appender
49
+ assert_equal 'dev.log', appender.name
50
+ assert_kind_of Logging::Layouts::Pattern, appender.layout
51
+ assert_equal '%d : %m\n', appender.layout.pattern
52
+ assert_kind_of Logging::ColorScheme, appender.layout.color_scheme
53
+ end
54
+ end
55
+
56
+ end
@@ -0,0 +1,123 @@
1
+ require 'assert'
2
+ require 'logging'
3
+ require 'logsly'
4
+ require 'test/support/logger'
5
+
6
+ module Logsly
7
+
8
+ class BaseTests < Assert::Context
9
+ desc "a logger with Logsly mixed in"
10
+ setup do
11
+ Logsly.reset
12
+ @logger = TestLogger.new(:testy_log_logger)
13
+ end
14
+ subject { @logger }
15
+
16
+ should have_readers :log_type, :level, :outputs, :logger
17
+
18
+ should "know its log_type" do
19
+ assert_equal 'testy_log_logger', subject.log_type
20
+ end
21
+
22
+ should "know its default opt values" do
23
+ assert_equal 'info', subject.level
24
+ assert_equal [], subject.outputs
25
+ end
26
+
27
+ should "allow overridding the default opt values" do
28
+ log = TestLogger.new(:testy_debug_logger, :level => :debug, :outputs => [:stdout])
29
+ assert_equal 'debug', log.level
30
+ assert_equal [:stdout], log.outputs
31
+ end
32
+
33
+ end
34
+
35
+ class LoggerTests < BaseTests
36
+
37
+ should "create a Logging::Logger" do
38
+ assert_not_nil subject.logger
39
+ assert_kind_of Logging::Logger, subject.logger
40
+ end
41
+
42
+ should "create the Logging::Logger with a unique name" do
43
+ expected = "#{subject.class.name}-testy_log_logger-#{subject.object_id}"
44
+ assert_equal expected, subject.logger.name
45
+ end
46
+
47
+ should "set the logger's level" do
48
+ assert_equal Logging::LEVELS['info'], subject.logger.level
49
+
50
+ log = TestLogger.new('test', :level => :debug)
51
+ assert_equal Logging::LEVELS['debug'], log.logger.level
52
+ end
53
+
54
+ end
55
+
56
+ class AppenderTests < LoggerTests
57
+ setup do
58
+ Logsly.stdout 'my_stdout'
59
+ Logsly.file('my_file') do |logger|
60
+ path "development-#{logger.log_type}.log"
61
+ end
62
+ Logsly.file('my_other_file') do |logger|
63
+ path "other-#{logger.log_type}.log"
64
+ end
65
+ Logsly.syslog('my_syslog') do |logger|
66
+ identity "my_syslog_logger-#{logger.log_type}"
67
+ end
68
+ end
69
+
70
+ should "add a named stdout appender" do
71
+ log = TestLogger.new(:test, :outputs => 'my_stdout')
72
+ assert_includes_appender Logging::Appenders::Stdout, log
73
+ end
74
+
75
+ should "add a named file appender" do
76
+ log = TestLogger.new(:test, :outputs => 'my_file')
77
+ filelog = extract_appender_from_logger(log, :file)
78
+
79
+ assert_includes_appender Logging::Appenders::File, log
80
+ assert_equal 'development-test.log', filelog.name
81
+ end
82
+
83
+ should "add a named syslog appender" do
84
+ log = TestLogger.new(:test, :outputs => 'my_syslog')
85
+ assert_includes_appender Logging::Appenders::Syslog, log
86
+ end
87
+
88
+ should "not add duplicate appenders" do
89
+ outputs = ['my_stdout', 'my_stdout', 'my_file', 'my_other_file']
90
+ log = TestLogger.new(:test, :outputs => outputs)
91
+
92
+ assert_equal 3, log.appenders.size
93
+ end
94
+
95
+ should "not add undefined appenders" do
96
+ outputs = ['my_stdout', 'undefined']
97
+ log = TestLogger.new(:test, :outputs => outputs)
98
+
99
+ assert_equal 1, log.appenders.size
100
+ end
101
+
102
+ protected
103
+
104
+ def assert_includes_appender(appender_class, logger)
105
+ assert_includes appender_class, logger.appenders.collect(&:class)
106
+ end
107
+
108
+ def extract_appender_from_logger(logger, type)
109
+ klass = case type
110
+ when :syslog
111
+ Logging::Appenders::Syslog
112
+ when :file
113
+ Logging::Appenders::File
114
+ when :stdout
115
+ Logging::Appenders::Stdout
116
+ end
117
+
118
+ logger.appenders.select{|a| a.is_a?(klass)}.first
119
+ end
120
+
121
+ end
122
+
123
+ end
@@ -0,0 +1,98 @@
1
+ require 'assert'
2
+ require 'logsly/settings'
3
+
4
+ module Logsly
5
+
6
+ class SettingsTests < Assert::Context
7
+ desc "Logsly settings"
8
+ setup do
9
+ Logsly::Settings.reset
10
+ end
11
+ subject { Logsly }
12
+
13
+ should have_imeths :reset, :colors, :stdout, :file, :syslog, :outputs
14
+
15
+ should "return a NullColors obj when requesting a color scheme that isn't defined" do
16
+ assert_kind_of NullColors, Logsly.colors('not_defined_yet')
17
+ end
18
+
19
+ should "return a NullOutput obj when requesting an output that isn't defined" do
20
+ assert_kind_of NullOutput, Logsly.outputs('not_defined_yet')
21
+ end
22
+
23
+ should "add a named color scheme using the `colors` method" do
24
+ assert_kind_of NullColors, Logsly.colors('test_colors')
25
+ Logsly.colors('test_colors') {}
26
+
27
+ assert_kind_of Colors, Logsly.colors('test_colors')
28
+ end
29
+
30
+ should "add a named stdout output using the `stdout` method" do
31
+ assert_kind_of NullOutput, Logsly.outputs('test_stdout')
32
+ Logsly.stdout('test_stdout') {}
33
+
34
+ assert_not_nil Logsly.outputs('test_stdout')
35
+ assert_kind_of StdoutOutput, Logsly.outputs('test_stdout')
36
+ end
37
+
38
+ should "add a named file output using the `file` method" do
39
+ assert_kind_of NullOutput, Logsly.outputs('test_file')
40
+ Logsly.file('test_file') {}
41
+
42
+ assert_not_nil Logsly.outputs('test_file')
43
+ assert_kind_of FileOutput, Logsly.outputs('test_file')
44
+ end
45
+
46
+ should "add a named syslog output using the `syslog` method" do
47
+ assert_kind_of NullOutput, Logsly.outputs('test_syslog')
48
+ Logsly.syslog('test_syslog') {}
49
+
50
+ assert_not_nil Logsly.outputs('test_syslog')
51
+ assert_kind_of SyslogOutput, Logsly.outputs('test_syslog')
52
+ end
53
+
54
+ should "convert non-string setting names to string" do
55
+ Logsly.colors(:test_colors) {}
56
+
57
+ assert_not_nil Logsly.colors(:test_colors)
58
+ assert_kind_of Colors, Logsly.colors(:test_colors)
59
+ end
60
+
61
+ should "overwrite same-named colors settings" do
62
+ Logsly.colors('something') {}
63
+ orig = Logsly.colors('something')
64
+ Logsly.colors('something') {}
65
+
66
+ assert_not_same orig, Logsly.colors('something')
67
+ end
68
+
69
+ should "overwrite same-named outputs settings" do
70
+ Logsly.stdout('something') {}
71
+ assert_kind_of StdoutOutput, Logsly.outputs('something')
72
+
73
+ Logsly.file('something') {}
74
+ assert_kind_of FileOutput, Logsly.outputs('something')
75
+ end
76
+
77
+ end
78
+
79
+ class ResetTests < SettingsTests
80
+ desc "`reset` method"
81
+ setup do
82
+ Logsly.colors('test_colors') {}
83
+ Logsly.stdout('test_stdout') {}
84
+ end
85
+
86
+ should "reset the Settings" do
87
+ assert_kind_of Colors, Logsly.colors('test_colors')
88
+ assert_kind_of StdoutOutput, Logsly.outputs('test_stdout')
89
+
90
+ Logsly.reset
91
+
92
+ assert_kind_of NullColors, Logsly.colors('test_colors')
93
+ assert_kind_of NullOutput, Logsly.outputs('test_stdout')
94
+ end
95
+
96
+ end
97
+
98
+ end
@@ -0,0 +1,41 @@
1
+ require 'assert'
2
+ require 'ostruct'
3
+ require 'logging'
4
+ require 'logsly/settings'
5
+ require 'logsly/stdout_output'
6
+
7
+ class Logsly::StdoutOutput
8
+
9
+ class BaseTests < Assert::Context
10
+ desc "the StdoutOutput handler"
11
+ setup do
12
+ @logger = OpenStruct.new
13
+ @logger.debug_level = :white
14
+ @logger.pattern = '%d : %m\n'
15
+
16
+ Logsly.colors('a_color_scheme') do |logger|
17
+ debug logger.debug_level
18
+ end
19
+
20
+ @out = Logsly::StdoutOutput.new do |logger|
21
+ pattern logger.pattern
22
+ colors 'a_color_scheme'
23
+ end
24
+ end
25
+ subject { @out }
26
+
27
+ should "be an output handler" do
28
+ assert_kind_of Logsly::BaseOutput, subject
29
+ end
30
+
31
+ should "build a Logging stdout appender, passing args to the builds" do
32
+ appender = subject.to_appender @logger
33
+
34
+ assert_kind_of Logging::Appenders::Stdout, appender
35
+ assert_kind_of Logging::Layouts::Pattern, appender.layout
36
+ assert_equal '%d : %m\n', appender.layout.pattern
37
+ assert_kind_of Logging::ColorScheme, appender.layout.color_scheme
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,66 @@
1
+ require 'assert'
2
+ require 'ostruct'
3
+ require 'syslog'
4
+ require 'logging'
5
+ require 'logsly/settings'
6
+ require 'logsly/syslog_output'
7
+
8
+ class Logsly::SyslogOutput
9
+
10
+ class DataTests < Assert::Context
11
+ desc "the FileOutputData handler"
12
+ setup do
13
+ @data = Logsly::SyslogOutputData.new {}
14
+ end
15
+ subject { @data }
16
+
17
+ should have_imeth :identity, :log_opts, :facility
18
+
19
+ should "default :log_opts" do
20
+ assert_equal (Syslog::LOG_PID | Syslog::LOG_CONS), subject.log_opts
21
+ end
22
+
23
+ should "default :facility" do
24
+ assert_equal Syslog::LOG_LOCAL0, subject.facility
25
+ end
26
+
27
+ end
28
+
29
+ class BaseTests < Assert::Context
30
+ desc "the SyslogOutput handler"
31
+ setup do
32
+ @logger = OpenStruct.new
33
+ @logger.debug_level = :white
34
+ @logger.pattern = '%d : %m\n'
35
+ @logger.identity = "whatever"
36
+ @logger.facility = Syslog::LOG_LOCAL3
37
+
38
+ Logsly.colors('a_color_scheme') do |logger|
39
+ debug logger.debug_level
40
+ end
41
+
42
+ @out = Logsly::SyslogOutput.new do |logger|
43
+ identity logger.identity
44
+ facility logger.facility
45
+
46
+ pattern logger.pattern
47
+ colors 'a_color_scheme'
48
+ end
49
+ end
50
+ subject { @out }
51
+
52
+ should "be an output handler" do
53
+ assert_kind_of Logsly::BaseOutput, subject
54
+ end
55
+
56
+ should "build a Logging syslog appender, passing args to the builds" do
57
+ appender = subject.to_appender @logger
58
+
59
+ assert_kind_of Logging::Appenders::Syslog, appender
60
+ assert_kind_of Logging::Layouts::Pattern, appender.layout
61
+ assert_equal '%d : %m\n', appender.layout.pattern
62
+ assert_kind_of Logging::ColorScheme, appender.layout.color_scheme
63
+ end
64
+ end
65
+
66
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: logsly
3
+ version: !ruby/object:Gem::Version
4
+ hash: 2488903281
5
+ prerelease: 6
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ - rc
11
+ - 1
12
+ version: 1.0.0.rc1
13
+ platform: ruby
14
+ authors:
15
+ - Kelly Redding
16
+ - Collin Redding
17
+ autorequire:
18
+ bindir: bin
19
+ cert_chain: []
20
+
21
+ date: 2012-12-10 00:00:00 Z
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ name: assert
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 15
31
+ segments:
32
+ - 1
33
+ - 0
34
+ version: "1.0"
35
+ type: :development
36
+ requirement: *id001
37
+ prerelease: false
38
+ - !ruby/object:Gem::Dependency
39
+ name: ns-options
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 13
46
+ segments:
47
+ - 1
48
+ - 1
49
+ version: "1.1"
50
+ type: :runtime
51
+ requirement: *id002
52
+ prerelease: false
53
+ - !ruby/object:Gem::Dependency
54
+ name: logging
55
+ version_requirements: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 55
61
+ segments:
62
+ - 1
63
+ - 8
64
+ - 0
65
+ version: 1.8.0
66
+ type: :runtime
67
+ requirement: *id003
68
+ prerelease: false
69
+ description: Create custom loggers.
70
+ email:
71
+ - kelly@kellyredding.com
72
+ - collin.redding@me.com
73
+ executables: []
74
+
75
+ extensions: []
76
+
77
+ extra_rdoc_files: []
78
+
79
+ files:
80
+ - .gitignore
81
+ - Gemfile
82
+ - LICENSE
83
+ - README.md
84
+ - Rakefile
85
+ - lib/logsly.rb
86
+ - lib/logsly/base_output.rb
87
+ - lib/logsly/colors.rb
88
+ - lib/logsly/file_output.rb
89
+ - lib/logsly/settings.rb
90
+ - lib/logsly/stdout_output.rb
91
+ - lib/logsly/syslog_output.rb
92
+ - lib/logsly/version.rb
93
+ - logsly.gemspec
94
+ - test/helper.rb
95
+ - test/irb.rb
96
+ - test/support/logger.rb
97
+ - test/unit/base_output_tests.rb
98
+ - test/unit/colors_tests.rb
99
+ - test/unit/file_output_tests.rb
100
+ - test/unit/logger_tests.rb
101
+ - test/unit/settings_tests.rb
102
+ - test/unit/stdout_output_tests.rb
103
+ - test/unit/syslog_output_tests.rb
104
+ homepage: http://github.com/redding/logsly
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options: []
109
+
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: 3
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">"
125
+ - !ruby/object:Gem::Version
126
+ hash: 25
127
+ segments:
128
+ - 1
129
+ - 3
130
+ - 1
131
+ version: 1.3.1
132
+ requirements: []
133
+
134
+ rubyforge_project:
135
+ rubygems_version: 1.8.24
136
+ signing_key:
137
+ specification_version: 3
138
+ summary: Create custom loggers.
139
+ test_files:
140
+ - test/helper.rb
141
+ - test/irb.rb
142
+ - test/support/logger.rb
143
+ - test/unit/base_output_tests.rb
144
+ - test/unit/colors_tests.rb
145
+ - test/unit/file_output_tests.rb
146
+ - test/unit/logger_tests.rb
147
+ - test/unit/settings_tests.rb
148
+ - test/unit/stdout_output_tests.rb
149
+ - test/unit/syslog_output_tests.rb