stackify-ruby-apm 0.9.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +18 -0
- data/Gemfile.lock +181 -8
- data/LICENSE.md +66 -0
- data/README.md +5 -3
- data/Rakefile +4 -0
- data/docker-compose.yml +46 -0
- data/lib/stackify/agent.rb +22 -9
- data/lib/stackify/config.rb +65 -29
- data/lib/stackify/context/response.rb +13 -0
- data/lib/stackify/context_builder.rb +0 -2
- data/lib/stackify/error.rb +2 -2
- data/lib/stackify/error_builder.rb +1 -1
- data/lib/stackify/instrumenter.rb +4 -4
- data/lib/stackify/logger/logger_high_version.rb +65 -0
- data/lib/stackify/logger/logger_lower_version.rb +63 -0
- data/lib/stackify/middleware.rb +0 -4
- data/lib/stackify/normalizers.rb +0 -1
- data/lib/stackify/normalizers/active_record.rb +3 -1
- data/lib/stackify/railtie.rb +0 -1
- data/lib/stackify/serializers/errors.rb +8 -7
- data/lib/stackify/serializers/transactions.rb +3 -2
- data/lib/stackify/span.rb +1 -2
- data/lib/stackify/span/context.rb +5 -1
- data/lib/stackify/spies/action_dispatch.rb +8 -1
- data/lib/stackify/spies/httpclient.rb +14 -5
- data/lib/stackify/spies/httprb.rb +45 -0
- data/lib/stackify/spies/mongo.rb +13 -1
- data/lib/stackify/spies/net_http.rb +14 -3
- data/lib/stackify/spies/redis.rb +66 -0
- data/lib/stackify/spies/sinatra.rb +3 -1
- data/lib/stackify/spies/sinatra_activerecord/mysql_adapter.rb +177 -0
- data/lib/stackify/spies/sinatra_activerecord/postgresql_adapter.rb +96 -0
- data/lib/stackify/spies/sinatra_activerecord/sqlite_adapter.rb +48 -0
- data/lib/stackify/spies/tilt.rb +8 -1
- data/lib/stackify/stacktrace_builder.rb +4 -3
- data/lib/stackify/subscriber.rb +4 -4
- data/lib/stackify/trace_logger.rb +6 -23
- data/lib/stackify/transaction.rb +10 -1
- data/lib/stackify/util.rb +0 -13
- data/lib/stackify/version.rb +1 -1
- data/lib/stackify/worker.rb +5 -5
- data/lib/stackify_ruby_apm.rb +2 -6
- data/run-test.sh +75 -0
- data/stackify-ruby-apm.gemspec +0 -1
- metadata +12 -17
- data/lib/stackify/logger.rb +0 -10
@@ -37,11 +37,13 @@ module StackifyRubyAPM
|
|
37
37
|
"oracle"
|
38
38
|
elsif driver.include? "db2"
|
39
39
|
"db2"
|
40
|
+
elsif driver.include? "sqlite"
|
41
|
+
"sqlite"
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
43
45
|
def query_variables(payload)
|
44
|
-
debug "
|
46
|
+
debug "[SqlNormalizer] query_variables payload:"
|
45
47
|
debug payload.inspect
|
46
48
|
|
47
49
|
if payload[:type_casted_binds]
|
data/lib/stackify/railtie.rb
CHANGED
@@ -24,7 +24,6 @@ module StackifyRubyAPM
|
|
24
24
|
# This will overwrite the default values of the config based from stackify_apm.yml initialized
|
25
25
|
|
26
26
|
initializer 'stackify_apm.initialize' do |app|
|
27
|
-
# puts '@stackify_ruby [Railtie] [lib/railtie.rb] initializer'
|
28
27
|
config = app.config.stackify.merge(app: app).tap do |c|
|
29
28
|
# Prepend Rails.root to log_path if present
|
30
29
|
if c.log_path && !c.log_path.start_with?('/')
|
@@ -10,14 +10,15 @@ module StackifyRubyAPM
|
|
10
10
|
def build(error)
|
11
11
|
|
12
12
|
if (exception = error.exception)
|
13
|
+
current_timestamp = error.timestamp
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
15
|
+
base = {
|
16
|
+
CaughtBy: exception.module,
|
17
|
+
Exception: exception.type,
|
18
|
+
Message: exception.message,
|
19
|
+
Timestamp: "#{current_timestamp.round}",
|
20
|
+
Frames: exception.stacktrace.to_a,
|
21
|
+
}
|
21
22
|
|
22
23
|
end
|
23
24
|
|
@@ -17,7 +17,9 @@ module StackifyRubyAPM
|
|
17
17
|
call: transaction.name,
|
18
18
|
reqBegin: transaction.timestamp,
|
19
19
|
reqEnd: transaction.duration,
|
20
|
-
props: RootInfo.build(config, transaction)
|
20
|
+
props: RootInfo.build(config, transaction),
|
21
|
+
exceptions: transaction.exceptions,
|
22
|
+
stacks: []
|
21
23
|
}
|
22
24
|
|
23
25
|
# serialize all the spans
|
@@ -27,7 +29,6 @@ module StackifyRubyAPM
|
|
27
29
|
end
|
28
30
|
|
29
31
|
add_children_spans(root_span_json, children_spans_json)
|
30
|
-
|
31
32
|
root_span_json
|
32
33
|
end
|
33
34
|
|
data/lib/stackify/span.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
#
|
2
|
+
#
|
3
|
+
# Monkey patch for the ActionDispatch::ShowExceptions class which handles exception events.
|
4
|
+
#
|
5
|
+
|
3
6
|
module StackifyRubyAPM
|
4
7
|
# @api private
|
5
8
|
module Spies
|
@@ -10,6 +13,8 @@ module StackifyRubyAPM
|
|
10
13
|
alias render_exception_without_apm render_exception
|
11
14
|
|
12
15
|
def render_exception(env, exception)
|
16
|
+
# Creates exception log report
|
17
|
+
#
|
13
18
|
StackifyRubyAPM.report(exception)
|
14
19
|
render_exception_without_apm env, exception
|
15
20
|
end
|
@@ -17,6 +22,8 @@ module StackifyRubyAPM
|
|
17
22
|
end
|
18
23
|
end
|
19
24
|
|
25
|
+
# Registers ActionDispatch spy, go to: /stackify/spies.rb
|
26
|
+
#
|
20
27
|
register(
|
21
28
|
'ActionDispatch::ShowExceptions',
|
22
29
|
'action_dispatch/show_exception',
|
@@ -1,14 +1,11 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# Monkey patch for the HTTPClient class for sending & receiving HTTP responses.
|
2
|
+
#
|
3
3
|
|
4
4
|
module StackifyRubyAPM
|
5
5
|
# @api private
|
6
6
|
module Spies
|
7
7
|
# @api private
|
8
8
|
class HTTPClientSpy
|
9
|
-
include Log
|
10
|
-
|
11
|
-
# This class monkeypatches the HTTPClient class with request method.
|
12
9
|
def install
|
13
10
|
HTTPClient.class_eval do
|
14
11
|
alias request_without_apm request
|
@@ -18,12 +15,20 @@ module StackifyRubyAPM
|
|
18
15
|
unless StackifyRubyAPM.current_transaction
|
19
16
|
return request_without_apm(method, uri, *args, &block)
|
20
17
|
end
|
18
|
+
|
19
|
+
# Data configuration
|
20
|
+
#
|
21
21
|
method = method.upcase
|
22
22
|
uri = uri.strip
|
23
23
|
name = "#{method} #{uri}"
|
24
24
|
type = "ext.httpclient.#{method}"
|
25
25
|
|
26
|
+
# Submits HTTP request
|
27
|
+
#
|
26
28
|
req = request_without_apm(method, uri, *args, &block)
|
29
|
+
|
30
|
+
# Builds span context
|
31
|
+
#
|
27
32
|
ctx = Span::Context.new(
|
28
33
|
CATEGORY: 'Web External',
|
29
34
|
SUBCATEGORY: 'Execute',
|
@@ -32,6 +37,8 @@ module StackifyRubyAPM
|
|
32
37
|
METHOD: method
|
33
38
|
)
|
34
39
|
|
40
|
+
# Creates new span from HTTP result
|
41
|
+
#
|
35
42
|
StackifyRubyAPM.span name, type, context: ctx do
|
36
43
|
req
|
37
44
|
end
|
@@ -42,6 +49,8 @@ module StackifyRubyAPM
|
|
42
49
|
# rubocop:enable Metrics/MethodLength
|
43
50
|
end
|
44
51
|
|
52
|
+
# Registers HTTPClient spy, go to: /stackify/spies.rb
|
53
|
+
#
|
45
54
|
register 'HTTPClient', 'httpclient', HTTPClientSpy.new
|
46
55
|
end
|
47
56
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# This class monkey patch the http.rb gem with the request method.
|
3
|
+
#
|
4
|
+
module StackifyRubyAPM
|
5
|
+
# @api private
|
6
|
+
module Spies
|
7
|
+
# @api private
|
8
|
+
class HTTPRbSpy
|
9
|
+
|
10
|
+
def install
|
11
|
+
HTTP::Client.class_eval do
|
12
|
+
alias request_without_apm request
|
13
|
+
|
14
|
+
# Make HTTP request
|
15
|
+
def request(verb, uri, opts = {})
|
16
|
+
unless StackifyRubyAPM.current_transaction
|
17
|
+
return request_without_apm(verb, uri, opts = {})
|
18
|
+
end
|
19
|
+
|
20
|
+
method = verb.upcase
|
21
|
+
uri = uri.strip
|
22
|
+
name = "#{method} #{uri}"
|
23
|
+
type = "ext.httprb.#{method}"
|
24
|
+
|
25
|
+
req = request_without_apm(verb, uri, opts = {})
|
26
|
+
ctx = Span::Context.new(
|
27
|
+
CATEGORY: 'Web External',
|
28
|
+
SUBCATEGORY: 'Execute',
|
29
|
+
URL: uri,
|
30
|
+
STATUS: req.code,
|
31
|
+
METHOD: method
|
32
|
+
)
|
33
|
+
|
34
|
+
StackifyRubyAPM.span name, type, context: ctx do
|
35
|
+
req
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
# rubocop:enable Metrics/MethodLength
|
41
|
+
end
|
42
|
+
|
43
|
+
register 'HTTP::Client', 'http/client', HTTPRbSpy.new
|
44
|
+
end
|
45
|
+
end
|
data/lib/stackify/spies/mongo.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# Monkey patch for the Mongo::Monitoring::Global module in mongoDB(http://api.mongodb.com/ruby/current/Mongo/Monitoring/Global.html)
|
2
|
+
# -> Allows subscribing to events for all Mongo clients.
|
3
|
+
#
|
4
|
+
|
1
5
|
module StackifyRubyAPM
|
2
6
|
# @api private
|
3
7
|
module Spies
|
4
8
|
# @api private
|
5
|
-
# This class monkeypatch the Mongo::Monitoring::Global module in mongoDB(http://api.mongodb.com/ruby/current/Mongo/Monitoring/Global.html)
|
6
9
|
class MongoSpy
|
7
10
|
def install
|
8
11
|
::Mongo::Monitoring::Global.subscribe(
|
@@ -36,6 +39,8 @@ module StackifyRubyAPM
|
|
36
39
|
def push_event(event)
|
37
40
|
return unless StackifyRubyAPM.current_transaction
|
38
41
|
|
42
|
+
# Fetches collection name from Mongo event
|
43
|
+
#
|
39
44
|
document = event.command.find
|
40
45
|
col = nil
|
41
46
|
if document
|
@@ -44,10 +49,15 @@ module StackifyRubyAPM
|
|
44
49
|
end
|
45
50
|
end
|
46
51
|
|
52
|
+
# Builds span context
|
53
|
+
#
|
47
54
|
ctx = Span::Context.new(
|
48
55
|
CATEGORY: 'MongoDB',
|
49
56
|
MONGODB_COLLECTION: col,
|
50
57
|
)
|
58
|
+
|
59
|
+
# Creates new span from Mongo event
|
60
|
+
#
|
51
61
|
span = StackifyRubyAPM.span(event.command_name, TYPE, context: ctx)
|
52
62
|
@events[event.operation_id] = span
|
53
63
|
end
|
@@ -61,6 +71,8 @@ module StackifyRubyAPM
|
|
61
71
|
end
|
62
72
|
end
|
63
73
|
|
74
|
+
# Registers Mongo spy, go to: /stackify/spies.rb
|
75
|
+
#
|
64
76
|
register 'Mongo', 'mongo', MongoSpy.new
|
65
77
|
end
|
66
78
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# Monkey patch for the Net::HTTP class for sending & receiving HTTP responses.
|
2
|
+
#
|
3
|
+
|
1
4
|
module StackifyRubyAPM
|
2
5
|
# @api private
|
3
6
|
module Spies
|
4
7
|
# @api private
|
5
8
|
class NetHTTPSpy
|
6
|
-
# This class monkeypatch the Net::HTTP class with request method.
|
7
9
|
def install
|
8
10
|
Net::HTTP.class_eval do
|
9
11
|
alias request_without_apm request
|
@@ -14,6 +16,8 @@ module StackifyRubyAPM
|
|
14
16
|
request_without_apm(req, body, &block)
|
15
17
|
end
|
16
18
|
|
19
|
+
# Data configuration
|
20
|
+
#
|
17
21
|
host, = req['host'] && req['host'].split(':')
|
18
22
|
method = req.method
|
19
23
|
|
@@ -22,16 +26,22 @@ module StackifyRubyAPM
|
|
22
26
|
name = "#{method} #{host}"
|
23
27
|
type = "ext.net_http.#{method}"
|
24
28
|
|
29
|
+
# Submits HTTP request
|
30
|
+
#
|
25
31
|
result = request_without_apm(req, body, &block)
|
26
32
|
|
33
|
+
# Builds span context
|
34
|
+
#
|
27
35
|
ctx = Span::Context.new(
|
28
36
|
CATEGORY: 'Web External',
|
29
37
|
SUBCATEGORY: 'Execute',
|
30
|
-
URL: req.uri,
|
38
|
+
URL: req.uri.nil? ? host : req.uri,
|
31
39
|
STATUS: result.code.to_i,
|
32
40
|
METHOD: method
|
33
41
|
)
|
34
42
|
|
43
|
+
# Creates new span from HTTP result
|
44
|
+
#
|
35
45
|
StackifyRubyAPM.span name, type, context: ctx do
|
36
46
|
return result
|
37
47
|
end
|
@@ -41,7 +51,8 @@ module StackifyRubyAPM
|
|
41
51
|
# rubocop:enable Metrics/MethodLength
|
42
52
|
end
|
43
53
|
|
44
|
-
|
54
|
+
# Registers Net::HTTP spy, go to: /stackify/spies.rb
|
55
|
+
#
|
45
56
|
register 'Net::HTTP', 'net/http', NetHTTPSpy.new
|
46
57
|
end
|
47
58
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# Monkey patch for Redis.
|
2
|
+
#
|
3
|
+
|
4
|
+
module StackifyRubyAPM
|
5
|
+
# @api private
|
6
|
+
module Spies
|
7
|
+
# @api private
|
8
|
+
class RedisSpy
|
9
|
+
|
10
|
+
def install
|
11
|
+
::Redis::Client.class_eval do
|
12
|
+
alias call_without_apm call
|
13
|
+
|
14
|
+
def call(command, &block)
|
15
|
+
name = command[0].upcase.to_s
|
16
|
+
type = 'db.redis'
|
17
|
+
redis_details = command[1].is_a?(String) ? command[1].split(":") : []
|
18
|
+
redis_nspace = !redis_details.blank? ? redis_details[0] : ""
|
19
|
+
redis_key = ""
|
20
|
+
|
21
|
+
# Checks CACHEKEY value
|
22
|
+
if !redis_details.blank? && redis_details[1]
|
23
|
+
# Initially sets the CACHEKEY value
|
24
|
+
args = redis_details[1].split("/")
|
25
|
+
redis_key = args[0]
|
26
|
+
|
27
|
+
# If command has passed __method__, it will be included in the CACHEKEY value
|
28
|
+
# Possible formats:
|
29
|
+
# `<namespace:key/method_name/expires_in=300/ttl=60/>`
|
30
|
+
# `<namespace:key/expires_in=300/ttl=60/>`
|
31
|
+
if args.length > 1 && !args[1].include?("=")
|
32
|
+
redis_key = args[0..1].join("/")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
return call_without_apm(command, &block) if command[0] == :auth
|
37
|
+
|
38
|
+
context = {
|
39
|
+
PROVIDER: 'Redis',
|
40
|
+
CATEGORY: 'Cache',
|
41
|
+
SUBCATEGORY: 'Execute',
|
42
|
+
COMPONENT_CATEGORY: 'Cache',
|
43
|
+
COMPONENT_DETAIL: 'Execute',
|
44
|
+
THREAD_ID: Thread.current.object_id,
|
45
|
+
OPERATION: name
|
46
|
+
}.tap do |hash|
|
47
|
+
hash[:CACHEKEY] = redis_key unless redis_key.empty?
|
48
|
+
hash[:CACHENAME] = redis_nspace unless redis_nspace.empty?
|
49
|
+
end
|
50
|
+
|
51
|
+
ctx = Span::Context.new(context)
|
52
|
+
|
53
|
+
StackifyRubyAPM.span name, type, context: ctx do
|
54
|
+
call_without_apm(command, &block)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
# Registers Redis spy, go to: /stackify/spies.rb
|
63
|
+
#
|
64
|
+
register 'Redis', 'redis', RedisSpy.new
|
65
|
+
end
|
66
|
+
end
|
@@ -25,7 +25,7 @@ module StackifyRubyAPM
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
# Tilt engine
|
28
|
+
# Tilt engine template
|
29
29
|
#
|
30
30
|
def compile_template(engine, data, opts, *args, &block)
|
31
31
|
opts[:__stackify_apm_template_name] =
|
@@ -45,6 +45,8 @@ module StackifyRubyAPM
|
|
45
45
|
#
|
46
46
|
register 'Sinatra::Base', 'sinatra/base', SinatraSpy.new
|
47
47
|
|
48
|
+
# Tilt template helper & span creator
|
49
|
+
#
|
48
50
|
require 'stackify/spies/tilt'
|
49
51
|
end
|
50
52
|
end
|
@@ -0,0 +1,177 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
3
|
+
#
|
4
|
+
module StackifyRubyAPM
|
5
|
+
# @api private
|
6
|
+
module Spies
|
7
|
+
# @api private
|
8
|
+
class MysqlAdapterSpy
|
9
|
+
TYPE = 'db.sinatra_active_record.sql'.freeze
|
10
|
+
if ActiveRecord::VERSION::MAJOR.to_i >= 5
|
11
|
+
# rubocop:disable Metrics/MethodLength
|
12
|
+
def install
|
13
|
+
ActiveRecord::ConnectionAdapters::MySQL::DatabaseStatements.class_eval do
|
14
|
+
alias exec_query_without_apm exec_query
|
15
|
+
alias exec_delete_without_apm exec_delete
|
16
|
+
alias exec_update_without_apm exec_update
|
17
|
+
|
18
|
+
def exec_update(sql, name = nil, binds = [])
|
19
|
+
result = nil
|
20
|
+
unless StackifyRubyAPM.current_transaction
|
21
|
+
exec_update_without_apm(sql, name, binds)
|
22
|
+
end
|
23
|
+
|
24
|
+
ctx = Span::Context.new(
|
25
|
+
CATEGORY: 'Database',
|
26
|
+
SUBCATEGORY: 'Execute',
|
27
|
+
COMPONENT_CATEGORY: 'DB Query',
|
28
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
29
|
+
SQL: sql,
|
30
|
+
PROVIDER: "mysql"
|
31
|
+
)
|
32
|
+
result = exec_update_without_apm(sql, name, binds)
|
33
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
34
|
+
return result
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def exec_delete(sql, name = nil, binds = [])
|
39
|
+
result = nil
|
40
|
+
unless StackifyRubyAPM.current_transaction
|
41
|
+
exec_delete_without_apm(sql, name, binds)
|
42
|
+
end
|
43
|
+
|
44
|
+
ctx = Span::Context.new(
|
45
|
+
CATEGORY: 'Database',
|
46
|
+
SUBCATEGORY: 'Execute',
|
47
|
+
COMPONENT_CATEGORY: 'DB Query',
|
48
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
49
|
+
SQL: sql,
|
50
|
+
PROVIDER: "mysql"
|
51
|
+
)
|
52
|
+
|
53
|
+
result = exec_delete_without_apm(sql, name, binds)
|
54
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
55
|
+
return result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
60
|
+
result = nil
|
61
|
+
unless StackifyRubyAPM.current_transaction
|
62
|
+
exec_query_without_apm(sql, name, binds)
|
63
|
+
end
|
64
|
+
|
65
|
+
ctx = Span::Context.new(
|
66
|
+
CATEGORY: 'Database',
|
67
|
+
SUBCATEGORY: 'Execute',
|
68
|
+
COMPONENT_CATEGORY: 'DB Query',
|
69
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
70
|
+
SQL: sql,
|
71
|
+
PROVIDER: "mysql"
|
72
|
+
)
|
73
|
+
|
74
|
+
result = exec_query_without_apm(sql, name, binds)
|
75
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
76
|
+
return result
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
# rubocop:enable Metrics/MethodLength
|
82
|
+
else
|
83
|
+
# rubocop:disable Metrics/MethodLength
|
84
|
+
def install
|
85
|
+
ActiveRecord::ConnectionAdapters::Mysql2Adapter.class_eval do
|
86
|
+
alias exec_query_without_apm exec_query
|
87
|
+
alias exec_delete_without_apm exec_delete
|
88
|
+
alias exec_update_without_apm exec_update
|
89
|
+
alias exec_insert_without_apm exec_insert
|
90
|
+
|
91
|
+
def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
|
92
|
+
result = nil
|
93
|
+
unless StackifyRubyAPM.current_transaction
|
94
|
+
exec_insert_without_apm(sql, name, binds, pk = nil, sequence_name = nil)
|
95
|
+
end
|
96
|
+
ctx = Span::Context.new(
|
97
|
+
CATEGORY: 'Database',
|
98
|
+
SUBCATEGORY: 'Execute',
|
99
|
+
COMPONENT_CATEGORY: 'DB Query',
|
100
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
101
|
+
SQL: sql,
|
102
|
+
PROVIDER: "mysql"
|
103
|
+
)
|
104
|
+
result = exec_insert_without_apm(sql, name, binds, pk = nil, sequence_name = nil)
|
105
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
106
|
+
return result
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def exec_update(sql, name, binds)
|
111
|
+
result = nil
|
112
|
+
unless StackifyRubyAPM.current_transaction
|
113
|
+
exec_update_without_apm(sql, name, binds)
|
114
|
+
end
|
115
|
+
ctx = Span::Context.new(
|
116
|
+
CATEGORY: 'Database',
|
117
|
+
SUBCATEGORY: 'Execute',
|
118
|
+
COMPONENT_CATEGORY: 'DB Query',
|
119
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
120
|
+
SQL: sql,
|
121
|
+
PROVIDER: "mysql"
|
122
|
+
)
|
123
|
+
result = exec_update_without_apm(sql, name, binds)
|
124
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
125
|
+
return result
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def exec_delete(sql, name, binds)
|
130
|
+
result = nil
|
131
|
+
unless StackifyRubyAPM.current_transaction
|
132
|
+
exec_delete_without_apm(sql, name, binds)
|
133
|
+
end
|
134
|
+
ctx = Span::Context.new(
|
135
|
+
CATEGORY: 'Database',
|
136
|
+
SUBCATEGORY: 'Execute',
|
137
|
+
COMPONENT_CATEGORY: 'DB Query',
|
138
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
139
|
+
SQL: sql,
|
140
|
+
PROVIDER: "mysql"
|
141
|
+
)
|
142
|
+
result = exec_delete_without_apm(sql, name, binds)
|
143
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
144
|
+
return result
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def exec_query(sql, name = "SQL", binds = [], prepare: false)
|
149
|
+
result = nil
|
150
|
+
unless StackifyRubyAPM.current_transaction
|
151
|
+
exec_query_without_apm(sql, name, binds)
|
152
|
+
end
|
153
|
+
ctx = Span::Context.new(
|
154
|
+
CATEGORY: 'Database',
|
155
|
+
SUBCATEGORY: 'Execute',
|
156
|
+
COMPONENT_CATEGORY: 'DB Query',
|
157
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
158
|
+
SQL: sql,
|
159
|
+
PROVIDER: "mysql"
|
160
|
+
)
|
161
|
+
result = exec_query_without_apm(sql, name, binds)
|
162
|
+
StackifyRubyAPM.span name, TYPE, context: ctx do
|
163
|
+
return result
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
# rubocop:enable Metrics/MethodLength
|
169
|
+
end
|
170
|
+
end
|
171
|
+
if ActiveRecord::VERSION::MAJOR.to_i >= 5
|
172
|
+
register 'ActiveRecord::ConnectionAdapters::MySQL::DatabaseStatements', 'active_record/connection_adapters/mysql/database_statements', MysqlAdapterSpy.new
|
173
|
+
else
|
174
|
+
register 'ActiveRecord::ConnectionAdapters::Mysql2Adapter', 'active_record/connection_adapters/mysql2_adapter', MysqlAdapterSpy.new
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|