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.
- 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,65 @@
|
|
1
|
+
module D13n::Metric::Instrumentation
|
2
|
+
module Exception
|
3
|
+
def self.included(descendance)
|
4
|
+
descendance.include(InstanceMethods)
|
5
|
+
descendance.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
module ClassMethods
|
8
|
+
def d13n_error_inherated?
|
9
|
+
!!(self < D13n::Error)
|
10
|
+
end
|
11
|
+
|
12
|
+
def exception_with_d13n_instrumentation(*arg)
|
13
|
+
return exception_without_d13n_instrumentation(*arg) if d13n_error_inherated?
|
14
|
+
|
15
|
+
manager = D13n::Metric::Manager.instance
|
16
|
+
metric = manager.metric(:app_state)
|
17
|
+
|
18
|
+
if metric.nil?
|
19
|
+
D13n.logger.info "Null intrumentation metric class and ignore collection"
|
20
|
+
return exception_without_d13n_instrumentation(*arg)
|
21
|
+
end
|
22
|
+
|
23
|
+
metric.instance(manager, {type: 'exception', at: 'runtime', src:'others'}).process do
|
24
|
+
exception_without_d13n_instrumentation(*arg)
|
25
|
+
end
|
26
|
+
return exception_without_d13n_instrumentation(*arg)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module InstanceMethods
|
31
|
+
def exception_with_d13n_instrumentation(*arg)
|
32
|
+
self.class.exception_with_d13n_instrumentation(*arg)
|
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
|
+
|
44
|
+
D13n::Metric::Instrumentation::Conductor.direct do
|
45
|
+
named :exception
|
46
|
+
|
47
|
+
depend_on do
|
48
|
+
D13n::Metric::Instrumentation::Exception.enable?
|
49
|
+
end
|
50
|
+
|
51
|
+
performances do
|
52
|
+
D13n.logger.info 'Installing Exeception instrumentation'
|
53
|
+
end
|
54
|
+
|
55
|
+
performances do
|
56
|
+
class StandardError
|
57
|
+
class << self
|
58
|
+
alias exception_without_d13n_instrumentation exception
|
59
|
+
alias exception exception_with_d13n_instrumentation
|
60
|
+
end
|
61
|
+
alias exception_without_d13n_instrumentation exception
|
62
|
+
alias exception exception_with_d13n_instrumentation
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module D13n::Metric::Instrumentation
|
2
|
+
module MiddlewareTracing
|
3
|
+
STREAM_STARTED_KEY = 'd13n.stream_started'.freeze unless defined?(STREAM_STARTED_KEY)
|
4
|
+
|
5
|
+
def call(env)
|
6
|
+
first_middleware = stream_started(env)
|
7
|
+
|
8
|
+
state = D13n::Metric::StreamState.st_get
|
9
|
+
|
10
|
+
begin
|
11
|
+
D13n::Metric::Stream.start(state, category, build_stream_options(env, first_middleware))
|
12
|
+
state.notify_rack_call(env) if first_middleware
|
13
|
+
result = (@target == self) ? traced_call(env) : @target.call(env)
|
14
|
+
|
15
|
+
if first_middleware
|
16
|
+
capture_response_attributes(state, result)
|
17
|
+
end
|
18
|
+
|
19
|
+
result
|
20
|
+
rescue Exception => e
|
21
|
+
D13n.logger.error(e)
|
22
|
+
raise e
|
23
|
+
ensure
|
24
|
+
D13n::Metric::Stream.stop(state)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def capture_response_code(state, result)
|
29
|
+
|
30
|
+
if result.is_a?(Array) && state.current_stream
|
31
|
+
state.current_stream.http_response_code = result[0]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
CONTENT_TYPE = 'Content-Type'.freeze unless defined?(CONTENT_TYPE)
|
36
|
+
|
37
|
+
def capture_response_content_type(state, result)
|
38
|
+
if result.is_a?(Array) && state.current_stream
|
39
|
+
_, headers, _ = result
|
40
|
+
state.current_stream.response_content_type = headers[CONTENT_TYPE]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
CONTENT_LENGTH = 'Content-Length'.freeze unless defined?(CONTENT_LENGTH)
|
45
|
+
|
46
|
+
def capture_response_content_length(state, result)
|
47
|
+
if result.is_a?(Array) && state.current_stream
|
48
|
+
_, headers, _ = result
|
49
|
+
state.current_stream.response_content_length = headers[CONTENT_LENGTH]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def capture_response_attributes(state, result)
|
54
|
+
capture_response_code(state, result)
|
55
|
+
capture_response_content_type(state, result)
|
56
|
+
capture_response_content_length(state, result)
|
57
|
+
end
|
58
|
+
#
|
59
|
+
# stream_name, apdex_started_at, request
|
60
|
+
#
|
61
|
+
|
62
|
+
def build_stream_options(env, first_middleware)
|
63
|
+
opts = @stream_options
|
64
|
+
opts = merge_first_middleware_options(opts, env) if first_middleware
|
65
|
+
opts
|
66
|
+
end
|
67
|
+
|
68
|
+
def merge_first_middleware_options(opts, env)
|
69
|
+
opts[:apdex_started_at] = parse_request_timestamp(env)
|
70
|
+
opts[:request] = ::Rack::Request.new(env) if defined?(::Rack)
|
71
|
+
opts
|
72
|
+
end
|
73
|
+
|
74
|
+
def parse_request_timestamp(env)
|
75
|
+
Time.now.to_f
|
76
|
+
end
|
77
|
+
|
78
|
+
def stream_started(env)
|
79
|
+
env[STREAM_STARTED_KEY] = true unless env[STREAM_STARTED_KEY]
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
D13n::Metric::Instrumentation::Conductor.direct do
|
3
|
+
named :net_http
|
4
|
+
|
5
|
+
depend_on do
|
6
|
+
defined?(Net) && defined?(Net::HTTP)
|
7
|
+
end
|
8
|
+
|
9
|
+
performances do
|
10
|
+
D13n.logger.info 'Installing Net instrumentation'
|
11
|
+
require 'd13n/metric/http_clients/net_http_wrappers'
|
12
|
+
end
|
13
|
+
|
14
|
+
performances do
|
15
|
+
class Net::HTTP
|
16
|
+
def request_with_d13n_instrumentation(request, *args, &block)
|
17
|
+
return request_without_d13n_instrumentation(request, *args, &block) unless started?
|
18
|
+
wrapped_request = D13n::Metric::HTTPClients::NetHTTPClientRequest.new(self, request)
|
19
|
+
manager = D13n::Metric::Manager.instance
|
20
|
+
metric = manager.metric(:app_http)
|
21
|
+
|
22
|
+
if metric.nil?
|
23
|
+
D13n.logger.info "Null intrumentation metric class and ignore collection"
|
24
|
+
return request_without_d13n_instrumentation(request, *args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
metric.instance(manager, direction: 'out').process(wrapped_request) do
|
28
|
+
request_without_d13n_instrumentation(request, *args, &block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
alias request_without_d13n_instrumentation request
|
33
|
+
alias request request_with_d13n_instrumentation
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module D13n::Metric::Instrumentation::Sinatra
|
2
|
+
module StreamNamer
|
3
|
+
extend self
|
4
|
+
|
5
|
+
SINATRA_ROUTE = 'sinatra.route'
|
6
|
+
UNKNOWN = 'unknown'.freeze
|
7
|
+
def for_route(env, request)
|
8
|
+
env[SINATRA_ROUTE]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initial_stream_name(request)
|
12
|
+
stream_name(UNKNOWN, request)
|
13
|
+
end
|
14
|
+
|
15
|
+
ROOT = '.'.freeze
|
16
|
+
|
17
|
+
|
18
|
+
def stream_name(route_text, request)
|
19
|
+
verb = http_verb(request)
|
20
|
+
|
21
|
+
route_text = route_text.source if route_text.is_a?(Regexp)
|
22
|
+
name = route_text.gsub(%r{^[/^\\A]*(.*?)[/\$\?\\z]*$}, '\1')
|
23
|
+
name = ROOT if name.empty?
|
24
|
+
name = "#{verb}#{name}" unless verb.nil?
|
25
|
+
name
|
26
|
+
rescue => e
|
27
|
+
::D13n.logger.debug("#{e.class} : #{e.message} - Error encountered trying to identify Sinatra transaction name")
|
28
|
+
UNKNOWN
|
29
|
+
end
|
30
|
+
|
31
|
+
def http_verb(request)
|
32
|
+
request.request_method if request.respond_to?(:request_method)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'd13n/metric/instrumentation/controller_instrumentation'
|
2
|
+
require 'd13n/metric/instrumentation/sinatra/stream_namer'
|
3
|
+
require 'd13n/rack/metric_middleware'
|
4
|
+
D13n::Metric::Instrumentation::Conductor.direct do
|
5
|
+
named :sinatra
|
6
|
+
|
7
|
+
depend_on do
|
8
|
+
D13n.config[:'metric.app.http.in.sinatra.enable'] &&
|
9
|
+
defined?(::Sinatra) && defined?(::Sinatra::Base) &&
|
10
|
+
Sinatra::Base.private_method_defined?(:dispatch!) &&
|
11
|
+
Sinatra::Base.private_method_defined?(:process_route) &&
|
12
|
+
Sinatra::Base.private_method_defined?(:route_eval)
|
13
|
+
end
|
14
|
+
|
15
|
+
performances do
|
16
|
+
D13n.logger.info 'Installing Sinatra instrumentation'
|
17
|
+
end
|
18
|
+
|
19
|
+
performances do
|
20
|
+
::Sinatra::Base.class_eval do
|
21
|
+
include D13n::Metric::Instrumentation::Sinatra
|
22
|
+
alias dispatch_without_d13n_instrumentation dispatch!
|
23
|
+
alias dispatch! dispatch_with_d13n_instrumentation
|
24
|
+
|
25
|
+
alias process_route_without_d13n_instrumentation process_route
|
26
|
+
alias process_route process_route_with_d13n_instrumentation
|
27
|
+
|
28
|
+
alias route_eval_without_d13n_instrumentation route_eval
|
29
|
+
alias route_eval route_eval_with_d13n_instrumentation
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
performances do
|
35
|
+
if Sinatra::Base.respond_to?(:build)
|
36
|
+
require 'd13n/rack/metric_middleware'
|
37
|
+
|
38
|
+
::Sinatra::Base.class_eval do
|
39
|
+
class << self
|
40
|
+
alias build_without_d13n_instrumentation build
|
41
|
+
alias build build_with_d13n_instrumentation
|
42
|
+
end
|
43
|
+
end
|
44
|
+
else
|
45
|
+
D13n.logger.info("Skipping auto-injection of middleware for Sinatra - require Sinatra 1.2.1+")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
performances do
|
50
|
+
if defined?(::SinatraWebsocket) &&
|
51
|
+
defined?(::Sinatra::Request) &&
|
52
|
+
Sinatra::Request.respond_to?(:websocket)
|
53
|
+
::Sinatra::Base.class_eval do
|
54
|
+
class << self
|
55
|
+
alias websocket_without_d13n_instrumentation websocket
|
56
|
+
alias websocket websocket_with_d13n_instrumentation
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module D13n::Metric::Instrumentation
|
64
|
+
module Sinatra
|
65
|
+
include D13n::Metric::Instrumentation::ControllerInstrumentation
|
66
|
+
|
67
|
+
def self.included(descendance)
|
68
|
+
descendance.extend(ClassMethods)
|
69
|
+
end
|
70
|
+
|
71
|
+
module ClassMethods
|
72
|
+
def d13n_middlewares
|
73
|
+
middlewares = []
|
74
|
+
if D13n::Rack::MetricMiddleware.enabled?
|
75
|
+
middlewares << D13n::Rack::MetricMiddleware
|
76
|
+
end
|
77
|
+
middlewares
|
78
|
+
end
|
79
|
+
|
80
|
+
def websocket_with_d13n_instrumentation(*args, &block)
|
81
|
+
websocket_without_d13n_instrumentation(*args, &block)
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_with_d13n_instrumentation(*args, &block)
|
85
|
+
if auto_middleware_enable?
|
86
|
+
d13n_middlewares.each do |middleware_kls|
|
87
|
+
try_to_use(self, middleware_kls)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
build_without_d13n_instrumentation(*args, &block)
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def auto_middleware_enable?
|
97
|
+
D13n.config[:'metric.app.http.in.sinatra.auto_middleware.enable']
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
def try_to_use(app, clazz)
|
102
|
+
if app.middleware.nil?
|
103
|
+
D13n.logger.debug("Failed to use middle for middleware missing in app")
|
104
|
+
return nil
|
105
|
+
end
|
106
|
+
has_middleware = app.middleware.any? { |info| info[0] == clazz }
|
107
|
+
app.use(clazz) unless has_middleware
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def process_route_with_d13n_instrumentation(*args, &block)
|
112
|
+
begin
|
113
|
+
env["d13n.last_route"] = args[0]
|
114
|
+
rescue => e
|
115
|
+
D13n.logger.debug("Failed determining last route in Sinatra", e)
|
116
|
+
end
|
117
|
+
|
118
|
+
process_route_without_d13n_instrumentation(*args, &block)
|
119
|
+
end
|
120
|
+
|
121
|
+
def route_eval_with_d13n_instrumentation(*args, &block)
|
122
|
+
begin
|
123
|
+
stream_name = StreamNamer.for_route(env, request)
|
124
|
+
|
125
|
+
unless stream_name.nil?
|
126
|
+
::D13n::Metric::Stream.set_default_stream_name("#{self.class.name}.#{stream_name}", :sinatra)
|
127
|
+
end
|
128
|
+
rescue => e
|
129
|
+
D13n.logger.debug("Failed during route_eval to set stream name", e)
|
130
|
+
end
|
131
|
+
|
132
|
+
route_eval_without_d13n_instrumentation(*args, &block)
|
133
|
+
end
|
134
|
+
|
135
|
+
def dispatch_with_d13n_instrumentation
|
136
|
+
request_params = get_request_params
|
137
|
+
name = StreamNamer.initial_stream_name(request)
|
138
|
+
filter_params = get_filter_parames(request_params)
|
139
|
+
perform_action_with_d13n_stream(:category => :sinatra,
|
140
|
+
:name => name,
|
141
|
+
:params => filter_params) do
|
142
|
+
dispatch_and_notice_errors_with_d13n_instrumentation
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def dispatch_and_notice_errors_with_d13n_instrumentation
|
147
|
+
dispatch_without_d13n_instrumentation
|
148
|
+
ensure
|
149
|
+
had_error = env.has_key?('sinatra.error')
|
150
|
+
::D13n::Metric::Manager.notice_error(env['sinatra.error']) if had_error
|
151
|
+
end
|
152
|
+
|
153
|
+
def get_request_params
|
154
|
+
begin
|
155
|
+
@request.params
|
156
|
+
rescue => e
|
157
|
+
D13n.logger.debug("Failed to get params from Rack request.", e)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def get_filter_parames(request_params)
|
162
|
+
request_params
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'd13n/metric/stream'
|
2
|
+
require 'd13n/metric/stream_state'
|
3
|
+
module D13n::Metric::Instrumentation
|
4
|
+
module WebSocketInstrumentation
|
5
|
+
def perform_websocket_with_d13n_stream(*args, &block)
|
6
|
+
state = D13n::Metric::StreamState.st_get
|
7
|
+
category = :websocket
|
8
|
+
|
9
|
+
trace_options = args.last.is_a?(Hash) ? args.last : {}
|
10
|
+
stream_options = create_stream_options(trace_options, category, state)
|
11
|
+
|
12
|
+
begin
|
13
|
+
stream = D13n::Metric::Stream.start(state, category, stream_options)
|
14
|
+
|
15
|
+
begin
|
16
|
+
yield
|
17
|
+
update_stream_data(state)
|
18
|
+
rescue => e
|
19
|
+
D13n::Metric::Manager.notice_error(e)
|
20
|
+
raise
|
21
|
+
ensure
|
22
|
+
D13n::Metric::Stream.stop(state)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def create_stream_options(trace_options, categroy, state)
|
29
|
+
stream_options = {}
|
30
|
+
stream_options[:stream_name]
|
31
|
+
stream_options
|
32
|
+
end
|
33
|
+
|
34
|
+
def update_stream_data(state)
|
35
|
+
stream = state.current_stream
|
36
|
+
stream.http_response_code = 200
|
37
|
+
stream.request_content_length = request.delete(:request_content_length)
|
38
|
+
stream.response_content_type = "websocket"
|
39
|
+
stream.response_content_length = request.delete(:response_content_length)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'd13n/metric/conductor'
|
2
|
+
module D13n::Metric::Instrumentation
|
3
|
+
def load_instrumentation_files path
|
4
|
+
Dir.glob(path) do |file|
|
5
|
+
begin
|
6
|
+
require file.to_s
|
7
|
+
rescue => e
|
8
|
+
D13n.logger.warn "Error loading instrumentation file '#{file}':", e
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_instrumentation file
|
14
|
+
if @instrumented
|
15
|
+
load_instrumentation_files file
|
16
|
+
else
|
17
|
+
@instrumentation_files << file
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup_instrumentation
|
22
|
+
_setup_instrumentation
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def _setup_instrumentation
|
27
|
+
return if @instrumented
|
28
|
+
|
29
|
+
@instrumentation_files = []
|
30
|
+
|
31
|
+
@instrumented = true
|
32
|
+
|
33
|
+
instrumentation_path = File.expand_path(File.join(File.dirname(__FILE__), 'instrumentation'))
|
34
|
+
|
35
|
+
@instrumentation_files << File.join(instrumentation_path, '*.rb')
|
36
|
+
|
37
|
+
@instrumentation_files.each { |path| load_instrumentation_files(path) }
|
38
|
+
Conductor.perform!
|
39
|
+
D13n.logger.info "Finished instrumentation"
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'statsd-instrument'
|
2
|
+
require 'd13n/metric/metrics'
|
3
|
+
require 'd13n/metric/instrumentation'
|
4
|
+
require 'd13n/metric/stream'
|
5
|
+
module D13n::Metric
|
6
|
+
class MetricInitError < MetricError;end
|
7
|
+
class MetricArgError < MetricError; end
|
8
|
+
class MetricNotFoundError < MetricError; end
|
9
|
+
class InstrumentInitError < MetricError; end
|
10
|
+
class Manager
|
11
|
+
include D13n::Metric::Instrumentation
|
12
|
+
def self.start(channel='logger', opts={})
|
13
|
+
@instance ||= new(channel, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.instance
|
17
|
+
@instance || start
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.notice_error(exception, opts={})
|
21
|
+
Stream.notice_error(exception, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
extend Forwardable
|
25
|
+
|
26
|
+
def_delegators StatsD, :measure, :increment, :gauge, :set
|
27
|
+
|
28
|
+
CHANNELS = ['udp', 'logger', 'null']
|
29
|
+
|
30
|
+
METRIC_MAPPING = {
|
31
|
+
'app_state' => AppStateMetric,
|
32
|
+
'app_http' => AppHttpMetric,
|
33
|
+
'app_database' => AppDatabaseMetric,
|
34
|
+
'biz_state' => BizStateMetric
|
35
|
+
}
|
36
|
+
|
37
|
+
attr_reader :channel, :backend
|
38
|
+
|
39
|
+
def initialize(channel, opts={})
|
40
|
+
self.channel = channel
|
41
|
+
@opts = opts
|
42
|
+
set_backend
|
43
|
+
setup_instrumentation
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_backend
|
47
|
+
@backend = if @channel == 'udp'
|
48
|
+
setup_udp_backend
|
49
|
+
elsif @channel == 'logger'
|
50
|
+
setup_logger_backend
|
51
|
+
else @channel == 'null'
|
52
|
+
setup_null_backend
|
53
|
+
end
|
54
|
+
D13n.logger.info "Using #{@backend.to_s} as channel in metric"
|
55
|
+
StatsD.backend = @backend
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_udp_backend
|
59
|
+
@host = @opts.fetch(:host, default_host)
|
60
|
+
@port = @opts.fetch(:port, default_port)
|
61
|
+
@backend_uri = "#{@host}:#{@port}"
|
62
|
+
@protocol = @opts.fetch(:protocol, default_protocol)
|
63
|
+
StatsD::Instrument::Backends::UDPBackend.new(@backend_uri, @protocol)
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_logger_backend
|
67
|
+
@logger = @opts.fetch(:logger, D13n.logger)
|
68
|
+
raise InstrumentInitError.new "Missing Logger for logger backend" if @logger.nil?
|
69
|
+
StatsD::Instrument::Backends::LoggerBackend.new(@logger)
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup_null_backend
|
73
|
+
StatsD::Instrument::Backends::NullBackend.new
|
74
|
+
end
|
75
|
+
|
76
|
+
def channel=(c)
|
77
|
+
@channel = c.to_s.downcase
|
78
|
+
raise MetricArgError.new("Invalid Instrument channel: #{c}") unless CHANNELS.include?(@channel)
|
79
|
+
end
|
80
|
+
|
81
|
+
def metric(type)
|
82
|
+
metric_for(type)
|
83
|
+
rescue MetricNotFoundError => e
|
84
|
+
D13n.logger.error "Instrument Metric Type #{type} Not Found in [#{METRIC_MAPPING.keys.join(',')}]"
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def metric_for(type)
|
89
|
+
expected_metric = METRIC_MAPPING[type.to_s.downcase]
|
90
|
+
raise MetricNotFoundError.new "#{type} of metric not found!" if expected_metric.nil?
|
91
|
+
expected_metric
|
92
|
+
end
|
93
|
+
|
94
|
+
def default_host
|
95
|
+
D13n.config[:'service.metric.host'] || 'localhost'
|
96
|
+
end
|
97
|
+
|
98
|
+
def default_port
|
99
|
+
D13n.config[:'service.metric.port'] || 8125
|
100
|
+
end
|
101
|
+
|
102
|
+
def default_protocol
|
103
|
+
D13n.config[:'service.metric.protocol'] || :datadog
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|