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,213 @@
1
+ # encoding: utf-8
2
+ #require 'd13n/api/operation_state'
3
+ require 'logger'
4
+ require 'singleton'
5
+ require 'd13n/logger/log_once'
6
+ require 'd13n/logger/memory_logger'
7
+ require 'd13n/logger/null_logger'
8
+ module D13n
9
+ class Logger
10
+ class SilenceLogger
11
+ def fatal(*args); end
12
+ def error(*args); end
13
+ def warn(*args); end
14
+ def info(*args); end
15
+ def debug(*args); end
16
+
17
+ def method_missing(method, *args, &blk)
18
+ nil
19
+ end
20
+ end
21
+
22
+ def initialize(root="STDOUT", override_logger=nil)
23
+ @root = root
24
+
25
+ create_logger(@root, override_logger)
26
+ set_log_level!
27
+ set_log_format!
28
+
29
+ gather_startup_logs
30
+ end
31
+
32
+ def info(*msgs, &blk)
33
+ format_and_send(:info, msgs, &blk)
34
+ end
35
+
36
+ def warn(*msgs, &blk)
37
+ format_and_send(:warn, msgs, &blk)
38
+ end
39
+
40
+ def error(*msgs, &blk)
41
+ format_and_send(:error, msgs, &blk)
42
+ end
43
+
44
+ def fatal(*msgs, &blk)
45
+ format_and_send(:fatal, msgs, &blk)
46
+ end
47
+
48
+ def debug(*msgs, &blk)
49
+ format_and_send(:debug, msgs, &blk)
50
+ end
51
+
52
+ def log_formatter=(formatter)
53
+ @log.formatter = formatter
54
+ end
55
+
56
+ def log_exception(level, e, backtrace_level=level)
57
+ @log.send(level, "%p: %s" % [ e.class, e.message ])
58
+ @log.send(backtrace_level) do
59
+ backtrace = backtrace_from_exception(e)
60
+ if backtrace
61
+ "Debugging backtrace:\n" + backtrace.join("\n ")
62
+ else
63
+ "No backtrace available."
64
+ end
65
+ end
66
+ end
67
+
68
+ def formatter
69
+ @log.formatter
70
+ end
71
+
72
+ private
73
+
74
+ def backtrace_from_exception(e)
75
+ return caller.drop(5) if e.is_a?(SystemStackError)
76
+
77
+ e.backtrace
78
+ end
79
+
80
+ def find_or_create_file_path(path_setting, root)
81
+ for abs_path in [ File.expand_path(path_setting),
82
+ File.expand_path(File.join(root, path_setting)) ] do
83
+ if File.directory?(abs_path) || (Dir.mkdir(abs_path) rescue nil)
84
+ return abs_path[%r{^(.*?)/?$}]
85
+ end
86
+ end
87
+ nil
88
+ end
89
+
90
+ def format_and_send(level, *msgs, &block)
91
+ if block
92
+ if @log.send("#{level}?")
93
+ msgs = Array(block.call)
94
+ else
95
+ msgs = []
96
+ end
97
+ end
98
+
99
+ msgs.flatten.each do |item|
100
+ case item
101
+ when Exception then log_exception(level, item, :debug)
102
+ else @log.send(level, item)
103
+ end
104
+ end
105
+ nil
106
+ end
107
+
108
+ LOG_LEVELS = {
109
+ "debug" => ::Logger::DEBUG,
110
+ "info" => ::Logger::INFO,
111
+ "warn" => ::Logger::WARN,
112
+ "error" => ::Logger::ERROR,
113
+ "fatal" => ::Logger::FATAL,
114
+ }
115
+
116
+ def self.log_level_for(level)
117
+ LOG_LEVELS.fetch(level.to_s.downcase, ::Logger::INFO)
118
+ end
119
+
120
+ def set_log_level!
121
+ @log.level = self.class.log_level_for(::D13n.config[:log_level])
122
+ end
123
+
124
+ def log_stdout?
125
+ D13n.config[:log_file_path].upcase == "STDOUT"
126
+ end
127
+
128
+ def create_log_to_file(root)
129
+ path = find_or_create_file_path(::D13n.config[:log_file_path], root)
130
+ if path.nil?
131
+ @log = ::Logger.new(STDOUT)
132
+ warn("Error creating log directory #{::D13n.config[:log_file_path]}, using standard out for logging.")
133
+ else
134
+ file_path = "#{path}/#{::D13n.config[:log_file_name]}"
135
+ begin
136
+ @log = ::Logger.new(file_path)
137
+ rescue => e
138
+ @log = ::Logger.new(STDOUT)
139
+ warn("Failed creating logger for file #{file_path}, using standard out for logging.", e)
140
+ end
141
+ end
142
+ end
143
+
144
+ def create_logger(root,override_logger)
145
+ if !override_logger.nil?
146
+ @log = override_logger
147
+ elsif ::D13n.config[:log_level] == :silence
148
+ create_silence_logger
149
+ else
150
+ if log_stdout?
151
+ @log = ::Logger.new(STDOUT)
152
+ else
153
+ create_log_to_file(root)
154
+ end
155
+ end
156
+ end
157
+
158
+ def set_log_format!
159
+ @prefix = log_stdout? ? "** [#{D13n.config[:app_name].capitalize}]" : ''
160
+ @log.formatter =
161
+ if log_format == 'json'
162
+ Proc.new do |severity, timestamp, progname, msg|
163
+ log_data = tag_hash.merge({
164
+ app: D13n.config.app_name,
165
+ ts: timestamp.strftime("%F %H:%M:%S %z"),
166
+ pid: $$,
167
+ severity: severity,
168
+ request_id: request_id
169
+ })
170
+ if msg.respond_to?(:to_hash)
171
+ log_data.merge!(msg.to_hash)
172
+ else
173
+ log_data.merge!({message: msg})
174
+ end
175
+ "#{log_data.to_json}\n"
176
+ end
177
+ else
178
+ Proc.new do |severity, timestamp, progname, msg|
179
+ "#{@prefix}[#{timestamp.strftime("%F %H:%M:%S %z")} (#{$$})] #{severity} #{request_id} : #{msg}\n"
180
+ end
181
+ end
182
+ end
183
+
184
+ def log_format
185
+ ::D13n.config[:log_format]
186
+ end
187
+
188
+ def state
189
+ D13n::Metric::StreamState.st_get
190
+ end
191
+
192
+ def request_id
193
+ @request_info = state.request_info || {}
194
+ @request_info['request_id'] || '-'
195
+ end
196
+
197
+ def tag_hash
198
+ state.tag_hash || {}
199
+ end
200
+
201
+ def create_silence_logger
202
+ @log = SilenceLogger.new
203
+ end
204
+
205
+ def gather_startup_logs
206
+ StartupLogger.instance.dump(self)
207
+ end
208
+
209
+ class StartupLogger < MemoryLogger
210
+ include Singleton
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,123 @@
1
+ require 'd13n/metric'
2
+ module D13n::Metric::Instrumentation
3
+ module Conductor
4
+ module_function
5
+ @concerts = []
6
+
7
+ def direct(&block)
8
+ concert = Performance.new
9
+ concert.instance_eval(&block)
10
+
11
+ if concert.name
12
+ seen_names = @concerts.map { |c| c.name }.compact
13
+ if seen_names.include?(concert.name)
14
+ D13n.logger.warn("Refusing to re-register Performance block with name '#{concert.name}'")
15
+ return @concerts
16
+ end
17
+ end
18
+
19
+ @concerts << concert
20
+ end
21
+
22
+ def perform!
23
+ @concerts.each do |concert|
24
+ if concert.ready?
25
+ concert.perform
26
+ end
27
+ end
28
+ end
29
+
30
+ def concert_by_name(name)
31
+ @concerts.find { |c| c.name == name }
32
+ end
33
+
34
+ def performed?(name)
35
+ concert = concert_by_name(name)
36
+ concert && concert.performed
37
+ end
38
+
39
+ def concerts
40
+ @concerts
41
+ end
42
+
43
+ def concerts=(new_concerts)
44
+ @concerts = new_concerts
45
+ end
46
+
47
+ def clear
48
+ @concerts = []
49
+ end
50
+
51
+ class Performance
52
+ attr_reader :performed
53
+ attr_accessor :name
54
+
55
+ def perform!
56
+ @performed = true
57
+ end
58
+
59
+ attr_reader :dependences
60
+
61
+ def initialize
62
+ @dependences = []
63
+ @performances = []
64
+ @name = nil
65
+ end
66
+
67
+ def ready?
68
+ !performed and check_dependences
69
+ end
70
+
71
+ def perform
72
+ @performances.each do |p|
73
+ begin
74
+ p.call
75
+ rescue => e
76
+ D13n.logger.error("Error while setting up #{self.name} instrumentation:", e)
77
+ break
78
+ end
79
+ end
80
+ ensure
81
+ perform!
82
+ end
83
+
84
+ def depend_on
85
+ @dependences << Proc.new
86
+ end
87
+
88
+ def check_dependences
89
+ return false unless allowed_by_config? && dependences
90
+
91
+ dependences.all? do |score|
92
+ begin
93
+ score.call
94
+ rescue => e
95
+ D13n.logger.error("Error while checking #{self.name}:", e)
96
+ false
97
+ end
98
+ end
99
+ end
100
+
101
+ def allowed_by_config?
102
+ return true if self.name.nil?
103
+
104
+ key = "instrumentation.#{self.name}.disable".to_sym
105
+
106
+ if (D13n.config[key] == true)
107
+ D13n.logger.debug("Not setting up #{self.name} instrumentation for configuration #{key}")
108
+ false
109
+ else
110
+ true
111
+ end
112
+ end
113
+
114
+ def named(new_name)
115
+ self.name = new_name
116
+ end
117
+
118
+ def performances
119
+ @performances << Proc.new
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,62 @@
1
+ module D13n::Metric
2
+ module Helper
3
+ def self.http_request_for(app_name, direction)
4
+ downcase_direction = direction.to_s.downcase
5
+ check_direction(downcase_direction)
6
+ scope ||= []
7
+ scope << D13n.idc_name
8
+ scope << D13n.app_name.downcase
9
+ scope << D13n.idc_env
10
+ scope << 'http'
11
+ scope << downcase_direction
12
+ scope
13
+ end
14
+
15
+ def self.http_request_count_for(service, direction)
16
+ scope = http_request_for(service, direction)
17
+ scope << "count"
18
+ scope.join('.')
19
+ end
20
+
21
+ def self.http_request_timing_for(service, direction)
22
+ scope = http_request_for(service, direction)
23
+ scope << "timing"
24
+ scope.join('.')
25
+ end
26
+
27
+ def self.http_in_tracable?
28
+ D13n.config[:'metric.app.http.in.tracable'] == 'true' || D13n.config[:'metric.app.http.in.tracable'] == true
29
+ end
30
+
31
+ def self.http_out_tracable?
32
+ D13n.config[:'metric.app.http.out.tracable'] == 'true' || D13n.config[:'metric.app.http.out.tracable'] == true
33
+ end
34
+
35
+ def self.db_tracable?
36
+ D13n.config[:'metric.app.db.tracable'] == 'true' || D13n.config[:'metric.app.db.tracable'] == true
37
+ end
38
+
39
+ def self.biz_tracable?
40
+ D13n.config[:'metric.business.state.tracable'] == 'true' || D13n.config[:'metric.business.state.tracable'] == true
41
+ end
42
+
43
+ def self.exception_tracable?
44
+ D13n.config[:'metric.app.state.exception.tracable'] == 'true' || D13n.config[:'metric.app.state.exception.tracable'] == true
45
+ end
46
+
47
+ def self.service_for(uri)
48
+ port = (uri.port.to_i == 80 ? "" : ":#{uri.port}")
49
+ url = "#{uri.scheme}://#{uri.host}#{port}"
50
+ expected_service = D13n.config.alias_key_for(url)
51
+ return nil if expected_service.nil?
52
+ expected_service.to_s.downcase
53
+ end
54
+
55
+ def self.endpoint_for(uri)
56
+ path = uri.path
57
+ expected_path = D13n.config.alias_key_for(path)
58
+ return nil if expected_path.nil?
59
+ expected_path.to_s.downcase
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,15 @@
1
+ module D13n::Metric::HTTPClients
2
+ module HTTPHelper
3
+ def service
4
+ Helper.service_for(uri)
5
+ end
6
+
7
+ def endpoint
8
+ Helper.endpoint_for(uri)
9
+ end
10
+
11
+ def service_endpoint
12
+ [service, endpoint].join('.')
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,54 @@
1
+ require 'd13n/metric/http_clients/http_helper'
2
+ module D13n::Metric::HTTPClients
3
+ class NetHTTPClientRequest
4
+ def initialize(connection, request)
5
+ @connection = connection
6
+ @request = request
7
+ end
8
+
9
+ def type
10
+ 'Net::HTTP'
11
+ end
12
+
13
+ def host
14
+ if hostname = self['host']
15
+ hostname.split(':').first
16
+ else
17
+ @connection.address
18
+ end
19
+ end
20
+
21
+ def [](key)
22
+ @request[key]
23
+ end
24
+
25
+ def []=(key, value)
26
+ @request[key] = value
27
+ end
28
+
29
+ def uri
30
+ case @request.path
31
+ when /^https?:\/\//
32
+ URI(@request.path)
33
+ else
34
+ scheme = @connection.use_ssl? ? 'https' : 'http'
35
+ URI("#{scheme}://#{@connection.address}:#{@connection.port}#{@request.path}")
36
+ end
37
+ end
38
+ end
39
+
40
+ class NetHTTPClientResponse
41
+ def initialize(connection, response)
42
+ @response = response
43
+ end
44
+
45
+ def uri
46
+ return @response.uri unless @response.uri.nil?
47
+ nil
48
+ end
49
+
50
+ def status_code
51
+ @response.code
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,4 @@
1
+ module D13n::Metric::HTTPClients
2
+ end
3
+ require 'd13n/metric/http_clients/net_http_wrappers'
4
+
@@ -0,0 +1,70 @@
1
+ module D13n::Metric::Instrumentation
2
+ module AppException
3
+ def self.included(descendance)
4
+ descendance.include(InstanceMethods)
5
+ descendance.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def metric_error_inherated?
10
+ !!(self < D13n::Metric::MetricError)
11
+ end
12
+
13
+ def exception_with_d13n_instrumentation(*args)
14
+ return exception_without_d13n_instrumentation(*args) unless metric_error_inherated?
15
+
16
+ manager = D13n::Metric::Manager.instance
17
+ metric = manager.metric(:app_state)
18
+
19
+ if metric.nil?
20
+ D13n.logger.info "Null intrumentation metric class and ignore collection"
21
+ return exception_without_d13n_instrumentation(*args)
22
+ end
23
+
24
+ metric.instance(manager, {type: 'exception', at: 'runtime', src: 'app'}).process do
25
+ exception_without_d13n_instrumentation(*args)
26
+ end
27
+ end
28
+ end
29
+
30
+ module InstanceMethods
31
+ def exception_with_d13n_instrumentation(*args)
32
+ self.class.exception_with_d13n_instrumentation(*args)
33
+ end
34
+ end
35
+
36
+ module_function
37
+ def enable?
38
+ D13n.config[:'metric.app.state.exception.enable'] == 'true' || D13n.config[:'metric.app.state.exception.enable'] == true
39
+ end
40
+ end
41
+ end
42
+
43
+ D13n::Metric::Instrumentation::Conductor.direct do
44
+ named :app_exception
45
+
46
+ depend_on do
47
+ D13n::Metric::Instrumentation::AppException.enable?
48
+ end
49
+
50
+ depend_on do
51
+ defined?(D13n) && defined?(D13n::Error)
52
+ end
53
+
54
+ performances do
55
+ D13n.logger.info 'Installing Application Exeception instrumentation'
56
+ end
57
+
58
+ performances do
59
+ class D13n::Error
60
+ include D13n::Metric::AppException
61
+ class << self
62
+ alias exception_without_d13n_instrumentation exception
63
+ alias exception exception_with_d13n_instrumentation
64
+ end
65
+
66
+ alias exception_without_d13n_instrumentation exception
67
+ alias exception exception_with_d13n_instrumentation
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,91 @@
1
+ require 'd13n/metric/stream'
2
+ require 'd13n/metric/stream_state'
3
+ module D13n::Metric::Instrumentation
4
+ module ControllerInstrumentation
5
+ def perform_action_with_d13n_stream(*args, &block)
6
+ return yield unless ::D13n::Metric::Helper.http_in_tracable?
7
+ state = D13n::Metric::StreamState.st_get
8
+ state.request = metric_request(args)
9
+
10
+ trace_options = args.last.is_a?(Hash) ? args.last : {}
11
+ category = trace_options[:category] || :action
12
+ stream_options = create_stream_options(trace_options, category, state)
13
+ begin
14
+ stream = D13n::Metric::Stream.start(state, category, stream_options)
15
+
16
+ begin
17
+ yield
18
+ rescue => e
19
+ D13n::Metric::Manager.notice_error(e)
20
+ raise
21
+ end
22
+ ensure
23
+ D13n::Metric::Stream.stop(state)
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def create_stream_options(trace_options, category, state)
30
+ stream_options = {}
31
+ stream_options[:request] = trace_options[:request]
32
+ stream_options[:request] ||= request if respond_to?(:request) rescue nil
33
+ stream_options[:filtered_params] = trace_options[:params]
34
+ stream_options[:stream_name] = StreamNamer.name_for(nil, self, category, stream_options)
35
+ stream_options
36
+ end
37
+
38
+ def metric_request(args)
39
+ opts = args.first
40
+ if opts.respond_to?(:keys) && opts.respond_to?(:[]) && opts[:request]
41
+ opts[:request]
42
+ else self.respond_to?(:request)
43
+ self.request rescue nil
44
+ end
45
+ end
46
+
47
+ class StreamNamer
48
+ def self.name_for(stream, trace_obj, category, options={})
49
+ "#{prefix_for_category(stream, category)}.#{namespace(trace_obj, options)}"
50
+ end
51
+
52
+ def self.prefix_for_category(stream, category = nil)
53
+ category ||= (stream && stream.category)
54
+ case category
55
+ when :sinatra then ::D13n::Metric::Stream::SINATRA_PREFIX
56
+ when :middleware then ::D13n::Metric::Stream::MIDDLEWARE_PREFIX
57
+ else "#{category.to_s}"
58
+ end
59
+ end
60
+
61
+ def self.namespace(traced_obj, options={})
62
+ return options[:namespace] if options[:namespace]
63
+
64
+ kls_name = kls_name(traced_obj, options)
65
+ if options[:name]
66
+ if kls_name
67
+ "#{kls_name}.#{options[:name]}"
68
+ else
69
+ options[:name]
70
+ end
71
+ elsif traced_obj.respond_to?(:d13n_metric_namespace)
72
+ traced_obj.d13n_metric_namespace
73
+ else
74
+ kls_name
75
+ end
76
+ end
77
+
78
+ def self.kls_name(trace_obj, options={})
79
+ return options[:class_name] if options[:class_name]
80
+
81
+ if (trace_obj.is_a?(Class) || trace_obj.is_a?(Module))
82
+ return nil if trace_obj.name.nil?
83
+ trace_obj.name.underscore
84
+ else
85
+ return nil if trace_obj.class.name.nil?
86
+ trace_obj.class.name.underscore
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,71 @@
1
+ require 'd13n/metric/instrumentation/websocket_instrumentation'
2
+ D13n::Metric::Instrumentation::Conductor.direct do
3
+ named :'em-websocket'
4
+
5
+ depend_on do
6
+ defined?(::EventMachine) && defined?(::EventMachine::WebSocket) &&
7
+ defined?(::EventMachine::WebSocket::Connection) &&
8
+ ::EventMachine::WebSocket::Connection.instance_methods.include?(:onmessage) &&
9
+ ::EventMachine::WebSocket::Connection.instance_methods.include?(:onclose) &&
10
+ ::EventMachine::WebSocket::Connection.instance_methods.include?(:onopen)
11
+ end
12
+
13
+ performances do
14
+ D13n.logger.info 'Installing em-websocket instrumentation'
15
+ end
16
+
17
+ performances do
18
+ ::EventMachine::WebSocket::Connection.class_eval do
19
+ include D13n::Metric::Instrumentation::EmWebSocket
20
+ alias trigger_on_message_without_d13n_instrumentation trigger_on_message
21
+ alias trigger_on_open_without_d13n_instrumentation trigger_on_open
22
+ alias trigger_on_close_without_d13n_instrumentation trigger_on_close
23
+ alias send_without_d13n_instrumentation send
24
+
25
+ alias trigger_on_message trigger_on_message_with_d13n_instrumentation
26
+ alias trigger_on_open trigger_on_open_with_d13n_instrumentation
27
+ alias trigger_on_close trigger_on_close_with_d13n_instrumentation
28
+ alias send send_with_d13n_instrumentation
29
+ end
30
+ end
31
+ end
32
+
33
+ module D13n::Metric::Instrumentation
34
+ module EmWebSocket
35
+ include D13n::Metric::Instrumentation::WebSocketInstrumentation
36
+
37
+ def self.included(descendance)
38
+ descendance.extend(ClassMethods)
39
+ end
40
+
41
+ module ClassMethods
42
+
43
+ end
44
+
45
+ def trigger_on_message_with_d13n_instrumentation(*args, &block)
46
+ options = {:category => :websocket, :name => :websocket_onmessage}
47
+ request[:request_content_length] = args[0].size if args.is_a?(Array)
48
+
49
+ perform_websocket_with_d13n_stream(options) do
50
+ trigger_on_message_without_d13n_instrumentation(*args, &block)
51
+ end
52
+ end
53
+
54
+ def send_with_d13n_instrumentation(*args, &block)
55
+ response_length = args[0].size if args.is_a?(Array)
56
+ request[:response_content_length] = response_length || 0 if request.is_a?(Hash)
57
+ send_without_d13n_instrumentation(*args, &block)
58
+ end
59
+
60
+ def trigger_on_open_with_d13n_instrumentation(*args, &block)
61
+ trigger_on_open_without_d13n_instrumentation(*args, &block)
62
+ end
63
+
64
+ def trigger_on_close_with_d13n_instrumentation(*args, &block)
65
+ trigger_on_close_without_d13n_instrumentation(*args, &block)
66
+ end
67
+ end
68
+ end
69
+
70
+
71
+