teelogger 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.
- checksums.yaml +7 -0
- data/.gitignore +24 -0
- data/Gemfile +4 -0
- data/LICENSE +30 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/features/logger.feature +42 -0
- data/features/step_definitions/steps.rb +55 -0
- data/features/support/env.rb +1 -0
- data/lib/teelogger.rb +199 -0
- data/lib/teelogger/version.rb +10 -0
- data/teelogger.gemspec +24 -0
- metadata +100 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 269cc8e131a866bd9a63206c5e20f33c02c3c3a9
|
4
|
+
data.tar.gz: 4aa61d289eebf2f4696ca5629be0a147c318f788
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5182be9dadb8218c3cefd5507ade52d58a431507ef8f179bc743dff1486fc7f71d62284610f09505315e63f1693a32d7152ed03ce3275558baf63ea47906b8ac
|
7
|
+
data.tar.gz: 9401f09297f125f6aecc8bfa07eeb657e22a269af817a6afa32fe2bee3e6dab7a801f0f3cfde02ab00b9dcacca0bd05ad43b9c50dec284f2ce5426fd0fbc4eed
|
data/.gitignore
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.*.sw*
|
4
|
+
.bundle
|
5
|
+
.config
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
*.bundle
|
20
|
+
*.so
|
21
|
+
*.o
|
22
|
+
*.a
|
23
|
+
mkmf.log
|
24
|
+
.ruby-version
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Copyright spriteCloud B.V. (http://www.spritecloud.com/) and other teelogger
|
2
|
+
contributors. All rights not covered below are reserved.
|
3
|
+
|
4
|
+
MIT +no-false-attribs License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
|
+
of this software and associated documentation files (the "Software"), to
|
8
|
+
deal in the Software without restriction, including without limitation the
|
9
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
11
|
+
furnished to do so, subject to the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be included in
|
14
|
+
all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
Distributions of all or part of the Software intended to be used by the
|
17
|
+
recipients as they would use the unmodified Software, containing modifications
|
18
|
+
that substantially alter, remove, or disable functionality of the Software,
|
19
|
+
outside of the documented configuration mechanisms provided by the Software,
|
20
|
+
shall be modified such that the Original Author's bug reporting email addresses
|
21
|
+
and urls are either replaced with the contact information of the parties
|
22
|
+
responsible for the changes, or removed entirely.
|
23
|
+
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
29
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
30
|
+
IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Teelogger
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'teelogger'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install teelogger
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/[my-github-username]/teelogger/fork )
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
@logger
|
2
|
+
Feature: Logger
|
3
|
+
As a user of the teelogger gem
|
4
|
+
When I use the TeeLogger class
|
5
|
+
I expect it to work as documented.
|
6
|
+
|
7
|
+
@logger_01
|
8
|
+
Scenario Outline: Default parameters
|
9
|
+
Given I create a TeeLogger with default parameters
|
10
|
+
And I set the log level to "<level>"
|
11
|
+
And I write a log message at log level "<level>"
|
12
|
+
Then I expect the log level "<level>" to have taken hold
|
13
|
+
And I expect the log message to appear on the screen
|
14
|
+
|
15
|
+
Examples:
|
16
|
+
| level |
|
17
|
+
| DEBUG |
|
18
|
+
| INFO |
|
19
|
+
| WARN |
|
20
|
+
| ERROR |
|
21
|
+
| FATAL |
|
22
|
+
|
23
|
+
@logger_02
|
24
|
+
Scenario Outline: I/O object
|
25
|
+
Given I create a TeeLogger with an IO object
|
26
|
+
And I set the log level to "<level>"
|
27
|
+
And I write a log message at log level "<level>"
|
28
|
+
Then I expect the log level "<level>" to have taken hold
|
29
|
+
And I expect the log message to appear in the IO object
|
30
|
+
|
31
|
+
Examples:
|
32
|
+
| level |
|
33
|
+
| DEBUG |
|
34
|
+
| INFO |
|
35
|
+
| WARN |
|
36
|
+
| ERROR |
|
37
|
+
| FATAL |
|
38
|
+
|
39
|
+
@logger_03
|
40
|
+
Scenario: multiple loggers
|
41
|
+
Given I create a TeeLogger with multiple loggers
|
42
|
+
Then I expect the class to let me access all loggers like a hash
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'test/unit/assertions'
|
2
|
+
|
3
|
+
message = "test message"
|
4
|
+
io = nil
|
5
|
+
logger = nil
|
6
|
+
|
7
|
+
Given(/^I create a TeeLogger with default parameters$/) do
|
8
|
+
logger = TeeLogger::TeeLogger.new
|
9
|
+
end
|
10
|
+
|
11
|
+
Given(/^I set the log level to "(.*?)"$/) do |level|
|
12
|
+
logger.level = level
|
13
|
+
end
|
14
|
+
|
15
|
+
Given(/^I write a log message at log level "(.*?)"$/) do |level|
|
16
|
+
meth = level.downcase.to_sym
|
17
|
+
res = logger.send(meth, message)
|
18
|
+
end
|
19
|
+
|
20
|
+
Then(/^I expect the log message to appear on the screen$/) do
|
21
|
+
puts "Can't test this; please check manually"
|
22
|
+
end
|
23
|
+
|
24
|
+
Then(/^I expect the log level "(.*?)" to have taken hold$/) do |level|
|
25
|
+
meth = "#{level.downcase}?".to_sym
|
26
|
+
res = logger.send(meth)
|
27
|
+
|
28
|
+
assert res, "Log level not active!"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
Given(/^I create a TeeLogger with an IO object$/) do
|
33
|
+
io = StringIO.new
|
34
|
+
logger = TeeLogger::TeeLogger.new io
|
35
|
+
end
|
36
|
+
|
37
|
+
Then(/^I expect the log message to appear in the IO object$/) do
|
38
|
+
assert io.string.include?(message), "Test message '#{message}' not included in output."
|
39
|
+
end
|
40
|
+
|
41
|
+
Given(/^I create a TeeLogger with multiple loggers$/) do
|
42
|
+
args = []
|
43
|
+
3.times do
|
44
|
+
args << StringIO.new
|
45
|
+
end
|
46
|
+
logger = TeeLogger::TeeLogger.new *args
|
47
|
+
end
|
48
|
+
|
49
|
+
Then(/^I expect the class to let me access all loggers like a hash$/) do
|
50
|
+
assert (3 == logger.length), "Expected 3 loggers, got #{logger.length}"
|
51
|
+
logger.each do |key, logger|
|
52
|
+
assert logger.is_a?(Logger), "Found a non-Logger object."
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
require "teelogger"
|
data/lib/teelogger.rb
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
#
|
2
|
+
# TeeLogger
|
3
|
+
# https://github.com/spriteCloud/teelogger
|
4
|
+
#
|
5
|
+
# Copyright (c) 2014 spriteCloud B.V. and other TeeLogger contributors.
|
6
|
+
# All rights reserved.
|
7
|
+
#
|
8
|
+
require "teelogger/version"
|
9
|
+
|
10
|
+
require "logger"
|
11
|
+
|
12
|
+
module TeeLogger
|
13
|
+
##
|
14
|
+
# Logger that writes to multiple outputs. Behaves just like Ruby's Logger,
|
15
|
+
# and like a hash of String => Logger.
|
16
|
+
#
|
17
|
+
# A typical use might be to log to STDOUT, but also to a file:
|
18
|
+
# log = TeeLogger.new(STDOUT, "filename.log")
|
19
|
+
# log.level = Logger::WARN # applies to all outputs
|
20
|
+
# log.level = "INFO" # convenience shortcut
|
21
|
+
#
|
22
|
+
# By using the instance as a hash, you can also set individual log levels
|
23
|
+
# for individual loggers:
|
24
|
+
# log = TeeLogger.new(STDOUT, "filename.log")
|
25
|
+
# log.each do |name, logger|
|
26
|
+
# if name.include?("filename.log")
|
27
|
+
# logger.level = "WARN"
|
28
|
+
# else
|
29
|
+
# logger.level = "DEBUG"
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
class TeeLogger
|
33
|
+
@default_level = Logger::Severity::INFO
|
34
|
+
@loggers
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
# Add a logger to the current loggers.
|
39
|
+
def add_logger(arg)
|
40
|
+
key = nil
|
41
|
+
logger = nil
|
42
|
+
if arg.is_a? String
|
43
|
+
# We have a filename
|
44
|
+
key = File.basename(arg)
|
45
|
+
|
46
|
+
# Try to create the logger.
|
47
|
+
file = File.new(arg, File::WRONLY | File::APPEND | File::CREAT)
|
48
|
+
logger = Logger.new(file)
|
49
|
+
|
50
|
+
# Initialize logger
|
51
|
+
logger.unknown "Logging to '#{arg}' initialized with level #{string_level(@default_level)}."
|
52
|
+
logger.level = convert_level(@default_level)
|
53
|
+
else
|
54
|
+
# We have some other object - let's hope it's an IO object
|
55
|
+
key = arg.to_s
|
56
|
+
|
57
|
+
# Try to create the logger.
|
58
|
+
logger = Logger.new(arg)
|
59
|
+
|
60
|
+
# Initialize logger
|
61
|
+
logger.unknown "Logging to #{key} initialized with level #{string_level(@default_level)}."
|
62
|
+
logger.level = convert_level(@default_level)
|
63
|
+
end
|
64
|
+
|
65
|
+
if not key.nil? and not logger.nil?
|
66
|
+
@loggers[key] = logger
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
##
|
72
|
+
# Start with any amount of IO objects or filenames; defaults to STDOUT
|
73
|
+
def initialize(*args)
|
74
|
+
# Handle default
|
75
|
+
if args.empty?
|
76
|
+
args = [STDOUT]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Initialization
|
80
|
+
@loggers = {}
|
81
|
+
|
82
|
+
# Create logs for all arguments
|
83
|
+
args.each do |arg|
|
84
|
+
add_logger(arg)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Convert a log level to its string name
|
90
|
+
def string_level(level)
|
91
|
+
if level.is_a? String
|
92
|
+
return level
|
93
|
+
end
|
94
|
+
|
95
|
+
Logger::Severity.constants.each do |const|
|
96
|
+
if level == Logger.const_get(const)
|
97
|
+
return const
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
return nil
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Convert a string log level to its constant value
|
106
|
+
def convert_level(val)
|
107
|
+
if val.is_a? String
|
108
|
+
begin
|
109
|
+
val = Logger.const_get(val)
|
110
|
+
rescue NameError
|
111
|
+
val = Logger::Severity::WARN
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
return val
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
##
|
120
|
+
# Set log level; override this to also accept strings
|
121
|
+
def level=(val)
|
122
|
+
# Convert strings to the constant value
|
123
|
+
val = convert_level(val)
|
124
|
+
|
125
|
+
# Update the default log level
|
126
|
+
@default_level = val
|
127
|
+
|
128
|
+
# Set all loggers' log levels
|
129
|
+
@loggers.each do |key, logger|
|
130
|
+
logger.level = val
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
##
|
136
|
+
# Log an exception
|
137
|
+
def exception(message, ex)
|
138
|
+
error("#{message} got #{ex.message}:\n#{ex.backtrace.join("\n")}")
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
##
|
143
|
+
# Every function this class doesn't have should be mapped to the original
|
144
|
+
# logger
|
145
|
+
def respond_to?(meth)
|
146
|
+
if @loggers.nil? or @loggers.empty?
|
147
|
+
raise "No loggers created, can't do anything."
|
148
|
+
end
|
149
|
+
|
150
|
+
meth_name = meth.to_s
|
151
|
+
|
152
|
+
# All loggers are the same, so we need to check only one of them.
|
153
|
+
@loggers.each do |key, logger|
|
154
|
+
if logger.respond_to? meth_name
|
155
|
+
return true
|
156
|
+
end
|
157
|
+
break
|
158
|
+
end
|
159
|
+
|
160
|
+
# If this didn't work, we're also emulating a hash
|
161
|
+
return @loggers.respond_to? meth_name
|
162
|
+
end
|
163
|
+
|
164
|
+
def method_missing(meth, *args, &block)
|
165
|
+
meth_name = meth.to_s
|
166
|
+
|
167
|
+
if @loggers.nil? or @loggers.empty?
|
168
|
+
raise "No loggers created, can't do anything."
|
169
|
+
end
|
170
|
+
|
171
|
+
# Compose message
|
172
|
+
message = ""
|
173
|
+
args.each do |arg|
|
174
|
+
message += arg.inspect
|
175
|
+
end
|
176
|
+
|
177
|
+
# Try to write the message to all loggers.
|
178
|
+
ret = []
|
179
|
+
@loggers.each do |key, logger|
|
180
|
+
if logger.respond_to? meth_name
|
181
|
+
if args.length > 0
|
182
|
+
ret << logger.send(meth_name, "[#{key}] #{message}", &block)
|
183
|
+
else
|
184
|
+
ret << logger.send(meth_name, *args, &block)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# Some double checking on the return value(s).
|
190
|
+
if not ret.empty?
|
191
|
+
return ret
|
192
|
+
end
|
193
|
+
|
194
|
+
# If the method wasn't from the loggers, we'll try to send it to the
|
195
|
+
# hash.
|
196
|
+
return @loggers.send(meth_name, *args, &block)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
data/teelogger.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'teelogger/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "teelogger"
|
8
|
+
spec.version = TeeLogger::VERSION
|
9
|
+
spec.authors = ["Jens Finkhaeuser"]
|
10
|
+
spec.email = ["foss@spritecloud.com"]
|
11
|
+
spec.summary = %q{Mini wrapper around Ruby Logger for logging to multiple destinations.}
|
12
|
+
spec.description = %q{Mini wrapper around Ruby Logger for logging to multiple destinations.}
|
13
|
+
spec.homepage = "https://github.com/spriteCloud/teelogger"
|
14
|
+
spec.license = "MITNFA"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "cucumber"
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: teelogger
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jens Finkhaeuser
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: cucumber
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: Mini wrapper around Ruby Logger for logging to multiple destinations.
|
56
|
+
email:
|
57
|
+
- foss@spritecloud.com
|
58
|
+
executables: []
|
59
|
+
extensions: []
|
60
|
+
extra_rdoc_files: []
|
61
|
+
files:
|
62
|
+
- ".gitignore"
|
63
|
+
- Gemfile
|
64
|
+
- LICENSE
|
65
|
+
- README.md
|
66
|
+
- Rakefile
|
67
|
+
- features/logger.feature
|
68
|
+
- features/step_definitions/steps.rb
|
69
|
+
- features/support/env.rb
|
70
|
+
- lib/teelogger.rb
|
71
|
+
- lib/teelogger/version.rb
|
72
|
+
- teelogger.gemspec
|
73
|
+
homepage: https://github.com/spriteCloud/teelogger
|
74
|
+
licenses:
|
75
|
+
- MITNFA
|
76
|
+
metadata: {}
|
77
|
+
post_install_message:
|
78
|
+
rdoc_options: []
|
79
|
+
require_paths:
|
80
|
+
- lib
|
81
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 2.0.3
|
94
|
+
signing_key:
|
95
|
+
specification_version: 4
|
96
|
+
summary: Mini wrapper around Ruby Logger for logging to multiple destinations.
|
97
|
+
test_files:
|
98
|
+
- features/logger.feature
|
99
|
+
- features/step_definitions/steps.rb
|
100
|
+
- features/support/env.rb
|