tagged_logging 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,16 @@
1
+ *.rbc
2
+ .bundle
3
+ bundle
4
+ .config
5
+ .yardoc
6
+ InstalledFiles
7
+ _yardoc
8
+ coverage
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ spec/reports
14
+ test/tmp
15
+ test/version_tmp
16
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.9.2-p290@go-saas-commons
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ bundler_args: --local
6
+ env:
7
+ - "TESTOPTS=-v"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in go_saas_commons.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tagged_logging (0.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ multi_json (1.3.4)
10
+ rake (0.9.2.2)
11
+ simplecov (0.6.2)
12
+ multi_json (~> 1.3)
13
+ simplecov-html (~> 0.5.3)
14
+ simplecov-html (0.5.3)
15
+ test-unit (2.4.8)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ rake
22
+ simplecov
23
+ tagged_logging!
24
+ test-unit
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 ThoughtWorks, Inc.
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,98 @@
1
+ # TaggedLogging
2
+
3
+ The rails tagged logger is awesome, but it's only available in rails. This gem makes it available for non-rails applications
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'tagged_logging'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install tagged_logging
18
+
19
+ ## Usage
20
+
21
+ ```{ruby}
22
+ class MyApplication
23
+ include TaggedLogging
24
+ push_tags(MyApplication, Process.pid)
25
+
26
+ def initialize
27
+ info('Initializing application')
28
+ end
29
+
30
+ def perform
31
+ tagged("Perform") do
32
+ info("performing some task")
33
+ end
34
+ end
35
+
36
+ at_exit do
37
+ info('Exiting application')
38
+ end
39
+ end
40
+
41
+ app = MyApplication.new
42
+ app.perform
43
+ ```
44
+
45
+ The above will print the following:
46
+
47
+ [2012-12-15T14:52:10+05:30] - INFO - [MyApplication] [11321] - Initializing application
48
+ [2012-12-15T14:52:10+05:30] - INFO - [MyApplication] [11321] [Perform] - performing some task
49
+ [2012-12-15T14:52:10+05:30] - INFO - [MyApplication] [11321] - Exiting application
50
+
51
+ If you'd rather prefer to not pollute your class with the logger methods:
52
+ ```{ruby}
53
+ class MyApplication
54
+ class MyLogger
55
+ include TaggedLogging
56
+ end
57
+
58
+ class <<self
59
+ attr_accessor :logger
60
+ end
61
+
62
+ def logger
63
+ self.class.logger
64
+ end
65
+
66
+ self.logger = MyLogger
67
+ logger.push_tags(MyApplication, Process.pid)
68
+
69
+ def initialize
70
+ logger.info('Initializing application')
71
+ end
72
+
73
+ def perform
74
+ logger.tagged("Perform") do
75
+ logger.info("performing some task")
76
+ end
77
+ end
78
+
79
+ at_exit do
80
+ logger.info('Exiting application')
81
+ end
82
+ end
83
+
84
+ app = MyApplication.new
85
+ app.perform
86
+ ```
87
+
88
+ ## Contributing
89
+
90
+ 1. Fork it
91
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
92
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
93
+ 4. Push to the branch (`git push origin my-new-feature`)
94
+ 5. Create new Pull Request
95
+
96
+ # License
97
+
98
+ MIT License (see the LICENSE file)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rake/testtask'
4
+
5
+ desc "run tests"
6
+ Rake::TestTask.new do |t|
7
+ t.libs << "test"
8
+ t.test_files = FileList['test/**/*test.rb']
9
+ t.verbose = true
10
+ end
11
+
12
+ task :default => :test
@@ -0,0 +1,119 @@
1
+ #Copied from ActiveSupport
2
+ class Object
3
+ # An object is blank if it's false, empty, or a whitespace string.
4
+ # For example, "", " ", +nil+, [], and {} are all blank.
5
+ #
6
+ # This simplifies:
7
+ #
8
+ # if address.nil? || address.empty?
9
+ #
10
+ # ...to:
11
+ #
12
+ # if address.blank?
13
+ unless method_defined? :blank?
14
+ def blank?
15
+ respond_to?(:empty?) ? empty? : !self
16
+ end
17
+ end
18
+ end
19
+
20
+ class NilClass
21
+ # +nil+ is blank:
22
+ #
23
+ # nil.blank? # => true
24
+ #
25
+ unless method_defined? :blank?
26
+ def blank?
27
+ true
28
+ end
29
+ end
30
+ end
31
+
32
+ class FalseClass
33
+ # +false+ is blank:
34
+ #
35
+ # false.blank? # => true
36
+ #
37
+ unless method_defined? :blank?
38
+ def blank?
39
+ true
40
+ end
41
+ end
42
+ end
43
+
44
+ class TrueClass
45
+ # +true+ is not blank:
46
+ #
47
+ # true.blank? # => false
48
+ #
49
+ unless method_defined? :blank?
50
+ def blank?
51
+ false
52
+ end
53
+ end
54
+ end
55
+
56
+ class Array
57
+ # An array is blank if it's empty:
58
+ #
59
+ # [].blank? # => true
60
+ # [1,2,3].blank? # => false
61
+ #
62
+ unless method_defined? :blank?
63
+ alias_method :blank?, :empty?
64
+ end
65
+ end
66
+
67
+ class Hash
68
+ # A hash is blank if it's empty:
69
+ #
70
+ # {}.blank? # => true
71
+ # {:key => 'value'}.blank? # => false
72
+ #
73
+ unless method_defined? :blank?
74
+ alias_method :blank?, :empty?
75
+ end
76
+ end
77
+
78
+ class String
79
+ if defined?(Encoding) && "".respond_to?(:encode)
80
+ def encoding_aware?
81
+ true
82
+ end
83
+ else
84
+ def encoding_aware?
85
+ false
86
+ end
87
+ end
88
+ # 0x3000: fullwidth whitespace
89
+ NON_WHITESPACE_REGEXP = %r![^\s#{[0x3000].pack("U")}]!
90
+
91
+ # A string is blank if it's empty or contains whitespaces only:
92
+ #
93
+ # "".blank? # => true
94
+ # " ".blank? # => true
95
+ # " ".blank? # => true
96
+ # " something here ".blank? # => false
97
+ #
98
+ def blank?
99
+ # 1.8 does not takes [:space:] properly
100
+ if encoding_aware?
101
+ self !~ /[^[:space:]]/
102
+ else
103
+ self !~ NON_WHITESPACE_REGEXP
104
+ end
105
+ end
106
+ end
107
+
108
+ class Numeric #:nodoc:
109
+ # No number is blank:
110
+ #
111
+ # 1.blank? # => false
112
+ # 0.blank? # => false
113
+ #
114
+ unless method_defined? :blank?
115
+ def blank?
116
+ false
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,54 @@
1
+ require 'time'
2
+ module TaggedLogging
3
+ class Formatter < ::Logger::Formatter
4
+
5
+ FORMAT = "[%s] - %4s - %s - %s\n"
6
+
7
+ def call(severity, time, progname, msg)
8
+ str = case msg
9
+ when ::String
10
+ msg
11
+ when ::Exception
12
+ "#{ msg.message } (#{ msg.class })\n | " <<
13
+ (msg.backtrace || []).join("\n | ")
14
+ else
15
+ msg.inspect
16
+ end
17
+ FORMAT % [format_datetime(time), severity, tags_text, msg]
18
+ end
19
+
20
+ def push_tags(*tags)
21
+ tags.flatten.reject(&:blank?).tap do |new_tags|
22
+ current_tags.concat new_tags
23
+ end
24
+ end
25
+
26
+ def pop_tags(size = 1)
27
+ current_tags.pop size
28
+ end
29
+
30
+ def clear_tags!
31
+ current_tags.clear
32
+ end
33
+
34
+ def current_tags
35
+ Thread.current[:__tagged_logging_current_tags] ||= []
36
+ end
37
+
38
+ def tags_text
39
+ tags = current_tags
40
+ if tags.any?
41
+ tags.collect { |tag| "[#{tag}] " }.join.strip
42
+ end
43
+ end
44
+
45
+ private
46
+ def format_datetime(time)
47
+ if @datetime_format.nil?
48
+ time.iso8601
49
+ else
50
+ time.strftime(@datetime_format)
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,61 @@
1
+ require 'logger'
2
+
3
+ module TaggedLogging
4
+ def self.included(receiver)
5
+ receiver.class_eval do
6
+ extend ClassMethods
7
+ include InstanceMethods
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def tagged(*new_tags, &block)
13
+ new_tags = push_tags(*new_tags)
14
+ yield(self)
15
+ ensure
16
+ pop_tags(new_tags.size)
17
+ end
18
+
19
+ [:push_tags, :pop_tags, :clear_tags!].each do |method_name|
20
+ define_method(method_name) do |*args, &block|
21
+ logger.formatter.send(method_name, *args, &block)
22
+ end
23
+ end
24
+
25
+ def logger
26
+ @@logger ||= ::Logger.new(STDOUT).tap do |l|
27
+ l.level = ::Logger::INFO
28
+ l.formatter = ::TaggedLogging::Formatter.new
29
+ end
30
+ end
31
+
32
+ def logger=(logger)
33
+ @@logger = logger
34
+ end
35
+
36
+ def flush
37
+ clear_tags!
38
+ logger.flush if defined?(logger.super)
39
+ end
40
+
41
+ [:debug, :info, :warn, :error, :fatal].each do |method_name|
42
+ define_method(method_name) do |*args, &block|
43
+ self.logger.send(method_name, *args, &block)
44
+ end
45
+ end
46
+ end
47
+
48
+ module InstanceMethods
49
+ [:debug, :info, :warn, :error, :fatal].each do |method_name|
50
+ define_method(method_name) do |*args, &block|
51
+ self.class.logger.send(method_name, *args, &block)
52
+ end
53
+ end
54
+
55
+ [:tagged, :flush, :logger, :logger=, :push_tags, :pop_tags, :clear_tags!].each do |method_name|
56
+ define_method(method_name) do |*args, &block|
57
+ self.class.send(method_name, *args, &block)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,8 @@
1
+ module TaggedLogging
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 1
5
+ PATCH = 0
6
+ VERSION = [MAJOR, MINOR, PATCH].compact.join('.')
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ require "tagged_logging/version"
2
+ require "tagged_logging/logger"
3
+
4
+ module TaggedLogging
5
+ # Your code goes here...
6
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/tagged_logging/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Ketan Padegaonkar"]
6
+ gem.email = ["KetanPadegaonkar@gmail.com"]
7
+ gem.description = %q{Provides a rails style TaggedLogging for ruby apps}
8
+ gem.summary = %q{Provides a rails style TaggedLogging for ruby apps}
9
+ gem.homepage = "https://github.com/ketan/tagged-logger"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "tagged_logging"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = TaggedLogging::Version::VERSION
17
+
18
+ gem.add_development_dependency 'test-unit'
19
+ gem.add_development_dependency "simplecov"
20
+ gem.add_development_dependency 'rake'
21
+ end
@@ -0,0 +1,103 @@
1
+ require 'test_helper'
2
+ require 'tagged_logging/formatter'
3
+ require 'tagged_logging/blank_ext'
4
+
5
+ class LoggerTest < Test::Unit::TestCase
6
+
7
+ class MyLogger
8
+ include TaggedLogging
9
+ end
10
+
11
+ setup do
12
+ @output = StringIO.new
13
+ @logger = MyLogger
14
+ @logger.logger = ::Logger.new(@output)
15
+ @logger.logger.formatter = TaggedLogging::Formatter.new
16
+ @logger.flush
17
+ end
18
+
19
+ test "tagged once" do
20
+ @logger.tagged("BCX") { @logger.info "Funky time" }
21
+ assert_match "INFO - [BCX] - Funky time\n", @output.string
22
+ end
23
+
24
+ test "tagged twice" do
25
+ @logger.tagged("BCX") { @logger.tagged("Jason") { @logger.info "Funky time" } }
26
+ assert_match "INFO - [BCX] [Jason] - Funky time\n", @output.string
27
+ end
28
+
29
+ test "tagged thrice at once" do
30
+ @logger.tagged("BCX", "Jason", "New") { @logger.info "Funky time" }
31
+ assert_match "INFO - [BCX] [Jason] [New] - Funky time", @output.string
32
+ end
33
+
34
+ test "tagged are flattened" do
35
+ @logger.tagged("BCX", %w(Jason New)) { @logger.info "Funky time" }
36
+ assert_match "[BCX] [Jason] [New] - Funky time", @output.string
37
+ end
38
+
39
+ test "provides access to the logger instance" do
40
+ @logger.tagged("BCX") { |logger| logger.info "Funky time" }
41
+ assert_match "[BCX] - Funky time", @output.string
42
+ end
43
+
44
+ test "push and pop tags directly" do
45
+ assert_equal %w(A B C), @logger.push_tags('A', ['B', ' ', ['C']])
46
+ @logger.info 'a'
47
+ assert_equal %w(C), @logger.pop_tags
48
+ @logger.info 'b'
49
+ assert_equal %w(B), @logger.pop_tags(1)
50
+ @logger.info 'c'
51
+ assert_equal [], @logger.clear_tags!
52
+ @logger.info 'd'
53
+
54
+ assert_match "INFO - [A] [B] [C] - a", @output.string
55
+ assert_match "INFO - [A] [B] - b", @output.string
56
+ assert_match "INFO - [A] - c", @output.string
57
+ assert_match "INFO - - d", @output.string
58
+ end
59
+
60
+ test "does not strip message content" do
61
+ @logger.info " \t\t Hello"
62
+ assert_match "INFO - - \t\t Hello\n", @output.string
63
+ end
64
+
65
+ test "tagged once with blank and nil" do
66
+ @logger.tagged(nil, "", "New") { @logger.info "Funky time" }
67
+ assert_match "INFO - [New] - Funky time", @output.string
68
+ end
69
+
70
+ test "keeps each tag in their own thread" do
71
+ @logger.tagged("BCX") do
72
+ Thread.new do
73
+ @logger.tagged("OMG") { @logger.info "Cool story bro" }
74
+ end.join
75
+ @logger.info "Funky time"
76
+ end
77
+ assert_match "INFO - [OMG] - Cool story bro", @output.string
78
+ assert_match "INFO - [BCX] - Funky time\n", @output.string
79
+ end
80
+
81
+ test "cleans up the taggings on flush" do
82
+ @logger.tagged("BCX") do
83
+ Thread.new do
84
+ @logger.tagged("OMG") do
85
+ @logger.flush
86
+ @logger.info "Cool story bro"
87
+ end
88
+ end.join
89
+ end
90
+ assert_match "INFO - - Cool story bro", @output.string
91
+ end
92
+
93
+ test "mixed levels of tagging" do
94
+ @logger.tagged("BCX") do
95
+ @logger.tagged("Jason") { @logger.info "Funky time" }
96
+ @logger.info "Junky time!"
97
+ end
98
+
99
+ assert_match "INFO - [BCX] [Jason] - Funky time", @output.string
100
+ assert_match "INFO - [BCX] - Junky time!", @output.string
101
+ end
102
+
103
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'simplecov'
4
+ SimpleCov.start do
5
+ add_filter "/.bundle/"
6
+ add_filter "/bundle/"
7
+ end
8
+
9
+ Bundler.require
10
+ require 'test/unit'
Binary file
Binary file
Binary file
Binary file
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tagged_logging
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ketan Padegaonkar
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: test-unit
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: simplecov
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Provides a rails style TaggedLogging for ruby apps
63
+ email:
64
+ - KetanPadegaonkar@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - .rvmrc
71
+ - .travis.yml
72
+ - Gemfile
73
+ - Gemfile.lock
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - lib/tagged_logging.rb
78
+ - lib/tagged_logging/blank_ext.rb
79
+ - lib/tagged_logging/formatter.rb
80
+ - lib/tagged_logging/logger.rb
81
+ - lib/tagged_logging/version.rb
82
+ - tagged_logging.gemspec
83
+ - test/logger_test.rb
84
+ - test/test_helper.rb
85
+ - vendor/cache/multi_json-1.3.4.gem
86
+ - vendor/cache/rake-0.9.2.2.gem
87
+ - vendor/cache/simplecov-0.6.2.gem
88
+ - vendor/cache/simplecov-html-0.5.3.gem
89
+ - vendor/cache/test-unit-2.4.8.gem
90
+ homepage: https://github.com/ketan/tagged-logger
91
+ licenses: []
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
+ none: false
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 1.8.24
111
+ signing_key:
112
+ specification_version: 3
113
+ summary: Provides a rails style TaggedLogging for ruby apps
114
+ test_files:
115
+ - test/logger_test.rb
116
+ - test/test_helper.rb