stackify-ruby-apm 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +38 -0
- data/.ruby-version +1 -0
- data/Gemfile +17 -11
- data/Gemfile.lock +98 -95
- data/Rakefile +7 -5
- data/docker/stackify-ruby +8 -0
- data/docker/stackify-ruby-rvm +10 -0
- data/docker/stackify-ruby-test +28 -0
- data/lib/{stackify → stackify_apm}/agent.rb +42 -33
- data/lib/{stackify → stackify_apm}/config.rb +56 -39
- data/lib/{stackify → stackify_apm}/context.rb +5 -6
- data/lib/{stackify → stackify_apm}/context/request.rb +0 -0
- data/lib/{stackify → stackify_apm}/context/request/socket.rb +0 -0
- data/lib/{stackify → stackify_apm}/context/request/url.rb +2 -6
- data/lib/stackify_apm/context/response.rb +33 -0
- data/lib/{stackify → stackify_apm}/context_builder.rb +2 -5
- data/lib/{stackify → stackify_apm}/error.rb +7 -6
- data/lib/stackify_apm/error/exception.rb +37 -0
- data/lib/stackify_apm/error/log.rb +24 -0
- data/lib/stackify_apm/error_builder.rb +61 -0
- data/lib/stackify_apm/helper/database_helper.rb +27 -0
- data/lib/{stackify → stackify_apm}/instrumenter.rb +12 -19
- data/lib/{stackify → stackify_apm}/internal_error.rb +0 -0
- data/lib/{stackify → stackify_apm}/log.rb +0 -0
- data/lib/{stackify → stackify_apm}/logger/log_device.rb +22 -11
- data/lib/{stackify → stackify_apm}/logger/logger_high_version.rb +1 -6
- data/lib/{stackify → stackify_apm}/logger/logger_lower_version.rb +2 -1
- data/lib/stackify_apm/middleware.rb +70 -0
- data/lib/{stackify → stackify_apm}/naively_hashable.rb +1 -3
- data/lib/{stackify → stackify_apm}/normalizers.rb +3 -2
- data/lib/{stackify → stackify_apm}/normalizers/action_controller.rb +0 -0
- data/lib/{stackify → stackify_apm}/normalizers/action_mailer.rb +0 -0
- data/lib/{stackify → stackify_apm}/normalizers/action_view.rb +0 -0
- data/lib/{stackify → stackify_apm}/normalizers/active_record.rb +3 -25
- data/lib/{stackify → stackify_apm}/railtie.rb +5 -7
- data/lib/{stackify → stackify_apm}/root_info.rb +2 -6
- data/lib/{stackify → stackify_apm}/serializers.rb +3 -2
- data/lib/{stackify → stackify_apm}/serializers/errors.rb +7 -10
- data/lib/{stackify → stackify_apm}/serializers/transactions.rb +11 -18
- data/lib/{stackify → stackify_apm}/span.rb +8 -9
- data/lib/{stackify → stackify_apm}/span/context.rb +3 -1
- data/lib/{stackify → stackify_apm}/spies.rb +3 -2
- data/lib/{stackify → stackify_apm}/spies/action_dispatch.rb +3 -4
- data/lib/stackify_apm/spies/curb.rb +49 -0
- data/lib/stackify_apm/spies/curb/easy.rb +157 -0
- data/lib/stackify_apm/spies/curb/multi.rb +43 -0
- data/lib/{stackify → stackify_apm}/spies/httpclient.rb +10 -8
- data/lib/{stackify → stackify_apm}/spies/httprb.rb +7 -9
- data/lib/{stackify → stackify_apm}/spies/mongo.rb +5 -3
- data/lib/{stackify → stackify_apm}/spies/net_http.rb +4 -5
- data/lib/{stackify → stackify_apm}/spies/redis.rb +19 -18
- data/lib/stackify_apm/spies/sequel.rb +65 -0
- data/lib/{stackify → stackify_apm}/spies/sinatra.rb +7 -10
- data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +201 -0
- data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +94 -0
- data/lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb +46 -0
- data/lib/stackify_apm/spies/stackify_logger.rb +60 -0
- data/lib/{stackify → stackify_apm}/spies/tilt.rb +3 -3
- data/lib/stackify_apm/stacktrace.rb +18 -0
- data/lib/stackify_apm/stacktrace/frame.rb +47 -0
- data/lib/{stackify → stackify_apm}/stacktrace_builder.rb +10 -11
- data/lib/{stackify → stackify_apm}/subscriber.rb +20 -14
- data/lib/{stackify → stackify_apm}/trace_logger.rb +10 -16
- data/lib/stackify_apm/transaction.rb +127 -0
- data/lib/{stackify → stackify_apm}/util.rb +3 -1
- data/lib/{stackify → stackify_apm}/util/dig.rb +1 -1
- data/lib/{stackify → stackify_apm}/util/inflector.rb +0 -0
- data/lib/{stackify → stackify_apm}/util/inspector.rb +1 -3
- data/lib/stackify_apm/util/lru_cache.rb +49 -0
- data/lib/stackify_apm/util/trace_log_watcher.rb +37 -0
- data/lib/stackify_apm/version.rb +6 -0
- data/lib/{stackify → stackify_apm}/worker.rb +8 -7
- data/lib/stackify_ruby_apm.rb +18 -15
- data/run-test-docker.sh +50 -0
- data/run-test.sh +1 -3
- data/stackify-ruby-apm.gemspec +14 -11
- metadata +86 -59
- data/lib/stackify/context/response.rb +0 -37
- data/lib/stackify/error/exception.rb +0 -36
- data/lib/stackify/error/log.rb +0 -25
- data/lib/stackify/error_builder.rb +0 -65
- data/lib/stackify/middleware.rb +0 -74
- data/lib/stackify/spies/sinatra_activerecord/mysql_adapter.rb +0 -177
- data/lib/stackify/spies/sinatra_activerecord/postgresql_adapter.rb +0 -96
- data/lib/stackify/spies/sinatra_activerecord/sqlite_adapter.rb +0 -48
- data/lib/stackify/stacktrace.rb +0 -19
- data/lib/stackify/stacktrace/frame.rb +0 -50
- data/lib/stackify/transaction.rb +0 -132
- data/lib/stackify/util/lru_cache.rb +0 -49
- data/lib/stackify/version.rb +0 -4
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
3
|
# This class builds the context of the Transaction/Span
|
4
4
|
# Context represents the HTTP request information such as headers, cookies, body.
|
5
|
-
#
|
6
5
|
|
7
6
|
module StackifyRubyAPM
|
8
7
|
# @api private
|
@@ -19,8 +18,6 @@ module StackifyRubyAPM
|
|
19
18
|
|
20
19
|
private
|
21
20
|
|
22
|
-
# rubocop:disable Metrics/AbcSize
|
23
|
-
#
|
24
21
|
# Request format and values are assigned to context
|
25
22
|
#
|
26
23
|
def apply_to_request(context, rack_env)
|
@@ -36,7 +33,6 @@ module StackifyRubyAPM
|
|
36
33
|
|
37
34
|
context
|
38
35
|
end
|
39
|
-
# rubocop:enable Metrics/AbcSize
|
40
36
|
|
41
37
|
def get_body(req)
|
42
38
|
return req.POST if req.form_data?
|
@@ -73,6 +69,7 @@ module StackifyRubyAPM
|
|
73
69
|
|
74
70
|
def build_http_version(rack_env)
|
75
71
|
return unless (http_version = rack_env['HTTP_VERSION'])
|
72
|
+
|
76
73
|
http_version.gsub(%r{HTTP/}, '')
|
77
74
|
end
|
78
75
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
4
|
-
require '
|
5
|
-
require '
|
6
|
-
require '
|
3
|
+
require 'stackify_apm/stacktrace'
|
4
|
+
require 'stackify_apm/context'
|
5
|
+
require 'stackify_apm/error/exception'
|
6
|
+
require 'stackify_apm/error/log'
|
7
7
|
|
8
8
|
module StackifyRubyAPM
|
9
9
|
# @api private
|
@@ -11,8 +11,9 @@ module StackifyRubyAPM
|
|
11
11
|
def initialize(culprit: nil)
|
12
12
|
@id = SecureRandom.uuid
|
13
13
|
@culprit = culprit
|
14
|
+
time_now = Time.now
|
14
15
|
|
15
|
-
@timestamp =
|
16
|
+
@timestamp = time_now.to_f * 1000
|
16
17
|
@context = Context.new
|
17
18
|
|
18
19
|
@transaction_id = nil
|
@@ -21,4 +22,4 @@ module StackifyRubyAPM
|
|
21
22
|
attr_accessor :id, :culprit, :exception, :log, :transaction_id, :context
|
22
23
|
attr_reader :timestamp
|
23
24
|
end
|
24
|
-
end
|
25
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
class Error
|
5
|
+
# @api private
|
6
|
+
class Exception
|
7
|
+
MOD_SPLIT = '::'.freeze
|
8
|
+
|
9
|
+
def initialize(exception, **attrs)
|
10
|
+
@message =
|
11
|
+
"#{exception.class}: #{exception.message}"
|
12
|
+
@type = exception.class.to_s
|
13
|
+
@module = format_module exception
|
14
|
+
|
15
|
+
attrs.each do |key, val|
|
16
|
+
send(:"#{key}=", val)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor(
|
21
|
+
:attributes,
|
22
|
+
:code,
|
23
|
+
:handled,
|
24
|
+
:message,
|
25
|
+
:module,
|
26
|
+
:stacktrace,
|
27
|
+
:type
|
28
|
+
)
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def format_module(exception)
|
33
|
+
exception.class.to_s.split(MOD_SPLIT)[0...-1].join(MOD_SPLIT)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
class Error
|
5
|
+
# @api private
|
6
|
+
class Log
|
7
|
+
def initialize(message, attrs = {})
|
8
|
+
@message = message
|
9
|
+
|
10
|
+
attrs.each do |key, val|
|
11
|
+
send(:"#{key}=", val)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
attr_accessor(
|
16
|
+
:level,
|
17
|
+
:logger_name,
|
18
|
+
:message,
|
19
|
+
:param_message,
|
20
|
+
:stacktrace
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# This module build errors/exceptions and the Frames/stacktraces affected/related to the error
|
4
|
+
|
5
|
+
module StackifyRubyAPM
|
6
|
+
# @api private
|
7
|
+
class ErrorBuilder
|
8
|
+
def initialize(agent)
|
9
|
+
@agent = agent
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_exception(exception, handled: true)
|
13
|
+
error = Error.new
|
14
|
+
error.exception = Error::Exception.new(exception, handled: handled)
|
15
|
+
|
16
|
+
if exception.backtrace
|
17
|
+
add_stacktrace error, :exception, exception.backtrace
|
18
|
+
end
|
19
|
+
|
20
|
+
add_transaction_id error
|
21
|
+
|
22
|
+
if (transaction = StackifyRubyAPM.current_transaction)
|
23
|
+
error.context = transaction.context.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
error
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_log(message, backtrace: nil, **attrs)
|
30
|
+
error = Error.new
|
31
|
+
error.log = Error::Log.new(message, **attrs)
|
32
|
+
|
33
|
+
add_stacktrace error, :log, backtrace if backtrace
|
34
|
+
add_transaction_id error
|
35
|
+
|
36
|
+
error
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def add_stacktrace(error, kind, backtrace)
|
42
|
+
stacktrace =
|
43
|
+
@agent.stacktrace_builder.build(backtrace, :error)
|
44
|
+
return unless stacktrace
|
45
|
+
|
46
|
+
case kind
|
47
|
+
when :exception
|
48
|
+
error.exception.stacktrace = stacktrace
|
49
|
+
when :log
|
50
|
+
error.log.stacktrace = stacktrace
|
51
|
+
end
|
52
|
+
|
53
|
+
error.culprit = stacktrace.frames.first.function
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_transaction_id(error)
|
57
|
+
return unless (transaction = StackifyRubyAPM.current_transaction)
|
58
|
+
error.transaction_id = transaction.id
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# get_profiler - It will return the database driver of the Object.
|
4
|
+
#
|
5
|
+
module DatabaseHelper
|
6
|
+
# return back valid PROVIDER based on driver name passed in
|
7
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
8
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
9
|
+
def get_profiler(driver)
|
10
|
+
if driver.to_s.empty?
|
11
|
+
'generic'
|
12
|
+
elsif driver.include? 'mysql'
|
13
|
+
'mysql'
|
14
|
+
elsif driver.include? 'postgres'
|
15
|
+
'postgresql'
|
16
|
+
elsif driver.include? 'oci8'
|
17
|
+
'oracle'
|
18
|
+
elsif driver.include? 'db2'
|
19
|
+
'db2'
|
20
|
+
elsif driver.include? 'sqlite'
|
21
|
+
'generic'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
25
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
26
|
+
end
|
27
|
+
include DatabaseHelper
|
@@ -1,24 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'stackify_apm/span'
|
4
|
+
require 'stackify_apm/transaction'
|
1
5
|
#
|
2
6
|
# The Instrumenter will build/process the transactions and spans.
|
3
7
|
#
|
4
|
-
|
5
|
-
require 'stackify/span'
|
6
|
-
require 'stackify/transaction'
|
7
|
-
|
8
8
|
module StackifyRubyAPM
|
9
|
-
|
10
|
-
|
9
|
+
# @api private
|
10
|
+
class Instrumenter
|
11
11
|
include Log
|
12
12
|
|
13
13
|
KEY = :_stackify_transaction_key
|
14
|
-
|
14
|
+
# Transaction Info class
|
15
15
|
class TransactionInfo
|
16
16
|
def initialize
|
17
17
|
self.current = nil
|
18
18
|
end
|
19
19
|
|
20
20
|
def current
|
21
|
-
# puts '[Instrumenter] [lib/instrumenter.rb] TransactionInfo.current()'
|
22
21
|
Thread.current[KEY]
|
23
22
|
end
|
24
23
|
|
@@ -48,20 +47,17 @@ module StackifyRubyAPM
|
|
48
47
|
end
|
49
48
|
|
50
49
|
def current_transaction
|
51
|
-
|
50
|
+
@transaction_info.current
|
52
51
|
end
|
53
52
|
|
54
53
|
def current_transaction=(transaction)
|
55
54
|
@transaction_info.current = transaction
|
56
55
|
end
|
57
56
|
|
58
|
-
# rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
59
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
60
|
-
#
|
61
57
|
# Creates a new transaction or return the currently running
|
62
58
|
#
|
63
59
|
def transaction(*args)
|
64
|
-
debug
|
60
|
+
debug '[Instrumenter] transaction(*args)'
|
65
61
|
unless config.instrument
|
66
62
|
yield if block_given?
|
67
63
|
return
|
@@ -83,17 +79,14 @@ module StackifyRubyAPM
|
|
83
79
|
self.current_transaction = nil
|
84
80
|
transaction.done
|
85
81
|
end
|
86
|
-
|
87
|
-
#puts transaction.inspect
|
88
82
|
|
89
83
|
transaction
|
90
84
|
end
|
91
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
92
|
-
# rubocop:enable Metrics/MethodLength, Metrics/AbcSize
|
93
85
|
|
94
86
|
def span(*args, &block)
|
95
87
|
unless current_transaction
|
96
88
|
return yield if block_given?
|
89
|
+
|
97
90
|
return
|
98
91
|
end
|
99
92
|
|
@@ -114,5 +107,5 @@ module StackifyRubyAPM
|
|
114
107
|
"current_transaction=#{current_transaction.inspect}" \
|
115
108
|
'>'
|
116
109
|
end
|
117
|
-
|
118
|
-
end
|
110
|
+
end
|
111
|
+
end
|
File without changes
|
File without changes
|
@@ -8,6 +8,20 @@
|
|
8
8
|
module StackifyRubyAPM
|
9
9
|
# @api private
|
10
10
|
class LogDevice < Logger::LogDevice
|
11
|
+
alias_method 'write_without_apm', 'write'
|
12
|
+
def write(message)
|
13
|
+
if @filename
|
14
|
+
if FileTest.exist?(@filename)
|
15
|
+
else
|
16
|
+
@dev = create_logfile(@filename)
|
17
|
+
File.chmod(0o777, @filename)
|
18
|
+
|
19
|
+
return @dev
|
20
|
+
end
|
21
|
+
end
|
22
|
+
write_without_apm(message)
|
23
|
+
end
|
24
|
+
|
11
25
|
def add_log_header(file)
|
12
26
|
# Make it only empty.
|
13
27
|
end
|
@@ -21,10 +35,7 @@ module StackifyRubyAPM
|
|
21
35
|
# set a temporary filename that doesn't have the increment prefix and .log format.
|
22
36
|
temp_filename = @filename.gsub(/\-(d*\.?\d*).log/, '')
|
23
37
|
# set a temporary file increment while stripping the current filename and retain the number
|
24
|
-
txttemp_fileincrement = @filename.gsub(temp_filename,'')
|
25
|
-
txttemp_fileincrement = txttemp_fileincrement.gsub('-','')
|
26
|
-
txttemp_fileincrement = txttemp_fileincrement.gsub('.log','')
|
27
|
-
|
38
|
+
txttemp_fileincrement = @filename.gsub(temp_filename, '').delete('^0-9')
|
28
39
|
# convert the string value to integer
|
29
40
|
current_fileprefix = txttemp_fileincrement.to_i
|
30
41
|
# assign as filename counter
|
@@ -33,12 +44,12 @@ module StackifyRubyAPM
|
|
33
44
|
filename_counter = current_fileprefix + 1
|
34
45
|
else
|
35
46
|
ctr_flagger = 0
|
36
|
-
# a loop that check if the number of filenames if exists or not
|
37
|
-
|
47
|
+
# a loop that check if the number of filenames if exists or not
|
48
|
+
1.upto(current_fileprefix) do |i|
|
38
49
|
temp_oldfile = "#{temp_filename}-#{i}.log"
|
39
|
-
ctr_flagger
|
50
|
+
ctr_flagger += 1 if FileTest.exist?(temp_oldfile)
|
40
51
|
end
|
41
|
-
# if the counter is 0 then set the filename counter to 1
|
52
|
+
# if the counter is 0 then set the filename counter to 1
|
42
53
|
filename_counter = 1 if ctr_flagger < 0
|
43
54
|
end
|
44
55
|
|
@@ -47,14 +58,13 @@ module StackifyRubyAPM
|
|
47
58
|
temp_newfilename = "#{temp_filename}-#{filename_counter}.log"
|
48
59
|
@filename = temp_newfilename
|
49
60
|
@dev = create_logfile(@filename)
|
61
|
+
File.chmod(0o777, @filename)
|
50
62
|
|
51
63
|
true
|
52
64
|
end
|
53
65
|
|
54
66
|
# This is the monkeypatch of core Logger method where reformats the file name when creating the file log.
|
55
67
|
def shift_log_period(period_end)
|
56
|
-
puts "shift_log_period(period_end) mao ni"
|
57
|
-
|
58
68
|
suffix = period_end.strftime(@shift_period_suffix)
|
59
69
|
age_file = "#{@filename}.#{suffix}"
|
60
70
|
if FileTest.exist?(age_file)
|
@@ -70,10 +80,11 @@ module StackifyRubyAPM
|
|
70
80
|
@dev.close rescue nil
|
71
81
|
File.rename(@filename.to_s, age_file)
|
72
82
|
@dev = create_logfile(@filename)
|
83
|
+
File.chmod(0o777, @filename)
|
73
84
|
|
74
85
|
true
|
75
86
|
end
|
76
87
|
# rubocop:enable Style/RescueModifier
|
77
88
|
# rubocop:enable Lint/RescueWithoutErrorClass
|
78
89
|
end
|
79
|
-
end
|
90
|
+
end
|
@@ -28,12 +28,7 @@ module StackifyRubyAPM
|
|
28
28
|
shift_period_suffix: shift_period_suffix)
|
29
29
|
end
|
30
30
|
end
|
31
|
-
require 'stackify/logger/log_device'
|
32
|
-
# rubocop:enable Style/NumericLiterals
|
33
|
-
# rubocop:enable Style/GuardClause
|
34
|
-
# rubocop:enable Metrics/ParameterLists
|
35
|
-
# rubocop:enable Lint/UnusedMethodArgument
|
36
|
-
|
37
31
|
|
32
|
+
require 'stackify_apm/logger/log_device'
|
38
33
|
end
|
39
34
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This class monkey patches the Rack Middleware method: e.g., call(env)
|
5
|
+
# It also handles the submission of transactions to Agent.
|
6
|
+
#
|
7
|
+
# If Agent is running, build_transaction(env) is called:
|
8
|
+
#
|
9
|
+
# -> BUILDS transaction: /stackify_ruby_apm.rb (#self.transaction)
|
10
|
+
# -> builds a [Context] from a Rack `env`: /stackify_ruby_apm.rb (#self.build_context)
|
11
|
+
# -> context may include information about the request,
|
12
|
+
# response, current user and more
|
13
|
+
#
|
14
|
+
# -> SUBMITS transaction: stackify_apm/transaction.rb (#submit)
|
15
|
+
# -> instrumenter submits transaction
|
16
|
+
# -> worker will run (if != running), responsible for sending transactions to APM
|
17
|
+
# for every 10 secs (based on config.flush_interval)
|
18
|
+
# -> transaction will be stored in queue by Agent
|
19
|
+
# -> worker will constantly execute transaction sending to APM
|
20
|
+
#
|
21
|
+
|
22
|
+
module StackifyRubyAPM
|
23
|
+
# @api private
|
24
|
+
class Middleware
|
25
|
+
def initialize(app)
|
26
|
+
@app = app
|
27
|
+
end
|
28
|
+
|
29
|
+
# This is where the requests are received, built into a transaction, and then submitted
|
30
|
+
#
|
31
|
+
def call(env)
|
32
|
+
begin
|
33
|
+
# if running? && !path_ignored?(env)
|
34
|
+
transaction = build_transaction(env) if running?
|
35
|
+
|
36
|
+
resp = @app.call env
|
37
|
+
|
38
|
+
submit_transaction(transaction, *resp) if transaction
|
39
|
+
rescue InternalError
|
40
|
+
raise # Don't report StackifyRubyAPM errors
|
41
|
+
rescue StandardError
|
42
|
+
transaction.submit('500', status: 500) if transaction
|
43
|
+
raise
|
44
|
+
ensure
|
45
|
+
transaction.release if transaction
|
46
|
+
end
|
47
|
+
|
48
|
+
resp
|
49
|
+
end
|
50
|
+
|
51
|
+
def submit_transaction(transaction, status, headers, _body)
|
52
|
+
result = status.to_i
|
53
|
+
transaction.submit(result, status: status, headers: headers)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Start of transaction building with params: name, type, context
|
57
|
+
#
|
58
|
+
def build_transaction(env)
|
59
|
+
StackifyRubyAPM.transaction 'Rack', 'request', context: StackifyRubyAPM.build_context(env)
|
60
|
+
end
|
61
|
+
|
62
|
+
def running?
|
63
|
+
StackifyRubyAPM.running?
|
64
|
+
end
|
65
|
+
|
66
|
+
def config
|
67
|
+
StackifyRubyAPM.agent.config
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|