output 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,31 @@
1
+ module Output
2
+ class Writer
3
+ module BuildLogger
4
+ extend self
5
+
6
+ def self.included(base)
7
+ base.extend ClassMethods
8
+ end
9
+
10
+ module ClassMethods
11
+ extend self
12
+
13
+ def build_logger(name, level, device_options)
14
+ logger = Logging.logger[name]
15
+ logger.level = level
16
+ logger.appenders = Output::Devices.build_device(device_options[:device], device_options)
17
+ logger.extend LevelName
18
+ logger
19
+ end
20
+ end
21
+
22
+ module LevelName
23
+ def level_name
24
+ level_names = Logging::LNAMES
25
+ level_name = Logging::levelify level_names[level]
26
+ level_name.to_sym
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,100 @@
1
+ module Output
2
+ module Devices
3
+ def self.build_device(type, options = {})
4
+ builders = {
5
+ :stdout => Builder::Stdout,
6
+ :string_io => Builder::StringIo,
7
+ :file => Builder::File,
8
+ }
9
+
10
+ default_options = { :name => type, :pattern => DEFAULT_PATTERN }
11
+ options = default_options.merge(options)
12
+ name = options[:name]
13
+
14
+ builder = builders[type]
15
+ builder.build(name, options)
16
+ end
17
+
18
+ module Builder
19
+ def layout(pattern = Output::Devices::DEFAULT_PATTERN)
20
+ Logging.layouts.pattern(:pattern => pattern)
21
+ end
22
+
23
+
24
+ def build(name, options)
25
+ pattern = options[:pattern]
26
+ layout = self.layout(pattern)
27
+ options = { :layout => layout }.merge(options)
28
+
29
+ Logging.appenders.send self.class.device_id, name, options
30
+ end
31
+
32
+ def self.included(base)
33
+ base.extend ClassMethods
34
+ end
35
+
36
+ module ClassMethods
37
+ def all_required_options
38
+ @all_required_options ||= []
39
+ end
40
+
41
+ def required_options=(*options)
42
+ @all_required_options = options
43
+ end
44
+ alias :required_options :required_options=
45
+
46
+ def device_id=(device_id)
47
+ @device_id = device_id
48
+ end
49
+ alias :device :device_id=
50
+
51
+ def device_id
52
+ @device_id ||= Output::DEFAULT_DEVICE
53
+ end
54
+
55
+ def build(name, options)
56
+ options.extend Output::Devices::OptionValidation
57
+ options.validate!(device_id, all_required_options)
58
+
59
+ instance = new
60
+ instance.build(name, options)
61
+ end
62
+ end
63
+
64
+ class StringIo
65
+ include Builder
66
+
67
+ device :string_io
68
+ required_options :pattern
69
+ end
70
+
71
+ class File
72
+ include Builder
73
+
74
+ device :rolling_file
75
+ required_options :filename, :pattern
76
+ end
77
+
78
+ class Stdout
79
+ include Builder
80
+
81
+ device :stdout
82
+ required_options :pattern
83
+ end
84
+ end
85
+
86
+ module OptionValidation
87
+ def validate!(device_id, required = [])
88
+ missing_option = false
89
+ message = "An #{device_id} device requires :\n"
90
+ required.each do |key|
91
+ unless self.has_key?(key)
92
+ missing_option = true
93
+ message = "#{message}\t :#{key}\n"
94
+ end
95
+ end
96
+ raise message if missing_option
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,239 @@
1
+ require 'ostruct'
2
+
3
+ module Output
4
+ DEFAULT_LOGGER_LEVEL = :info
5
+ DEFAULT_PATTERN = '%m\n'
6
+ DEFAULT_DEVICE = :stdout
7
+
8
+ def self.included(base)
9
+ base.extend ClassMethods
10
+ end
11
+
12
+ def disable
13
+ each_writer { |w| w.disable }
14
+ if block_given?
15
+ yield
16
+ enable
17
+ end
18
+ end
19
+
20
+ def enable
21
+ each_writer { |w| w.enable }
22
+ end
23
+
24
+ def write(method, message)
25
+ send method, message
26
+ end
27
+
28
+ def writer(name)
29
+ send self.class.writer_attribute(name)
30
+ end
31
+
32
+ def last_method
33
+ @last_method
34
+ end
35
+
36
+ def last_method=(val)
37
+ @last_method = val
38
+ end
39
+
40
+ def last_method?(*methods)
41
+ methods.include? last_method
42
+ end
43
+
44
+ def build_writer(name, level, device_options = nil, message_transformer=nil)
45
+ device_options ||= {}
46
+ device_options = self.class.device_options.merge device_options
47
+ logger_name = Writer::Naming.fully_qualified(self.class, name)
48
+ writer = Writer.build name, level, message_transformer, self.level, logger_name, device_options
49
+ writer
50
+ end
51
+
52
+ def each_writer
53
+ self.class.writer_names.each do |name|
54
+ writer = send self.class.writer_attribute(name)
55
+ yield writer
56
+ end
57
+ end
58
+
59
+ def level
60
+ @level ||= self.class.logger_level
61
+ end
62
+
63
+ def level=(level)
64
+ @level = level
65
+ each_writer { |w| w.logger_level = level }
66
+ level
67
+ end
68
+
69
+ def initial_level?
70
+ level == self.class.logger_level
71
+ end
72
+
73
+ def levels
74
+ @levels ||= []
75
+ end
76
+
77
+ def reset_level
78
+ @level = self.class.logger_level
79
+
80
+ each_writer do |writer|
81
+ writer.reset_level
82
+ end
83
+ end
84
+
85
+ def push_level(level)
86
+ levels.unshift self.level
87
+ self.level = level
88
+
89
+ if block_given?
90
+ yield
91
+ self.level = pop_level
92
+ end
93
+
94
+ level
95
+ end
96
+
97
+ def pop_level
98
+ level = levels.shift unless levels.empty?
99
+ self.level = level
100
+ level
101
+ end
102
+
103
+ def suspend_devices(device, &block)
104
+ return suspend_devices__obj(device, &block) if device.is_a? Logging::Appender
105
+ suspend_devices__name device, &block
106
+ end
107
+
108
+ def suspend_devices__obj(device, &block)
109
+ device_selector = ->(writer) { device }
110
+ suspend_devices__device_selector device_selector, &block
111
+ end
112
+
113
+
114
+ def suspend_devices__name(name, &block)
115
+ device_selector = ->(writer) { writer.device name }
116
+ suspend_devices__device_selector device_selector, &block
117
+ end
118
+
119
+ def suspend_devices__device_selector(device_selector, &block)
120
+ suspensions = []
121
+
122
+ each_writer do |writer|
123
+ device = device_selector.call writer
124
+ suspension = Writer::DeviceSuspension.new writer, device
125
+ suspensions << suspension
126
+ suspension.suspend
127
+ end
128
+
129
+ yield
130
+
131
+ suspensions.each { |suspension| suspension.restore }
132
+ end
133
+
134
+ def to_s
135
+ details = "Output : #{self.class.name} - Object Id:#{self.object_id}\n"
136
+ details << "Level: #{self.level}\n"
137
+ details << "Writer Details: \n"
138
+ each_writer do |writer|
139
+ details << "#{writer.to_s}\n"
140
+ end
141
+ details
142
+ end
143
+
144
+ def push_device(device, options = {}, &block)
145
+ return device if device.nil?
146
+
147
+ return push_device__obj(device, &block) if device.is_a? Logging::Appender
148
+
149
+ push_device__opts(type = device, options, &block)
150
+ end
151
+
152
+ def push_device__opts(type, options = {}, &block)
153
+ options = self.class.device_options.merge(options)
154
+ device = Output::Devices.build_device(type, options)
155
+ push_device__obj device, &block
156
+ end
157
+
158
+ def push_device__obj(device, &block)
159
+ each_writer do |writer|
160
+ writer.push_device device
161
+ end
162
+ if block_given?
163
+ yield
164
+ pop_device
165
+ end
166
+ device
167
+ end
168
+
169
+ def pop_device
170
+ each_writer do |writer|
171
+ writer.pop_device
172
+ end
173
+ nil
174
+ end
175
+
176
+
177
+ def add_device(device)
178
+ each_writer do |writer|
179
+ writer.add_device device
180
+ end
181
+ device
182
+ end
183
+
184
+ module ClassMethods
185
+ def default_pattern
186
+ @pattern ||= Output::DEFAULT_PATTERN
187
+ end
188
+
189
+ def pattern(format)
190
+ @pattern = format
191
+ end
192
+
193
+ def default_device_type
194
+ @device ||= ::Output::DEFAULT_DEVICE
195
+ end
196
+
197
+ def device(device)
198
+ @device = device
199
+ end
200
+
201
+ def logger_level
202
+ @logger_level ||= Output::DEFAULT_LOGGER_LEVEL
203
+ end
204
+
205
+
206
+ def logger_level=(level=nil)
207
+ @logger_level = level unless level.nil?
208
+ @logger_level
209
+ end
210
+ alias :level :logger_level=
211
+
212
+ def writer_names
213
+ @writer_names ||= []
214
+ end
215
+
216
+ def device_options
217
+ device_options = {}
218
+ device_options[:device] = default_device_type
219
+ device_options[:pattern] = default_pattern
220
+ device_options
221
+ end
222
+
223
+
224
+ def writer_macro(name, options = {}, &message_transformer)
225
+ level = options[:level] || logger_level
226
+ options = device_options.merge(options)
227
+
228
+ WriterMacro.define_writer self, name, level, options, message_transformer
229
+ writer_names << name
230
+ end
231
+
232
+ alias :writer :writer_macro
233
+
234
+ def writer_attribute(name)
235
+ Writer::Attribute.attribute_name(name)
236
+ end
237
+
238
+ end
239
+ end
@@ -0,0 +1,235 @@
1
+ module Output
2
+ class Writer
3
+ include BuildLogger
4
+ include Initializer
5
+
6
+ attr_reader :name
7
+ attr_accessor :level
8
+ attr_reader :message_transformer
9
+ attr_reader :enabled
10
+ attr_writer :devices
11
+
12
+ initializer :name, :level, :message_transformer, :logger, :device_options
13
+
14
+ def self.build(writer_name, level=Output::DEFAULT_LOGGER_LEVEL, message_transformer=nil, logger_level=Output::DEFAULT_LOGGER_LEVEL, logger_name=nil, device_options)
15
+ logger_name ||= writer_name
16
+ logger = build_logger(logger_name, logger_level, device_options)
17
+ writer = new(writer_name, level, message_transformer, logger, device_options)
18
+ end
19
+
20
+ def devices
21
+ @devices ||= []
22
+ end
23
+
24
+ def disable
25
+ @enabled = false
26
+ end
27
+
28
+ def enable
29
+ @enabled = true
30
+ end
31
+
32
+ def enabled?
33
+ @enabled = true if @enabled.nil?
34
+ @enabled
35
+ end
36
+
37
+ def logger_level
38
+ @logger.level_name
39
+ end
40
+
41
+ def logger_level=(level)
42
+ @logger.level = level
43
+ end
44
+
45
+ def reset_level
46
+ self.logger_level = level
47
+ end
48
+
49
+ def initial_logger_level?
50
+ logger_level == level
51
+ end
52
+
53
+ def logger_name
54
+ @logger.name
55
+ end
56
+
57
+ def write(message)
58
+ message = message_transformer.call message if message_transformer
59
+ @logger.send level, message if self.enabled?
60
+ end
61
+
62
+ def add_device(device)
63
+ @logger.add_appenders device
64
+ device
65
+ end
66
+
67
+ def device(name)
68
+ result = nil
69
+ logger.appenders.each do|device|
70
+ result = device if device.name == name.to_s
71
+ end
72
+ result
73
+ end
74
+
75
+ def number_of_stack_devices
76
+ devices.count
77
+ end
78
+
79
+ def logger_device?(device)
80
+ logger.appenders.include? device
81
+ end
82
+
83
+
84
+
85
+ def remove_device(device)
86
+ @logger.remove_appenders device
87
+ device
88
+ end
89
+
90
+ def logging_appender?(arg)
91
+ arg.is_a? Logging::Appender
92
+ end
93
+
94
+ def suspend_device(device, &block)
95
+ return suspend_device__obj device, &block if logging_appender?(device)
96
+
97
+ suspend_device__name device, &block
98
+ end
99
+
100
+ def suspend_device__name(name, &block)
101
+ dvc = device name
102
+ suspend_device__obj dvc, &block
103
+ end
104
+
105
+ class DeviceSuspension
106
+ include Initializer
107
+
108
+ attr_accessor :logger_device
109
+ attr_accessor :writer_device
110
+
111
+ initializer :writer, :device
112
+
113
+ def restore
114
+ unless device.nil?
115
+ writer.push_device device if (writer_device)
116
+ writer.add_device device if (logger_device)
117
+ end
118
+ end
119
+
120
+
121
+ def suspend
122
+ self.logger_device = writer.logger_device? device
123
+ self.writer_device = writer.device? device
124
+
125
+ writer.remove_device device if logger_device
126
+ writer.devices.delete device if writer_device
127
+ end
128
+ end
129
+
130
+ def suspend_device__obj(device, &block)
131
+ suspension = DeviceSuspension.new self, device
132
+ suspension.suspend
133
+
134
+ if block_given?
135
+ yield
136
+ suspension.restore
137
+ end
138
+ device
139
+ end
140
+
141
+ def push_device__obj(device, &block)
142
+ raise "The writer:[#{self.name}] already has a device named #{device.name}:[#{device.class}]" if device?(device)
143
+
144
+ devices.push device
145
+
146
+ add_device device
147
+
148
+ if block_given?
149
+ yield
150
+ pop_device
151
+ end
152
+ device
153
+ end
154
+
155
+ def push_device(device, options = {}, &block)
156
+ return device if device.nil?
157
+ return push_device__obj(device, &block) if device.is_a? Logging::Appender
158
+
159
+ push_device__opts(type = device, options, &block)
160
+ end
161
+
162
+ def push_device__opts(type, options = {}, &block)
163
+ options = self.device_options.merge(options)
164
+ name = options[:name] || type
165
+
166
+ raise "Writer:[#{self.name}] - already has a device named [#{name}]. It cannot be pushed the device again" unless device(name).nil?
167
+
168
+ device = Output::Devices.build_device(type, options)
169
+ push_device__obj device, &block
170
+ end
171
+
172
+ def pop_device
173
+ return if devices.count == 0
174
+ device = devices.pop
175
+ remove_device device
176
+ end
177
+
178
+ def device?(device)
179
+ return false if device.nil?
180
+
181
+ devices.include?(device) || devices.any? { |dvc| dvc.name == device.name }
182
+ end
183
+
184
+ def to_s
185
+ details = "Writer : #{self.name}\n"
186
+ details << "\tLevel : #{self.level}\n"
187
+ details << "\tDevice Stack : \n"
188
+ devices.each do |device|
189
+ details << "\t\tDevice : #{device.name} - #{device.class}\n"
190
+ end
191
+ details << "\tLogger Appenders : \n"
192
+ logger.appenders.each do |appender|
193
+ details << "\t\t\Appender : #{appender.name} - #{appender.class}\n"
194
+ end
195
+ details
196
+ end
197
+
198
+ class Attribute
199
+ include Initializer
200
+
201
+ attr_reader :name
202
+ attr_reader :variable_name
203
+
204
+ initializer :name, :variable_name
205
+
206
+ def self.build(name)
207
+ attribute_name = attribute_name(name)
208
+ variable_name = variable_name(name)
209
+ new attribute_name, variable_name
210
+ end
211
+
212
+ def self.attribute_name(name)
213
+ :"#{name}_writer"
214
+ end
215
+
216
+ def self.variable_name(name)
217
+ :"@#{name}_writer"
218
+ end
219
+ end
220
+
221
+ module Naming
222
+ extend self
223
+
224
+ def fully_qualified(mod, writer_name)
225
+ namespace = mod.name
226
+ writer_name = camel_case(writer_name)
227
+ "#{namespace}::#{writer_name}"
228
+ end
229
+
230
+ def camel_case(name)
231
+ name.to_s.split('_').collect { |s| s.capitalize }.join
232
+ end
233
+ end
234
+ end
235
+ end
@@ -0,0 +1,62 @@
1
+ module Output
2
+ class WriterMacro
3
+ include Initializer
4
+
5
+ initializer :output_class, :name, :level, :device_options, :message_transformer
6
+
7
+ def self.define_writer(output_class, name, level, device_options, message_transformer)
8
+ macro = new output_class, name, level, device_options, message_transformer
9
+ macro.define_writer
10
+ end
11
+
12
+ def define_writer
13
+ define_getter
14
+ define_setter
15
+ define_write_method
16
+ end
17
+
18
+ def define_getter
19
+ name = self.name
20
+ level = self.level
21
+ transformer = self.message_transformer
22
+ device_options = self.device_options
23
+
24
+ writer_attribute = Writer::Attribute.build name
25
+ attribute_name = writer_attribute.name
26
+ var_name = writer_attribute.variable_name
27
+
28
+ output_class.send :define_method, attribute_name do
29
+ writer = instance_variable_get var_name
30
+
31
+ unless writer
32
+ writer = build_writer(name, level, device_options, transformer) unless writer
33
+ instance_variable_set var_name, writer
34
+ end
35
+
36
+ writer
37
+ end
38
+ end
39
+
40
+ def define_setter
41
+ writer_attribute = Writer::Attribute.build name
42
+ attribute_name = writer_attribute.name
43
+ var_name = writer_attribute.variable_name
44
+
45
+ output_class.send :define_method, "#{attribute_name}=" do |writer|
46
+ writer.logger_level = level
47
+ instance_variable_set var_name, writer
48
+ writer
49
+ end
50
+ end
51
+
52
+ def define_write_method
53
+ name = self.name
54
+ output_class.send :define_method, name do |message|
55
+ writer(name).write message
56
+ self.last_method = name
57
+ message
58
+ end
59
+ end
60
+ end
61
+ end
62
+
data/lib/output.rb ADDED
@@ -0,0 +1,11 @@
1
+ require 'logging'
2
+ require 'setter'
3
+ require 'single'
4
+ require 'initializer'
5
+
6
+ require 'output/devices'
7
+ require 'output/writer_macro'
8
+ require 'output/output'
9
+ require 'output/build_logger'
10
+ require 'output/writer'
11
+
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: output
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - The Sans Collective
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-21 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: logging
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
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
+ description:
31
+ email:
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - lib/output/build_logger.rb
37
+ - lib/output/devices.rb
38
+ - lib/output/output.rb
39
+ - lib/output/writer.rb
40
+ - lib/output/writer_macro.rb
41
+ - lib/output.rb
42
+ homepage: https://github.com/Sans/output
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.9.2
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project:
62
+ rubygems_version: 1.8.25
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Output Library
66
+ test_files: []