multilog 0.1.0a
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/lib/multilog.rb +191 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2d1171ef2208798e22e0a57c80de69d807ad8aec
|
4
|
+
data.tar.gz: e37fdfb4646fe2fa18d1387fa500f082f1254d00
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 9861531007285c0c8ca09b88a92e0957d3ed1c9f95b06bd1db4b148cb8d07906e4681e1f234d6ff626dda3900f73a3c72e1458a145a106e30e16be16d0afd9eb
|
7
|
+
data.tar.gz: 047a66e172175dfb8e2be1324269efe50f4325c395671a944780cbb2e709032c8d3a5718aae6eca7e64a49dd2706f53cddd8640ed4b637c12d513377c17cd254
|
data/lib/multilog.rb
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
# Logs to many devices, each of which may have an individual
|
4
|
+
# level and device.
|
5
|
+
#
|
6
|
+
# Acts in compliance with other configuration options from ruby's
|
7
|
+
# default Logger class.
|
8
|
+
#
|
9
|
+
# Author:: Stephen Wattam <http://stephenwattam.com>
|
10
|
+
# License:: Beerware
|
11
|
+
#
|
12
|
+
class MultiLog < Logger
|
13
|
+
|
14
|
+
# Version, for convenience.
|
15
|
+
VERSION = '0.1.0a'
|
16
|
+
|
17
|
+
# Default log level set to Logger::UNKNOWN
|
18
|
+
DEFAULT_LEVEL = Logger::UNKNOWN
|
19
|
+
|
20
|
+
# Create a simple log object with one log level and one device
|
21
|
+
#
|
22
|
+
# May be called in the same manner as ruby's Logger class,
|
23
|
+
# or with a list of logs specified in the same format as #configure_logs
|
24
|
+
#
|
25
|
+
def initialize(logdevs = {}, progname=nil, shift_age = 0, shift_size = 1048576)
|
26
|
+
super(nil, shift_age, shift_size)
|
27
|
+
@progname = progname
|
28
|
+
@shift_age = shift_age
|
29
|
+
@shift_size = shift_size
|
30
|
+
@lowest_level = DEFAULT_LEVEL
|
31
|
+
configure_logs(logdevs)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Set all logging devices as per the hash provided.
|
35
|
+
# Will remove all current logs in the process.
|
36
|
+
#
|
37
|
+
# name :: Default: :default :: The name of the log, used when identifying it or removing it later
|
38
|
+
# dev :: Default: STDOUT :: The device to be used. Should be an IO and will be closed on calling #close
|
39
|
+
# level :: Default: The value of MultiLog.DEFAULT_LEVEL :: A log level as per ruby's Logger class or a string representing it.
|
40
|
+
# shift_age :: Default: The value of @shift_age :: As per ruby's Logger
|
41
|
+
# shift_size :: Default: The value of @shift_size :: As per ruby's Logger
|
42
|
+
#
|
43
|
+
def configure_logs(logdevs = {})
|
44
|
+
# Remove all exsiting logs
|
45
|
+
@logdevs.each{ |name, ld| remove_log(name) } if @logdevs
|
46
|
+
|
47
|
+
# Parse logdevs hash options
|
48
|
+
@logdevs = {}
|
49
|
+
logdevs = [logdevs] if logdevs.is_a? Hash
|
50
|
+
|
51
|
+
# If the user provides a device then set up a single log as :log
|
52
|
+
unless logdevs.is_a? Array then
|
53
|
+
@logdevs[:default] = {:dev => logdevs, :level => DEFAULT_LEVEL}
|
54
|
+
@lowest_level = @logdevs[:default][:level]
|
55
|
+
return
|
56
|
+
end
|
57
|
+
|
58
|
+
# If the user provides a hash, check each arg
|
59
|
+
logdevs.each do |ld|
|
60
|
+
name = ld[:name] ||= :default
|
61
|
+
dev = ld[:dev] ||= $stdout
|
62
|
+
level = ld[:level] ||= DEFAULT_LEVEL
|
63
|
+
shift_age = ld[:shift_age] ||= @shift_age
|
64
|
+
shift_size = ld[:shift_size] ||= @shift_size
|
65
|
+
level = MultiLog.string_to_level(level) unless level.is_a? Fixnum
|
66
|
+
|
67
|
+
# Add to the name deely.
|
68
|
+
add_log(name, dev, level, shift_age, shift_size)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add a log to the list of existing logs, without removing others
|
73
|
+
#
|
74
|
+
# name :: The name of the log
|
75
|
+
# destination:: A device to log to
|
76
|
+
# level :: As per ruby's Logger class
|
77
|
+
# shift_age :: As per ruby's Logger class
|
78
|
+
# shift_size :: As per ruby's Logger class
|
79
|
+
#
|
80
|
+
def add_log(name, destination, level, shift_age = 0, shift_size = 1048576)
|
81
|
+
dev = LogDevice.new(destination, :shift_age => shift_age, :shift_size => shift_size)
|
82
|
+
|
83
|
+
@logdevs[name] = {:dev => dev, :level => level}
|
84
|
+
@lowest_level = level if (not @lowest_level) or level < @lowest_level
|
85
|
+
end
|
86
|
+
|
87
|
+
# Stop logging to one of the logs
|
88
|
+
def remove_log(name)
|
89
|
+
if(@logdevs[name])
|
90
|
+
# Back up old level
|
91
|
+
old_level = @logdevs[name][:level]
|
92
|
+
|
93
|
+
# Remove
|
94
|
+
@logdevs.delete(name)
|
95
|
+
|
96
|
+
# Update lowest level if we need to
|
97
|
+
@lowest_level = @logdevs.values.map{|x| x[:level] }.min if old_level == @lowest_level
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Print a summary of log output devices to the log, at such a level
|
102
|
+
# that all logs see it.
|
103
|
+
def summarise
|
104
|
+
add(@lowest_level, "Summary of logs:")
|
105
|
+
if(@logdevs.length > 0)
|
106
|
+
c = 0
|
107
|
+
@logdevs.each{|name, ld|
|
108
|
+
msg = " (#{c+=1}/#{@logdevs.length}) #{name} (level: #{MultiLog.level_to_string(ld[:level])}, device: fd=#{ld[:dev].dev.fileno}#{ld[:dev].dev.tty? ? " TTY" : ""}#{ld[:dev].filename ? " filename=#{ld[:dev].filename}" : ""})"
|
109
|
+
add(@lowest_level, msg)
|
110
|
+
}
|
111
|
+
else
|
112
|
+
add(@lowest_level, " *** No logs!") # Amusingly, this can never output
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Set the log level of one of the logs to a given Logger level.
|
117
|
+
def set_level(name, level=nil)
|
118
|
+
# Default
|
119
|
+
unless level then
|
120
|
+
level = name
|
121
|
+
name = nil
|
122
|
+
end
|
123
|
+
|
124
|
+
# Look up the level if the user provided a :symbol or "string"
|
125
|
+
level = MultiLog.string_to_level(level.to_s) unless level.is_a? Fixnum
|
126
|
+
|
127
|
+
if name
|
128
|
+
# Set a specific one
|
129
|
+
raise "No log by the name '#{name}'" unless @logdevs[name]
|
130
|
+
@logdevs[name][:level] = level
|
131
|
+
else
|
132
|
+
# Set them all by default
|
133
|
+
@logdevs.each{|name, logdev| logdev[:level] = level }
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns the log level of a log
|
138
|
+
def get_level(name = nil)
|
139
|
+
name = :default unless name
|
140
|
+
return nil unless @logdevs[name]
|
141
|
+
return @logdevs[name][:level]
|
142
|
+
end
|
143
|
+
|
144
|
+
# Overrides the basic internal add in Logger
|
145
|
+
def add(severity, message = nil, progname = nil, &block)
|
146
|
+
severity ||= UNKNOWN
|
147
|
+
|
148
|
+
# give up if no logdevs or if too low a severity
|
149
|
+
return true if severity < @lowest_level or (not @logdevs.values.map{ |ld| ld[:dev].nil? }.include?(false))
|
150
|
+
|
151
|
+
# Set progname to nil unless it is explicitly specified
|
152
|
+
progname ||= @progname
|
153
|
+
if message.nil?
|
154
|
+
if block_given?
|
155
|
+
message = yield
|
156
|
+
else
|
157
|
+
message = progname
|
158
|
+
progname = @progname
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Sync time across the logs and output only if above the log level for that device
|
163
|
+
msg = format_message(format_severity(severity), Time.now, progname, message)
|
164
|
+
@logdevs.each do |name, ld|
|
165
|
+
ld[:dev].write(msg) unless ld[:dev].nil? && ld[:level] <= severity
|
166
|
+
end
|
167
|
+
return true
|
168
|
+
end
|
169
|
+
|
170
|
+
# Convert a log level to a string.
|
171
|
+
#
|
172
|
+
# Used in the output summary
|
173
|
+
def self.level_to_string(lvl)
|
174
|
+
labels = %w(DEBUG INFO WARN ERROR FATAL)
|
175
|
+
return labels[lvl] || "UNKNOWN"
|
176
|
+
end
|
177
|
+
|
178
|
+
# Convert a string to a logger level number.
|
179
|
+
def self.string_to_level(str)
|
180
|
+
labels = %w(DEBUG INFO WARN ERROR FATAL)
|
181
|
+
return labels.index(str.to_s.upcase) || Logger::UNKNOWN
|
182
|
+
end
|
183
|
+
|
184
|
+
# Close the log and all associated devices.
|
185
|
+
def close
|
186
|
+
@logdevs.each do |name, ld|
|
187
|
+
ld[:dev].close
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: multilog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0a
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Wattam
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: A drop-in replacement for ruby's Logger supporting multiple outputs at
|
14
|
+
various levels
|
15
|
+
email: stephenwattam@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- lib/multilog.rb
|
21
|
+
homepage: http://stephenwattam.com/git/cgit.cgi/multilog/
|
22
|
+
licenses:
|
23
|
+
- Beerware
|
24
|
+
metadata: {}
|
25
|
+
post_install_message:
|
26
|
+
rdoc_options: []
|
27
|
+
require_paths:
|
28
|
+
- lib
|
29
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.0'
|
34
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - '>'
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: 1.3.1
|
39
|
+
requirements: []
|
40
|
+
rubyforge_project:
|
41
|
+
rubygems_version: 2.0.14
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: A multiple-output extension of ruby's Logger
|
45
|
+
test_files: []
|