d13n 0.5.2

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.
Files changed (95) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.rspec +6 -0
  4. data/.rubocop.yml +5 -0
  5. data/.ruby-version +1 -0
  6. data/Gemfile +22 -0
  7. data/Gemfile.lock +151 -0
  8. data/Guardfile +63 -0
  9. data/README.md +200 -0
  10. data/bin/d13n +11 -0
  11. data/d13n.gemspec +34 -0
  12. data/lib/d13n/application/class_methods.rb +56 -0
  13. data/lib/d13n/application.rb +3 -0
  14. data/lib/d13n/cli/command.rb +76 -0
  15. data/lib/d13n/cli/commands/scaffold.rb +345 -0
  16. data/lib/d13n/configuration/default_source.rb +200 -0
  17. data/lib/d13n/configuration/dotted_hash.rb +39 -0
  18. data/lib/d13n/configuration/environment_source.rb +89 -0
  19. data/lib/d13n/configuration/manager.rb +239 -0
  20. data/lib/d13n/configuration/manual_source.rb +4 -0
  21. data/lib/d13n/configuration/mask_defaults.rb +6 -0
  22. data/lib/d13n/configuration/server_source.rb +83 -0
  23. data/lib/d13n/configuration/yaml_source.rb +66 -0
  24. data/lib/d13n/configuration.rb +6 -0
  25. data/lib/d13n/ext/string.rb +17 -0
  26. data/lib/d13n/logger/log_once.rb +24 -0
  27. data/lib/d13n/logger/memory_logger.rb +48 -0
  28. data/lib/d13n/logger/null_logger.rb +16 -0
  29. data/lib/d13n/logger.rb +213 -0
  30. data/lib/d13n/metric/conductor.rb +123 -0
  31. data/lib/d13n/metric/helper.rb +62 -0
  32. data/lib/d13n/metric/http_clients/http_helper.rb +15 -0
  33. data/lib/d13n/metric/http_clients/net_http_wrappers.rb +54 -0
  34. data/lib/d13n/metric/http_clients.rb +4 -0
  35. data/lib/d13n/metric/instrumentation/app_exception.rb +70 -0
  36. data/lib/d13n/metric/instrumentation/controller_instrumentation.rb +91 -0
  37. data/lib/d13n/metric/instrumentation/em-websocket.rb +71 -0
  38. data/lib/d13n/metric/instrumentation/exception.rb +65 -0
  39. data/lib/d13n/metric/instrumentation/middleware_tracing.rb +82 -0
  40. data/lib/d13n/metric/instrumentation/net.rb +36 -0
  41. data/lib/d13n/metric/instrumentation/sinatra/stream_namer.rb +35 -0
  42. data/lib/d13n/metric/instrumentation/sinatra.rb +165 -0
  43. data/lib/d13n/metric/instrumentation/websocket_instrumentation.rb +42 -0
  44. data/lib/d13n/metric/instrumentation.rb +41 -0
  45. data/lib/d13n/metric/manager.rb +106 -0
  46. data/lib/d13n/metric/metrics/app_database_metric.rb +4 -0
  47. data/lib/d13n/metric/metrics/app_http_metric.rb +229 -0
  48. data/lib/d13n/metric/metrics/app_state_metric.rb +103 -0
  49. data/lib/d13n/metric/metrics/base.rb +14 -0
  50. data/lib/d13n/metric/metrics/biz_state_metric.rb +4 -0
  51. data/lib/d13n/metric/metrics.rb +6 -0
  52. data/lib/d13n/metric/stream/span_tracer_helpers.rb +72 -0
  53. data/lib/d13n/metric/stream/stream_tracer_helpers.rb +141 -0
  54. data/lib/d13n/metric/stream/traced_span_stack.rb +73 -0
  55. data/lib/d13n/metric/stream.rb +322 -0
  56. data/lib/d13n/metric/stream_state.rb +68 -0
  57. data/lib/d13n/metric.rb +11 -0
  58. data/lib/d13n/rack/d13n_middleware.rb +21 -0
  59. data/lib/d13n/rack/metric_middleware.rb +18 -0
  60. data/lib/d13n/service/background_job/sinatra.rb +24 -0
  61. data/lib/d13n/service/background_job.rb +1 -0
  62. data/lib/d13n/service/start.rb +75 -0
  63. data/lib/d13n/service.rb +91 -0
  64. data/lib/d13n/support/request_id.rb +29 -0
  65. data/lib/d13n/version.rb +14 -0
  66. data/lib/d13n.rb +92 -0
  67. data/templates/.rspec.template +6 -0
  68. data/templates/.ruby-version.template +1 -0
  69. data/templates/Gemfile.template +16 -0
  70. data/templates/Guardfile.template +64 -0
  71. data/templates/Jenkinsfile.template +85 -0
  72. data/templates/Makefile.template +178 -0
  73. data/templates/README.md.template +1 -0
  74. data/templates/Rakefile.template +6 -0
  75. data/templates/application.yml.template +14 -0
  76. data/templates/config.ru.template +4 -0
  77. data/templates/docker/.dockerignore.template +5 -0
  78. data/templates/docker/Dockerfile.application.development +15 -0
  79. data/templates/docker/Dockerfile.cache.development +18 -0
  80. data/templates/docker/Dockerfile.development +27 -0
  81. data/templates/docker/Dockerfile.release +16 -0
  82. data/templates/docker/docker-compose.yml.development +53 -0
  83. data/templates/docker/docker-compose.yml.release +37 -0
  84. data/templates/lib/api/service.rb.template +10 -0
  85. data/templates/lib/api/support.rb.template +38 -0
  86. data/templates/lib/api/version.rb.template +3 -0
  87. data/templates/lib/api.rb.template +4 -0
  88. data/templates/lib/application.rb.template +49 -0
  89. data/templates/lib/service.rb.template +4 -0
  90. data/templates/lib/version.rb.template +3 -0
  91. data/templates/scripts/test.sh.template +7 -0
  92. data/templates/spec/spec_helper.rb.template +56 -0
  93. data/templates/tasks/migration.rake.template +11 -0
  94. data/templates/tasks/spec.rake.template +21 -0
  95. 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,4 @@
1
+ module D13n::Configuration
2
+ class ManualSource < DottedHash
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module D13n
2
+ module Configuration
3
+ MASK_DEFAULTS = {
4
+ }
5
+ end
6
+ end
@@ -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,6 @@
1
+ require 'd13n/configuration/manager'
2
+
3
+ module D13n
4
+ module Configuration
5
+ end
6
+ 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