d13n 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.rspec +6 -0
- data/.rubocop.yml +5 -0
- data/.ruby-version +1 -0
- data/Gemfile +22 -0
- data/Gemfile.lock +151 -0
- data/Guardfile +63 -0
- data/README.md +200 -0
- data/bin/d13n +11 -0
- data/d13n.gemspec +34 -0
- data/lib/d13n/application/class_methods.rb +56 -0
- data/lib/d13n/application.rb +3 -0
- data/lib/d13n/cli/command.rb +76 -0
- data/lib/d13n/cli/commands/scaffold.rb +345 -0
- data/lib/d13n/configuration/default_source.rb +200 -0
- data/lib/d13n/configuration/dotted_hash.rb +39 -0
- data/lib/d13n/configuration/environment_source.rb +89 -0
- data/lib/d13n/configuration/manager.rb +239 -0
- data/lib/d13n/configuration/manual_source.rb +4 -0
- data/lib/d13n/configuration/mask_defaults.rb +6 -0
- data/lib/d13n/configuration/server_source.rb +83 -0
- data/lib/d13n/configuration/yaml_source.rb +66 -0
- data/lib/d13n/configuration.rb +6 -0
- data/lib/d13n/ext/string.rb +17 -0
- data/lib/d13n/logger/log_once.rb +24 -0
- data/lib/d13n/logger/memory_logger.rb +48 -0
- data/lib/d13n/logger/null_logger.rb +16 -0
- data/lib/d13n/logger.rb +213 -0
- data/lib/d13n/metric/conductor.rb +123 -0
- data/lib/d13n/metric/helper.rb +62 -0
- data/lib/d13n/metric/http_clients/http_helper.rb +15 -0
- data/lib/d13n/metric/http_clients/net_http_wrappers.rb +54 -0
- data/lib/d13n/metric/http_clients.rb +4 -0
- data/lib/d13n/metric/instrumentation/app_exception.rb +70 -0
- data/lib/d13n/metric/instrumentation/controller_instrumentation.rb +91 -0
- data/lib/d13n/metric/instrumentation/em-websocket.rb +71 -0
- data/lib/d13n/metric/instrumentation/exception.rb +65 -0
- data/lib/d13n/metric/instrumentation/middleware_tracing.rb +82 -0
- data/lib/d13n/metric/instrumentation/net.rb +36 -0
- data/lib/d13n/metric/instrumentation/sinatra/stream_namer.rb +35 -0
- data/lib/d13n/metric/instrumentation/sinatra.rb +165 -0
- data/lib/d13n/metric/instrumentation/websocket_instrumentation.rb +42 -0
- data/lib/d13n/metric/instrumentation.rb +41 -0
- data/lib/d13n/metric/manager.rb +106 -0
- data/lib/d13n/metric/metrics/app_database_metric.rb +4 -0
- data/lib/d13n/metric/metrics/app_http_metric.rb +229 -0
- data/lib/d13n/metric/metrics/app_state_metric.rb +103 -0
- data/lib/d13n/metric/metrics/base.rb +14 -0
- data/lib/d13n/metric/metrics/biz_state_metric.rb +4 -0
- data/lib/d13n/metric/metrics.rb +6 -0
- data/lib/d13n/metric/stream/span_tracer_helpers.rb +72 -0
- data/lib/d13n/metric/stream/stream_tracer_helpers.rb +141 -0
- data/lib/d13n/metric/stream/traced_span_stack.rb +73 -0
- data/lib/d13n/metric/stream.rb +322 -0
- data/lib/d13n/metric/stream_state.rb +68 -0
- data/lib/d13n/metric.rb +11 -0
- data/lib/d13n/rack/d13n_middleware.rb +21 -0
- data/lib/d13n/rack/metric_middleware.rb +18 -0
- data/lib/d13n/service/background_job/sinatra.rb +24 -0
- data/lib/d13n/service/background_job.rb +1 -0
- data/lib/d13n/service/start.rb +75 -0
- data/lib/d13n/service.rb +91 -0
- data/lib/d13n/support/request_id.rb +29 -0
- data/lib/d13n/version.rb +14 -0
- data/lib/d13n.rb +92 -0
- data/templates/.rspec.template +6 -0
- data/templates/.ruby-version.template +1 -0
- data/templates/Gemfile.template +16 -0
- data/templates/Guardfile.template +64 -0
- data/templates/Jenkinsfile.template +85 -0
- data/templates/Makefile.template +178 -0
- data/templates/README.md.template +1 -0
- data/templates/Rakefile.template +6 -0
- data/templates/application.yml.template +14 -0
- data/templates/config.ru.template +4 -0
- data/templates/docker/.dockerignore.template +5 -0
- data/templates/docker/Dockerfile.application.development +15 -0
- data/templates/docker/Dockerfile.cache.development +18 -0
- data/templates/docker/Dockerfile.development +27 -0
- data/templates/docker/Dockerfile.release +16 -0
- data/templates/docker/docker-compose.yml.development +53 -0
- data/templates/docker/docker-compose.yml.release +37 -0
- data/templates/lib/api/service.rb.template +10 -0
- data/templates/lib/api/support.rb.template +38 -0
- data/templates/lib/api/version.rb.template +3 -0
- data/templates/lib/api.rb.template +4 -0
- data/templates/lib/application.rb.template +49 -0
- data/templates/lib/service.rb.template +4 -0
- data/templates/lib/version.rb.template +3 -0
- data/templates/scripts/test.sh.template +7 -0
- data/templates/spec/spec_helper.rb.template +56 -0
- data/templates/tasks/migration.rake.template +11 -0
- data/templates/tasks/spec.rake.template +21 -0
- metadata +199 -0
@@ -0,0 +1,239 @@
|
|
1
|
+
|
2
|
+
module D13n::Configuration
|
3
|
+
class Manager
|
4
|
+
def [](key)
|
5
|
+
@cache[key]
|
6
|
+
end
|
7
|
+
|
8
|
+
def has_key?(key)
|
9
|
+
@cache.has_key?(key)
|
10
|
+
end
|
11
|
+
|
12
|
+
def keys
|
13
|
+
@cache.keys
|
14
|
+
end
|
15
|
+
|
16
|
+
def key(value)
|
17
|
+
@cache.key(value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def alias_key_for(value)
|
21
|
+
alias_for(key(value))
|
22
|
+
end
|
23
|
+
|
24
|
+
def alias_for(key)
|
25
|
+
@alias_cache[key]
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
reset_to_defaults
|
30
|
+
@callbacks = Hash.new { |hash, key| hash[key] = [] }
|
31
|
+
end
|
32
|
+
|
33
|
+
def remove_config_type(sym)
|
34
|
+
source = case sym
|
35
|
+
when :environment then @environment_source
|
36
|
+
when :server then @server_source
|
37
|
+
when :manual then @manual_source
|
38
|
+
when :yaml then @yaml_source
|
39
|
+
when :default then @default_source
|
40
|
+
end
|
41
|
+
|
42
|
+
remove_config(source)
|
43
|
+
end
|
44
|
+
|
45
|
+
def remove_config(source)
|
46
|
+
case source
|
47
|
+
when EnvironmentSource then @environment_source = nil
|
48
|
+
when ServerSource then @server_source = nil
|
49
|
+
when ManualSource then @manual_source = nil
|
50
|
+
when YamlSource then @yaml_source = nil
|
51
|
+
when DefaultSource then @default_source = nil
|
52
|
+
end
|
53
|
+
|
54
|
+
reset_cache
|
55
|
+
reset_alias
|
56
|
+
invoke_callbacks(:remove, source)
|
57
|
+
log_config(:remove, source)
|
58
|
+
end
|
59
|
+
|
60
|
+
def replace_or_add_config(source)
|
61
|
+
source.freeze
|
62
|
+
|
63
|
+
invoke_callbacks(:add, source)
|
64
|
+
case source
|
65
|
+
when EnvironmentSource then @environment_source = source
|
66
|
+
when ServerSource then @server_source = source
|
67
|
+
when ManualSource then @manual_source = source
|
68
|
+
when YamlSource then @yaml_source = source
|
69
|
+
when DefaultSource then @default_source = source
|
70
|
+
else
|
71
|
+
D13n.logger.warn("Invalid config format; config will be ignored: #{source}")
|
72
|
+
end
|
73
|
+
|
74
|
+
reset_cache
|
75
|
+
reset_alias
|
76
|
+
log_config(:add, source)
|
77
|
+
end
|
78
|
+
|
79
|
+
def source(key)
|
80
|
+
config_stack.each do |config|
|
81
|
+
if config.respond_to?(key.to_sym) || config.has_key?(key.to_sym)
|
82
|
+
return config
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def fetch(key)
|
88
|
+
config_stack.each do |config|
|
89
|
+
next unless config
|
90
|
+
accessor = key.to_sym
|
91
|
+
|
92
|
+
if config.has_key?(accessor)
|
93
|
+
evaluated = evaluate_procs(config[accessor])
|
94
|
+
begin
|
95
|
+
return apply_transformations(accessor, evaluated)
|
96
|
+
rescue
|
97
|
+
next
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
def apply_transformations(key, value)
|
105
|
+
if transform = transform_from_default(key)
|
106
|
+
begin
|
107
|
+
transform.call(value)
|
108
|
+
rescue => e
|
109
|
+
D13n.logger.error("Error applying transformation for #{key}, pre-transform value was: #{value}.", e)
|
110
|
+
raise e
|
111
|
+
end
|
112
|
+
else
|
113
|
+
value
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def transform_from_default(key)
|
118
|
+
D13n::Configuration::DefaultSource.transform_for(key)
|
119
|
+
end
|
120
|
+
|
121
|
+
def evaluate_procs(value)
|
122
|
+
if value.respond_to?(:call)
|
123
|
+
instance_eval(&value)
|
124
|
+
else
|
125
|
+
value
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Generally only useful during initial construction and tests
|
130
|
+
def reset_to_defaults
|
131
|
+
@environment_source = EnvironmentSource.new
|
132
|
+
@server_source = nil
|
133
|
+
@manual_source = nil
|
134
|
+
@yaml_source = nil
|
135
|
+
@default_source = DefaultSource.new
|
136
|
+
reset_cache
|
137
|
+
reset_alias
|
138
|
+
end
|
139
|
+
|
140
|
+
def reset_cache
|
141
|
+
@cache = Hash.new {|hash,key| hash[key] = self.fetch(key) }
|
142
|
+
end
|
143
|
+
|
144
|
+
def reset_alias
|
145
|
+
@alias_cache = @default_source.default_alias
|
146
|
+
end
|
147
|
+
|
148
|
+
def log_config(direction, source)
|
149
|
+
D13n.logger.debug do
|
150
|
+
"Updating config (#{direction}) from #{source.class}. Results: #{flattened.inspect}"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def register_callback(key, &proc)
|
155
|
+
@callbacks[key] << proc
|
156
|
+
proc.call(@cache[key])
|
157
|
+
end
|
158
|
+
|
159
|
+
def invoke_callbacks(direction, source)
|
160
|
+
return unless source
|
161
|
+
source.keys.each do |key|
|
162
|
+
|
163
|
+
if @cache[key] != source[key]
|
164
|
+
@callbacks[key].each do |proc|
|
165
|
+
if direction == :add
|
166
|
+
proc.call(source[key])
|
167
|
+
else
|
168
|
+
proc.call(@cache[key])
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def flattened
|
176
|
+
config_stack.reverse.inject({}) do |flat,layer|
|
177
|
+
thawed_layer = layer.to_hash.dup
|
178
|
+
thawed_layer.each do |k,v|
|
179
|
+
begin
|
180
|
+
thawed_layer[k] = instance_eval(&v) if v.respond_to?(:call)
|
181
|
+
rescue => e
|
182
|
+
D13n.logger.debug("#{e.class.name} : #{e.message} - when accessing config key #{k}")
|
183
|
+
thawed_layer[k] = nil
|
184
|
+
end
|
185
|
+
thawed_layer.delete(:config)
|
186
|
+
end
|
187
|
+
flat.merge(thawed_layer.to_hash)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def apply_mask(hash)
|
192
|
+
MASK_DEFAULTS. \
|
193
|
+
select {|_, proc| proc.call}. \
|
194
|
+
each {|key, _| hash.delete(key) }
|
195
|
+
hash
|
196
|
+
end
|
197
|
+
|
198
|
+
def to_hash
|
199
|
+
DottedHash.new(apply_mask(flattened)).to_hash
|
200
|
+
end
|
201
|
+
|
202
|
+
def to_collector_hash
|
203
|
+
DottedHash.new(apply_mask(flattened)).to_hash.delete_if do |k, v|
|
204
|
+
default = DEFAULTS[k]
|
205
|
+
if default
|
206
|
+
default[:exclude_from_reported_settings]
|
207
|
+
else
|
208
|
+
false
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
def app_name
|
214
|
+
D13n.config[:app_name]
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
def config_stack
|
220
|
+
stack = [@environment_source,
|
221
|
+
@server_source,
|
222
|
+
@manual_source,
|
223
|
+
@yaml_source,
|
224
|
+
@default_source]
|
225
|
+
|
226
|
+
stack.compact!
|
227
|
+
stack
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
require 'd13n/configuration/mask_defaults'
|
234
|
+
require 'd13n/configuration/dotted_hash'
|
235
|
+
require 'd13n/configuration/default_source'
|
236
|
+
require 'd13n/configuration/yaml_source'
|
237
|
+
require 'd13n/configuration/environment_source'
|
238
|
+
require 'd13n/configuration/server_source'
|
239
|
+
require 'd13n/configuration/manual_source'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module D13n::Configuration
|
2
|
+
class ServerSource < DottedHash
|
3
|
+
SERVICE_PREFIXES = /^service/i
|
4
|
+
PROPERTY_PREFIXES = /^property/i
|
5
|
+
IDC_PREFIXES = /^idc/i
|
6
|
+
CLIENT_PREFIXES = /^client/i
|
7
|
+
JURISDICTION_PREFIXES = /^jurisdiction/i
|
8
|
+
|
9
|
+
attr_accessor :type_map
|
10
|
+
|
11
|
+
def initialize(connect_reply)
|
12
|
+
#filter_keys(connect_reply)
|
13
|
+
@type_map = {}
|
14
|
+
|
15
|
+
DEFAULTS.each do |config_setting, value|
|
16
|
+
self.type_map[config_setting] = value[:type]
|
17
|
+
end
|
18
|
+
|
19
|
+
super(connect_reply)
|
20
|
+
end
|
21
|
+
|
22
|
+
def set_keys_by_type()
|
23
|
+
self.keys.each do |key|
|
24
|
+
set_key_by_type(key)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_key_by_type(config_key)
|
29
|
+
value = self[config_key]
|
30
|
+
type = self.type_map[config_key]
|
31
|
+
|
32
|
+
if type == String
|
33
|
+
self[config_key] = value.to_s
|
34
|
+
elsif type == Integer
|
35
|
+
self[config_key] = value.to_i
|
36
|
+
elsif type == Float
|
37
|
+
self[config_key] = value.to_f
|
38
|
+
elsif type == Symbol
|
39
|
+
self[config_key] = value.to_sym
|
40
|
+
elsif type == Array
|
41
|
+
self[config_key] = value.split(/\s*,\s*/)
|
42
|
+
elsif type == D13n::Configuration::Boolean
|
43
|
+
if value =~ /false|off|no/i
|
44
|
+
self[config_key] = false
|
45
|
+
elsif value != nil
|
46
|
+
self[config_key] = true
|
47
|
+
end
|
48
|
+
else
|
49
|
+
D13n.logger.info("#{config_key} does not have a corresponding configuration setting (#{config_key} does not exist).")
|
50
|
+
self[config_key] = value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.build(connect_reply)
|
55
|
+
instance = new(connect_reply)
|
56
|
+
self.filter_keys(instance)
|
57
|
+
instance
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.filter_keys(instance)
|
61
|
+
instance.delete_if do |key, _|
|
62
|
+
s_key = key.to_s
|
63
|
+
if s_key.match(SERVICE_PREFIXES) || s_key.match(PROPERTY_PREFIXES) || s_key.match(IDC_PREFIXES) || s_key.match(CLIENT_PREFIXES) || s_key.match(JURISDICTION_PREFIXES)
|
64
|
+
false
|
65
|
+
else
|
66
|
+
setting_spec = DEFAULTS[key.to_sym]
|
67
|
+
if setting_spec
|
68
|
+
if setting_spec[:allowed_from_server]
|
69
|
+
instance.set_key_by_type(key)
|
70
|
+
false # it's allowed, so don't delete it
|
71
|
+
else
|
72
|
+
D13n.logger.warn("Ignoring server-sent config for '#{key}' - this setting cannot be set from the server")
|
73
|
+
true # delete it
|
74
|
+
end
|
75
|
+
else
|
76
|
+
D13n.logger.debug("Ignoring unrecognized config key from server: '#{key}'")
|
77
|
+
true
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
module D13n::Configuration
|
3
|
+
class YamlSource < DottedHash
|
4
|
+
attr_accessor :file_path, :failures
|
5
|
+
|
6
|
+
def initialize(path,env)
|
7
|
+
config = {}
|
8
|
+
@failures = []
|
9
|
+
|
10
|
+
begin
|
11
|
+
@file_path = validate_config_file(path)
|
12
|
+
return unless @file_path
|
13
|
+
|
14
|
+
D13n.logger.info("Reading configuration from #{path} (#{Dir.pwd})")
|
15
|
+
raw_file = File.read(@file_path)
|
16
|
+
erb_file = process_erb(raw_file)
|
17
|
+
config = process_yaml(erb_file, env, config, @file_path)
|
18
|
+
rescue ScriptError, StandardError => e
|
19
|
+
log_failure("Failed to read or parse configuration file at #{path}", e)
|
20
|
+
end
|
21
|
+
|
22
|
+
super(config, true)
|
23
|
+
end
|
24
|
+
|
25
|
+
protected
|
26
|
+
|
27
|
+
def validate_config_file(path)
|
28
|
+
expanded_path = File.expand_path(path)
|
29
|
+
|
30
|
+
if path.empty? || !File.exist?(expanded_path)
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
expanded_path
|
35
|
+
end
|
36
|
+
|
37
|
+
def process_erb(file)
|
38
|
+
begin
|
39
|
+
file.gsub!(/^\s*#.*$/, '#')
|
40
|
+
|
41
|
+
ERB.new(file).result(binding)
|
42
|
+
rescue Exception => e
|
43
|
+
log_failure("Failed ERB processing configuration file. This is typically caused by a Ruby error in <% %> templating blocks in your axle.yml file.", e)
|
44
|
+
ensure
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def process_yaml(file, env, config, path)
|
50
|
+
if file
|
51
|
+
confighash = YAML.load(file)
|
52
|
+
unless confighash.key?(env)
|
53
|
+
log_failure("Config file at #{path} doesn't include a '#{env}' section!")
|
54
|
+
end
|
55
|
+
config = confighash[env] || {}
|
56
|
+
end
|
57
|
+
|
58
|
+
config
|
59
|
+
end
|
60
|
+
|
61
|
+
def log_failure(*messages)
|
62
|
+
D13n.logger.error(*messages)
|
63
|
+
@failures << messages
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class String
|
2
|
+
# By default, +camelize+ converts strings to UpperCamelCase.
|
3
|
+
#
|
4
|
+
# 'active_record'.camelize # => "ActiveRecord"
|
5
|
+
def camelize
|
6
|
+
string = self
|
7
|
+
string.split('_').map{ |e| e.capitalize }.join
|
8
|
+
end
|
9
|
+
|
10
|
+
def underscore
|
11
|
+
self.gsub(/::/, '/').
|
12
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
13
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
14
|
+
tr("-", "_").
|
15
|
+
downcase
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module D13n
|
3
|
+
class Logger
|
4
|
+
module LogOnce
|
5
|
+
NUM_LOG_ONCE_KEYS = 1000
|
6
|
+
|
7
|
+
def log_once(level, key, *msgs)
|
8
|
+
return if @already_logged.include?(key)
|
9
|
+
|
10
|
+
if @already_logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
|
11
|
+
return
|
12
|
+
end
|
13
|
+
|
14
|
+
@already_logged[key] = true
|
15
|
+
|
16
|
+
self.send(level, *msgs)
|
17
|
+
end
|
18
|
+
|
19
|
+
def clear_already_logged
|
20
|
+
@already_logged = {}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module D13n
|
3
|
+
class Logger
|
4
|
+
class MemoryLogger
|
5
|
+
include LogOnce
|
6
|
+
def initialize
|
7
|
+
@messages = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def is_startup_logger?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_accessor :messages, :level, :log_formatter
|
15
|
+
|
16
|
+
def fatal(*msgs, &blk)
|
17
|
+
messages << [:fatal, msgs, blk]
|
18
|
+
end
|
19
|
+
|
20
|
+
def error(*msgs, &blk)
|
21
|
+
messages << [:error, msgs, blk]
|
22
|
+
end
|
23
|
+
|
24
|
+
def warn(*msgs, &blk)
|
25
|
+
messages << [:warn, msgs, blk]
|
26
|
+
end
|
27
|
+
|
28
|
+
def info(*msgs, &blk)
|
29
|
+
messages << [:info, msgs, blk]
|
30
|
+
end
|
31
|
+
|
32
|
+
def debug(*msgs, &blk)
|
33
|
+
messages << [:debug, msgs, blk]
|
34
|
+
end
|
35
|
+
|
36
|
+
def log_exception(level, e, backtrace_level=level)
|
37
|
+
messages << [:log_exception, [level, e, backtrace_level]]
|
38
|
+
end
|
39
|
+
|
40
|
+
def dump(logger)
|
41
|
+
messages.each do |(method, args, blk)|
|
42
|
+
logger.send(method, *args, &blk)
|
43
|
+
end
|
44
|
+
messages.clear
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module D13n
|
2
|
+
class Logger
|
3
|
+
class NullLogger
|
4
|
+
include Singleton
|
5
|
+
def fatal(*args); end
|
6
|
+
def error(*args); end
|
7
|
+
def warn(*args); end
|
8
|
+
def info(*args); end
|
9
|
+
def debug(*args); end
|
10
|
+
|
11
|
+
def method_missing(method, *args, &blk)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|