stackify-ruby-apm 1.12.3 → 1.14.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/stackify_apm/config.rb +4 -1
- data/lib/stackify_apm/helper/database_helper.rb +6 -5
- data/lib/stackify_apm/logger/log_device.rb +19 -0
- data/lib/stackify_apm/middleware.rb +2 -0
- data/lib/stackify_apm/normalizers/active_record.rb +11 -0
- data/lib/stackify_apm/root_info.rb +6 -6
- data/lib/stackify_apm/span/context.rb +16 -13
- data/lib/stackify_apm/spies/dynamo_db.rb +51 -0
- data/lib/stackify_apm/spies/faraday.rb +87 -0
- data/lib/stackify_apm/spies/log4r.rb +2 -1
- data/lib/stackify_apm/spies/logger.rb +2 -1
- data/lib/stackify_apm/spies/logging.rb +2 -1
- data/lib/stackify_apm/spies/mongo.rb +3 -1
- data/lib/stackify_apm/spies/redis.rb +13 -6
- data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +21 -0
- data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +8 -0
- data/lib/stackify_apm/spies/sucker_punch.rb +39 -0
- data/lib/stackify_apm/spies/yell.rb +2 -1
- data/lib/stackify_apm/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d95a01fea8c43d40a4cf1f0f541f539e31d9e022d985e70096d3b01260cbab8
|
4
|
+
data.tar.gz: c4a871133a02ba479ceea744f9f868ab34910c291e947fe62cc644330f6935c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4ca5f2806b494bc98ecb9828a01dbb3e459328401c8a880a4239d0ff8ad16073ace3a7e52ec02fb93b633f14f1b6493dd46daa381ee0ef7fc9ac23a1a319cdb
|
7
|
+
data.tar.gz: 873b62a9ef92ef3ea222ea7ed2fbfff26e41b2114ea030ac668646db394e0093feab0588d08e390776fcc38b8d6ff152cf6df1d472b886be0f102a71f5d0ab90
|
data/lib/stackify_apm/config.rb
CHANGED
@@ -29,7 +29,7 @@ module DatabaseHelper
|
|
29
29
|
# Placeholder for mysql, sqlite, jdbc oracle, db2 is ?, example "SELECT * FROM posts WHERE author = ? and id = ?"
|
30
30
|
# Placeholder for postgres is $1, $2,...$n, example "SELECT * FROM posts WHERE author = $1 and id = $2"
|
31
31
|
# statement - contains the db properties such as SQL, PROVIDER, etc.
|
32
|
-
# So if there's payload value we append
|
32
|
+
# So if there's payload value we append PREFIX_SQL_PARAMETERS to the existing object properties.
|
33
33
|
# payload - contains the payload[:binds] which is the payload value/data of the placeholder.
|
34
34
|
# Example payload: {:sql=>"SELECT * FROM posts WHERE author = ? and id = ?", :db_adapter=>"mysql2::client", :binds=>["J.K. Rowling", 1]}
|
35
35
|
def check_prepared_stmt_by_placeholder(placeholder, statement, payload)
|
@@ -37,14 +37,15 @@ module DatabaseHelper
|
|
37
37
|
unless payload[:binds].nil?
|
38
38
|
payload[:binds].each_with_index do |record, idx|
|
39
39
|
if record && defined?(record.value)
|
40
|
-
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record.value)
|
40
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record.value[0..999])
|
41
41
|
elsif ((record && record.instance_of?(Array)) && defined?(record[1]))
|
42
|
-
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record[1])
|
42
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record[1][0..999])
|
43
43
|
else
|
44
|
-
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record)
|
44
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record[0..999])
|
45
45
|
end
|
46
46
|
end
|
47
|
-
statement[:
|
47
|
+
statement[:PREFIX_SQL_PARAMETERS] = sqlParam[0..99].to_json if sqlParam.count > 0
|
48
|
+
statement[:PREFIX_SQL_PARAMETER_COUNT] = sqlParam.length.to_s if sqlParam.count > 0
|
48
49
|
true
|
49
50
|
else
|
50
51
|
false
|
@@ -8,6 +8,7 @@
|
|
8
8
|
module StackifyRubyAPM
|
9
9
|
# @api private
|
10
10
|
class LogDevice < Logger::LogDevice
|
11
|
+
MAX_LOG_FILES_COUNT = 10
|
11
12
|
alias_method 'write_without_apm', 'write'
|
12
13
|
def write(message)
|
13
14
|
if @filename
|
@@ -84,6 +85,24 @@ module StackifyRubyAPM
|
|
84
85
|
def create_logfile(filename)
|
85
86
|
logdev = super
|
86
87
|
File.chmod(0o777, filename)
|
88
|
+
|
89
|
+
begin
|
90
|
+
dir_name = File.dirname(filename)
|
91
|
+
# repath current file due to windows separator \\ doesn't work with Dir.glob
|
92
|
+
dir_name = dir_name.split(File::ALT_SEPARATOR).join(File::SEPARATOR)
|
93
|
+
search_files = File.join("#{dir_name}", "{[!stackify-ruby-apm]*}.log")
|
94
|
+
log_files = Dir.glob(search_files).sort_by { |f| File.stat(f).mtime}.reverse
|
95
|
+
|
96
|
+
if log_files.length > MAX_LOG_FILES_COUNT
|
97
|
+
files_to_delete = log_files[MAX_LOG_FILES_COUNT..-1]
|
98
|
+
files_to_delete.each { |f|
|
99
|
+
File.delete(f) if File.exists? f
|
100
|
+
}
|
101
|
+
end
|
102
|
+
rescue
|
103
|
+
# nothing to do here
|
104
|
+
end
|
105
|
+
|
87
106
|
logdev
|
88
107
|
end
|
89
108
|
# rubocop:enable Style/RescueModifier
|
@@ -53,6 +53,8 @@ module StackifyRubyAPM
|
|
53
53
|
if okay_to_modify?
|
54
54
|
@configuration.already_instrumented_flag = true
|
55
55
|
if @configuration.rum_enabled.is_a?(TrueClass)
|
56
|
+
# close old response body proxy to close all db connections
|
57
|
+
@rack_body.close if @rack_body.respond_to?(:close)
|
56
58
|
response = Rack::Response.new @rack_body, @rack_status, @rack_headers
|
57
59
|
response.set_cookie(@configuration.rum_cookie_name, value: transaction.id, path: @configuration.rum_cookie_path)
|
58
60
|
resp = response.finish
|
@@ -29,9 +29,13 @@ module StackifyRubyAPM
|
|
29
29
|
private
|
30
30
|
|
31
31
|
def query_variables(payload)
|
32
|
+
adapter_config = lookup_adapter_config
|
32
33
|
props = get_common_db_properties
|
33
34
|
props[:PROVIDER] = get_profiler(lookup_adapter)
|
34
35
|
props[:SQL] = payload[:sql]
|
36
|
+
if adapter_config
|
37
|
+
props[:URL] = "#{adapter_config[:host]}:#{adapter_config[:port]}"
|
38
|
+
end
|
35
39
|
props
|
36
40
|
end
|
37
41
|
|
@@ -42,6 +46,13 @@ module StackifyRubyAPM
|
|
42
46
|
nil
|
43
47
|
end
|
44
48
|
|
49
|
+
def lookup_adapter_config
|
50
|
+
::ActiveRecord::Base.connection_config.to_h
|
51
|
+
rescue StandardError => error
|
52
|
+
debug '[SqlNormalizer] lookup_adapter_config err: ' + error.inspect.to_s
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
45
56
|
def check_prepared_stmt(statement, payload)
|
46
57
|
if StackifyRubyAPM.agent.config.prefix_enabled
|
47
58
|
case get_profiler(lookup_adapter)
|
@@ -47,12 +47,12 @@ module StackifyRubyAPM
|
|
47
47
|
hash[:URL] = @transaction.context.request.url[:full] if @transaction.context && @transaction.context.request && @transaction.context.request.url[:full]
|
48
48
|
hash[:RUM] = true if @config.rum_enabled.is_a?(TrueClass)
|
49
49
|
hash[:AWS_LAMBDA_ARN] = @transaction.context.aws[:arn] if @transaction.context && @transaction.context.aws && @transaction.context.aws[:arn]
|
50
|
-
hash[:
|
51
|
-
hash[:
|
52
|
-
hash[:
|
53
|
-
hash[:
|
54
|
-
hash[:
|
55
|
-
hash[:
|
50
|
+
hash[:PREFIX_RESPONSE_BODY] = @transaction.context.prefix.response_body.to_s if @transaction.context.prefix && @transaction.context.prefix.response_body
|
51
|
+
hash[:PREFIX_RESPONSE_SIZE_BYTES] = @transaction.context.prefix.response_body.length.to_s if @transaction.context.prefix && @transaction.context.prefix.response_body
|
52
|
+
hash[:PREFIX_RESPONSE_HEADERS] = @transaction.context.prefix.response_headers.to_s if @transaction.context.prefix && @transaction.context.prefix.response_headers
|
53
|
+
hash[:PREFIX_REQUEST_BODY] = @transaction.context.prefix.request_body.to_s if @transaction.context.prefix && @transaction.context.prefix.request_body
|
54
|
+
hash[:PREFIX_REQUEST_SIZE_BYTES] = @transaction.context.prefix.request_body.length.to_s if @transaction.context.prefix && @transaction.context.prefix.request_body
|
55
|
+
hash[:PREFIX_REQUEST_HEADERS] = @transaction.context.prefix.request_headers.to_s if @transaction.context.prefix && @transaction.context.prefix.request_headers
|
56
56
|
hash
|
57
57
|
end
|
58
58
|
# rubocop:enable Metrics/CyclomaticComplexity
|
@@ -17,7 +17,8 @@ module StackifyRubyAPM
|
|
17
17
|
:COMPONENT_CATEGORY,
|
18
18
|
:COMPONENT_DETAIL,
|
19
19
|
:SQL,
|
20
|
-
:
|
20
|
+
:PREFIX_SQL_PARAMETERS,
|
21
|
+
:PREFIX_SQL_PARAMETER_COUNT,
|
21
22
|
:SQL_TRUNCATED,
|
22
23
|
:MONGODB_COLLECTION,
|
23
24
|
:METHOD,
|
@@ -33,33 +34,35 @@ module StackifyRubyAPM
|
|
33
34
|
:LEVEL,
|
34
35
|
:MESSAGE,
|
35
36
|
:EXCEPTION,
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
37
|
+
:PREFIX_REQUEST_BODY,
|
38
|
+
:PREFIX_REQUEST_SIZE_BYTES,
|
39
|
+
:PREFIX_REQUEST_HEADERS,
|
40
|
+
:PREFIX_RESPONSE_BODY,
|
41
|
+
:PREFIX_RESPONSE_SIZE_BYTES,
|
42
|
+
:PREFIX_RESPONSE_HEADERS,
|
43
|
+
:PREFIX,
|
44
|
+
:ACTION
|
42
45
|
# rubocop:disable Style/VariableName
|
43
46
|
def update_status(status)
|
44
47
|
@STATUS = status
|
45
48
|
end
|
46
49
|
|
47
50
|
def update_request_body(body)
|
48
|
-
@
|
49
|
-
@
|
51
|
+
@PREFIX_REQUEST_BODY = body.to_s
|
52
|
+
@PREFIX_REQUEST_SIZE_BYTES = body.to_s.length.to_s
|
50
53
|
end
|
51
54
|
|
52
55
|
def update_request_headers(headers)
|
53
|
-
@
|
56
|
+
@PREFIX_REQUEST_HEADERS = to_json_list(headers)
|
54
57
|
end
|
55
58
|
|
56
59
|
def update_response_body(body)
|
57
|
-
@
|
58
|
-
@
|
60
|
+
@PREFIX_RESPONSE_BODY = body.to_s
|
61
|
+
@PREFIX_RESPONSE_SIZE_BYTES = body.to_s.length.to_s
|
59
62
|
end
|
60
63
|
|
61
64
|
def update_response_headers(headers)
|
62
|
-
@
|
65
|
+
@PREFIX_RESPONSE_HEADERS = to_json_list(headers)
|
63
66
|
end
|
64
67
|
|
65
68
|
private
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Monkey patch for the Aws::DynamoDB::Client class
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
# @api private
|
5
|
+
module Spies
|
6
|
+
# @api private
|
7
|
+
class DynamoDBSpy
|
8
|
+
TYPE = 'db.dynamo.aws'.freeze
|
9
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
10
|
+
def install
|
11
|
+
Aws::DynamoDB::Client.class_eval do
|
12
|
+
# Alias all available operations
|
13
|
+
api.operation_names.each do |operation_name|
|
14
|
+
alias_method "#{operation_name}_without_apm", "#{operation_name}"
|
15
|
+
|
16
|
+
define_method(operation_name) do |params = {}, options = {}|
|
17
|
+
original_method = method("#{operation_name}_without_apm")
|
18
|
+
return original_method.call(params, options) unless StackifyRubyAPM.current_transaction
|
19
|
+
|
20
|
+
result = nil
|
21
|
+
|
22
|
+
begin
|
23
|
+
name = operation_name
|
24
|
+
ctx = Span::Context.new(
|
25
|
+
CATEGORY: 'Database',
|
26
|
+
SUBCATEGORY: 'DynamoDB',
|
27
|
+
ACTION: operation_name,
|
28
|
+
URL: self.config.endpoint,
|
29
|
+
)
|
30
|
+
rescue Exception => e
|
31
|
+
StackifyRubyAPM.agent.error "[DynamoDBSpy] Error: creating span context."
|
32
|
+
StackifyRubyAPM.agent.error "[DynamoDBSpy] #{e.inspect}"
|
33
|
+
return original_method.call(params, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
37
|
+
result = original_method.call(params, options)
|
38
|
+
return result
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
# rubocop:enable Metrics/MethodLength
|
45
|
+
end
|
46
|
+
|
47
|
+
# Registers Aws::DynamoDB::Client spy, go to: /stackify_apm/spies.rb
|
48
|
+
#
|
49
|
+
register 'Aws::DynamoDB::Client', 'aws-sdk-dynamodb', DynamoDBSpy.new
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Monkey patch for the Faraday class
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
# @api private
|
5
|
+
module Spies
|
6
|
+
# @api private
|
7
|
+
class FaradaySpy
|
8
|
+
def install
|
9
|
+
Faraday::Connection.class_eval do
|
10
|
+
alias_method 'run_request_without_apm', 'run_request'
|
11
|
+
|
12
|
+
def run_request(method, url, body, headers, &block)
|
13
|
+
result = nil
|
14
|
+
return run_request_without_apm(method, url, body, headers, &block) unless StackifyRubyAPM.current_transaction
|
15
|
+
|
16
|
+
begin
|
17
|
+
uri = URI(build_url(url))
|
18
|
+
|
19
|
+
# url is not available yet if it is set inside block
|
20
|
+
# we need to build temporary request as of now
|
21
|
+
# NOTE: this could have a side effect doing yeild twice
|
22
|
+
unless uri.host
|
23
|
+
tmp_request = build_request(method) do |req|
|
24
|
+
yield(req) if block_given?
|
25
|
+
end
|
26
|
+
uri = URI(tmp_request.path)
|
27
|
+
end
|
28
|
+
|
29
|
+
host = uri.host
|
30
|
+
method_upcase = method.to_s.upcase
|
31
|
+
name = "#{method_upcase} #{host}"
|
32
|
+
type = "ext.faraday.#{method_upcase}"
|
33
|
+
|
34
|
+
# Builds span context
|
35
|
+
#
|
36
|
+
ctx = Span::Context.new(
|
37
|
+
CATEGORY: 'Web External',
|
38
|
+
SUBCATEGORY: 'Execute',
|
39
|
+
URL: uri,
|
40
|
+
STATUS: '',
|
41
|
+
METHOD: method_upcase
|
42
|
+
)
|
43
|
+
rescue Exception => e
|
44
|
+
StackifyRubyAPM.agent.error "[FaradaySpy] Error: creating span context."
|
45
|
+
StackifyRubyAPM.agent.error "[FaradaySpy] #{e.inspect}"
|
46
|
+
return run_request_without_apm(method, url, body, headers, &block)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Creates new span from HTTP result
|
50
|
+
#
|
51
|
+
StackifyRubyAPM.span name, type, context: ctx do
|
52
|
+
# Submits HTTP request
|
53
|
+
#
|
54
|
+
result = run_request_without_apm(method, url, body, headers) do |req|
|
55
|
+
yield req if block_given?
|
56
|
+
|
57
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
58
|
+
ctx.update_request_body(req.body || body || "")
|
59
|
+
ctx.update_request_headers(req.headers || headers || Hash.new)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
status_code = result.status.to_s
|
65
|
+
ctx.update_status(status_code)
|
66
|
+
|
67
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
68
|
+
ctx.update_response_body(result.body || "")
|
69
|
+
ctx.update_response_headers(result.headers || Hash.new)
|
70
|
+
end
|
71
|
+
rescue Exception => e
|
72
|
+
StackifyRubyAPM.agent.error '[FaradaySpy] Error: getting status code or updating request/response context.'
|
73
|
+
StackifyRubyAPM.agent.error "[FaradaySpy] #{e.inspect}"
|
74
|
+
end
|
75
|
+
return result
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
# rubocop:enable Metrics/MethodLength
|
81
|
+
end
|
82
|
+
|
83
|
+
# Registers Faraday spy, go to: /stackify_apm/spies.rb
|
84
|
+
#
|
85
|
+
register 'Faraday', 'faraday', FaradaySpy.new
|
86
|
+
end
|
87
|
+
end
|
@@ -18,11 +18,13 @@ module StackifyRubyAPM
|
|
18
18
|
name = command[0].upcase.to_s
|
19
19
|
type = 'db.redis'
|
20
20
|
redis_details = command[1].is_a?(String) ? command[1].split(':') : []
|
21
|
-
|
21
|
+
# use length instead of .blank?
|
22
|
+
# reason: will throw error if activesupport missing
|
23
|
+
redis_nspace = redis_details.length ? redis_details[0] : ''
|
22
24
|
redis_key = ''
|
23
25
|
|
24
26
|
# Checks CACHEKEY value
|
25
|
-
if
|
27
|
+
if redis_details.length && redis_details[1]
|
26
28
|
# Initially sets the CACHEKEY value
|
27
29
|
args = redis_details[1].split('/')
|
28
30
|
redis_key = args[0]
|
@@ -31,7 +33,11 @@ module StackifyRubyAPM
|
|
31
33
|
# Possible formats:
|
32
34
|
# `<namespace:key/method_name/expires_in=300/ttl=60/>`
|
33
35
|
# `<namespace:key/expires_in=300/ttl=60/>`
|
34
|
-
|
36
|
+
if redis_key.nil?
|
37
|
+
redis_key = redis_details[1]
|
38
|
+
else
|
39
|
+
redis_key = args[0..1].join('/') if args.length > 1 && !args[1].include?('=')
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
37
43
|
return call_without_apm(command, &block) if command[0] == :auth
|
@@ -43,10 +49,11 @@ module StackifyRubyAPM
|
|
43
49
|
COMPONENT_CATEGORY: 'Cache',
|
44
50
|
COMPONENT_DETAIL: 'Execute',
|
45
51
|
THREAD_ID: Thread.current.object_id,
|
46
|
-
OPERATION: name
|
52
|
+
OPERATION: name,
|
53
|
+
URL: "#{self.options[:host]}:#{self.options[:port]}"
|
47
54
|
}.tap do |hash|
|
48
|
-
hash[:CACHEKEY] = redis_key unless redis_key.empty?
|
49
|
-
hash[:CACHENAME] = redis_nspace unless redis_nspace.empty?
|
55
|
+
hash[:CACHEKEY] = redis_key unless redis_key.nil? || redis_key.empty?
|
56
|
+
hash[:CACHENAME] = redis_nspace unless redis_nspace.nil? || redis_nspace.empty?
|
50
57
|
end
|
51
58
|
|
52
59
|
ctx = Span::Context.new(context)
|
@@ -10,6 +10,7 @@ module StackifyRubyAPM
|
|
10
10
|
# @api private
|
11
11
|
class MysqlAdapterSpy
|
12
12
|
TYPE = 'db.sinatra_active_record.sql'.freeze
|
13
|
+
DEFAULT_PORT = 3306
|
13
14
|
if ActiveRecord::VERSION::MAJOR.to_i >= 5
|
14
15
|
def install
|
15
16
|
ActiveRecord::ConnectionAdapters::MySQL::DatabaseStatements.class_eval do
|
@@ -79,6 +80,7 @@ module StackifyRubyAPM
|
|
79
80
|
props = get_common_db_properties
|
80
81
|
props[:PROVIDER] = 'mysql'
|
81
82
|
props[:SQL] = payload[:sql]
|
83
|
+
props[:URL] = get_host unless !get_host
|
82
84
|
props
|
83
85
|
end
|
84
86
|
|
@@ -87,6 +89,13 @@ module StackifyRubyAPM
|
|
87
89
|
check_prepared_stmt_by_placeholder(payload[:sql].include?('?'), statement, payload)
|
88
90
|
end
|
89
91
|
end
|
92
|
+
|
93
|
+
def get_host
|
94
|
+
query_options = self.raw_connection.query_options.to_h
|
95
|
+
"#{query_options[:host]}:#{query_options[:port] || DEFAULT_PORT}"
|
96
|
+
rescue StandardError => error
|
97
|
+
nil
|
98
|
+
end
|
90
99
|
end
|
91
100
|
end
|
92
101
|
else
|
@@ -112,6 +121,7 @@ module StackifyRubyAPM
|
|
112
121
|
SQL: sql,
|
113
122
|
PROVIDER: 'mysql'
|
114
123
|
)
|
124
|
+
ctx[:URL] = get_host unless !get_host
|
115
125
|
|
116
126
|
result = exec_query_without_apm(sql, name, binds)
|
117
127
|
|
@@ -135,6 +145,7 @@ module StackifyRubyAPM
|
|
135
145
|
SQL: sql,
|
136
146
|
PROVIDER: 'mysql'
|
137
147
|
)
|
148
|
+
ctx[:URL] = get_host unless !get_host
|
138
149
|
|
139
150
|
result = exec_delete_without_apm(sql, name, binds)
|
140
151
|
|
@@ -158,6 +169,7 @@ module StackifyRubyAPM
|
|
158
169
|
SQL: sql,
|
159
170
|
PROVIDER: 'mysql'
|
160
171
|
)
|
172
|
+
ctx[:URL] = get_host unless !get_host
|
161
173
|
|
162
174
|
result = exec_update_without_apm(sql, name, binds)
|
163
175
|
|
@@ -181,6 +193,7 @@ module StackifyRubyAPM
|
|
181
193
|
SQL: sql,
|
182
194
|
PROVIDER: 'mysql'
|
183
195
|
)
|
196
|
+
ctx[:URL] = get_host unless !get_host
|
184
197
|
|
185
198
|
result = exec_insert_without_apm(sql, name, binds, _pk = nil, _sequence_name = nil)
|
186
199
|
|
@@ -188,6 +201,14 @@ module StackifyRubyAPM
|
|
188
201
|
return result
|
189
202
|
end
|
190
203
|
end
|
204
|
+
|
205
|
+
def get_host
|
206
|
+
config = self.config.to_h
|
207
|
+
"#{config[:host]}:#{config[:port] || DEFAULT_PORT}"
|
208
|
+
rescue StandardError => error
|
209
|
+
nil
|
210
|
+
end
|
211
|
+
|
191
212
|
end
|
192
213
|
end
|
193
214
|
end
|
@@ -80,6 +80,7 @@ module StackifyRubyAPM
|
|
80
80
|
props = get_common_db_properties
|
81
81
|
props[:PROVIDER] = 'postgresql'
|
82
82
|
props[:SQL] = payload[:sql]
|
83
|
+
props[:URL] = get_host unless !get_host
|
83
84
|
props
|
84
85
|
end
|
85
86
|
|
@@ -88,6 +89,13 @@ module StackifyRubyAPM
|
|
88
89
|
check_prepared_stmt_by_placeholder(!!payload[:sql].match(/\$\d/), statement, payload)
|
89
90
|
end
|
90
91
|
end
|
92
|
+
|
93
|
+
def get_host
|
94
|
+
connection = self.raw_connection
|
95
|
+
"#{connection.host}:#{connection.port}"
|
96
|
+
rescue StandardError => error
|
97
|
+
nil
|
98
|
+
end
|
91
99
|
end
|
92
100
|
end
|
93
101
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Monkey patch for the sucker_punch class for running async tasks.
|
4
|
+
#
|
5
|
+
|
6
|
+
module StackifyRubyAPM
|
7
|
+
# @api private
|
8
|
+
module Spies
|
9
|
+
# @api private
|
10
|
+
class SuckerPunchSpy
|
11
|
+
def install
|
12
|
+
SuckerPunch::Job::ClassMethods.class_eval do
|
13
|
+
alias_method '__run_perform_without_elastic_apm', '__run_perform'
|
14
|
+
|
15
|
+
def __run_perform(*args)
|
16
|
+
ret = nil
|
17
|
+
begin
|
18
|
+
name = "#{to_s}.perform"
|
19
|
+
ctx = StackifyRubyAPM::Context.new
|
20
|
+
ctx.category = 'SuckerPunch::Job'
|
21
|
+
transaction = StackifyRubyAPM.transaction name, 'TASK', context: ctx
|
22
|
+
ret = __run_perform_without_elastic_apm(*args)
|
23
|
+
rescue StackifyRubyAPM::InternalError
|
24
|
+
raise # Don't report StackifyRubyAPM errors
|
25
|
+
rescue StandardError => e
|
26
|
+
StackifyRubyAPM.report e
|
27
|
+
raise e
|
28
|
+
ensure
|
29
|
+
transaction.submit()
|
30
|
+
end
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
register 'SuckerPunch', 'sucker_punch', SuckerPunchSpy.new
|
38
|
+
end
|
39
|
+
end
|
data/lib/stackify_apm/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stackify-ruby-apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.14.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stackify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -474,6 +474,8 @@ files:
|
|
474
474
|
- lib/stackify_apm/spies/curb/multi.rb
|
475
475
|
- lib/stackify_apm/spies/custom_instrumenter.rb
|
476
476
|
- lib/stackify_apm/spies/delayed_job.rb
|
477
|
+
- lib/stackify_apm/spies/dynamo_db.rb
|
478
|
+
- lib/stackify_apm/spies/faraday.rb
|
477
479
|
- lib/stackify_apm/spies/httparty.rb
|
478
480
|
- lib/stackify_apm/spies/httpclient.rb
|
479
481
|
- lib/stackify_apm/spies/httprb.rb
|
@@ -490,6 +492,7 @@ files:
|
|
490
492
|
- lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb
|
491
493
|
- lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb
|
492
494
|
- lib/stackify_apm/spies/stackify_logger.rb
|
495
|
+
- lib/stackify_apm/spies/sucker_punch.rb
|
493
496
|
- lib/stackify_apm/spies/tilt.rb
|
494
497
|
- lib/stackify_apm/spies/yell.rb
|
495
498
|
- lib/stackify_apm/stacktrace.rb
|