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
data/lib/d13n/logger.rb
ADDED
@@ -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,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,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
|
+
|