output 0.0.1

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.
@@ -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: []