stackify-ruby-apm 1.10.4 → 1.14.0
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 +4 -4
- data/lib/stackify_apm/agent.rb +0 -2
- data/lib/stackify_apm/config.rb +36 -6
- data/lib/stackify_apm/context.rb +4 -1
- data/lib/stackify_apm/context/prefix.rb +30 -0
- data/lib/stackify_apm/context/request/headers.rb +30 -0
- data/lib/stackify_apm/context_builder.rb +1 -0
- data/lib/stackify_apm/helper/database_helper.rb +39 -0
- data/lib/stackify_apm/instrumenter_helper.rb +87 -0
- data/lib/stackify_apm/logger/logger_high_version.rb +5 -1
- data/lib/stackify_apm/logger/logger_lower_version.rb +5 -1
- data/lib/stackify_apm/middleware.rb +21 -3
- data/lib/stackify_apm/normalizers/active_record.rb +27 -8
- data/lib/stackify_apm/root_info.rb +6 -0
- data/lib/stackify_apm/serializers/transactions.rb +5 -0
- data/lib/stackify_apm/span/context.rb +42 -1
- data/lib/stackify_apm/spies.rb +4 -2
- data/lib/stackify_apm/spies/action_dispatch.rb +6 -1
- data/lib/stackify_apm/spies/curb.rb +41 -20
- data/lib/stackify_apm/spies/curb/easy.rb +220 -92
- data/lib/stackify_apm/spies/curb/multi.rb +26 -12
- data/lib/stackify_apm/spies/custom_instrumenter.rb +25 -4
- data/lib/stackify_apm/spies/dynamo_db.rb +51 -0
- data/lib/stackify_apm/spies/faraday.rb +87 -0
- data/lib/stackify_apm/spies/httparty.rb +45 -24
- data/lib/stackify_apm/spies/httpclient.rb +41 -20
- data/lib/stackify_apm/spies/httprb.rb +39 -18
- data/lib/stackify_apm/spies/log4r.rb +60 -0
- data/lib/stackify_apm/spies/logger.rb +117 -0
- data/lib/stackify_apm/spies/logging.rb +66 -0
- data/lib/stackify_apm/spies/mongo.rb +3 -1
- data/lib/stackify_apm/spies/net_http.rb +38 -20
- data/lib/stackify_apm/spies/redis.rb +39 -30
- data/lib/stackify_apm/spies/sequel.rb +28 -11
- data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +48 -25
- data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +35 -24
- data/lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb +18 -8
- data/lib/stackify_apm/spies/stackify_logger.rb +28 -16
- data/lib/stackify_apm/spies/sucker_punch.rb +39 -0
- data/lib/stackify_apm/spies/yell.rb +65 -0
- data/lib/stackify_apm/util.rb +10 -9
- data/lib/stackify_apm/version.rb +1 -1
- metadata +11 -2
@@ -2,12 +2,15 @@
|
|
2
2
|
|
3
3
|
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
4
4
|
|
5
|
+
require 'stackify_apm/helper/database_helper'
|
6
|
+
|
5
7
|
module StackifyRubyAPM
|
6
8
|
# @api private
|
7
9
|
module Spies
|
8
10
|
# @api private
|
9
11
|
class MysqlAdapterSpy
|
10
12
|
TYPE = 'db.sinatra_active_record.sql'.freeze
|
13
|
+
DEFAULT_PORT = 3306
|
11
14
|
if ActiveRecord::VERSION::MAJOR.to_i >= 5
|
12
15
|
def install
|
13
16
|
ActiveRecord::ConnectionAdapters::MySQL::DatabaseStatements.class_eval do
|
@@ -22,14 +25,10 @@ module StackifyRubyAPM
|
|
22
25
|
exec_update_without_apm(sql, name, binds)
|
23
26
|
end
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
30
|
-
SQL: sql,
|
31
|
-
PROVIDER: 'mysql'
|
32
|
-
)
|
28
|
+
payload = {sql: sql, binds: binds}
|
29
|
+
statement = query_variables(payload)
|
30
|
+
check_prepared_stmt(statement, payload)
|
31
|
+
ctx = Span::Context.new(statement)
|
33
32
|
|
34
33
|
result = exec_update_without_apm(sql, name, binds)
|
35
34
|
|
@@ -45,14 +44,10 @@ module StackifyRubyAPM
|
|
45
44
|
exec_delete_without_apm(sql, name, binds)
|
46
45
|
end
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
53
|
-
SQL: sql,
|
54
|
-
PROVIDER: 'mysql'
|
55
|
-
)
|
47
|
+
payload = {sql: sql, binds: binds}
|
48
|
+
statement = query_variables(payload)
|
49
|
+
check_prepared_stmt(statement, payload)
|
50
|
+
ctx = Span::Context.new(statement)
|
56
51
|
|
57
52
|
result = exec_delete_without_apm(sql, name, binds)
|
58
53
|
|
@@ -69,22 +64,38 @@ module StackifyRubyAPM
|
|
69
64
|
exec_query_without_apm(sql, name, binds)
|
70
65
|
end
|
71
66
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
77
|
-
SQL: sql,
|
78
|
-
PROVIDER: 'mysql'
|
79
|
-
)
|
67
|
+
payload = {sql: sql, binds: binds}
|
68
|
+
statement = query_variables(payload)
|
69
|
+
check_prepared_stmt(statement, payload)
|
70
|
+
ctx = Span::Context.new(statement)
|
80
71
|
|
81
72
|
result = exec_query_without_apm(sql, name, binds)
|
82
|
-
|
83
73
|
StackifyRubyAPM.span name, TYPE, context: ctx do
|
84
74
|
return result
|
85
75
|
end
|
86
76
|
end
|
87
77
|
# rubocop:enable Lint/UnusedMethodArgument
|
78
|
+
|
79
|
+
def query_variables(payload)
|
80
|
+
props = get_common_db_properties
|
81
|
+
props[:PROVIDER] = 'mysql'
|
82
|
+
props[:SQL] = payload[:sql]
|
83
|
+
props[:URL] = get_host unless !get_host
|
84
|
+
props
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_prepared_stmt(statement, payload)
|
88
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
89
|
+
check_prepared_stmt_by_placeholder(payload[:sql].include?('?'), statement, payload)
|
90
|
+
end
|
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
|
88
99
|
end
|
89
100
|
end
|
90
101
|
else
|
@@ -110,6 +121,7 @@ module StackifyRubyAPM
|
|
110
121
|
SQL: sql,
|
111
122
|
PROVIDER: 'mysql'
|
112
123
|
)
|
124
|
+
ctx[:URL] = get_host unless !get_host
|
113
125
|
|
114
126
|
result = exec_query_without_apm(sql, name, binds)
|
115
127
|
|
@@ -133,6 +145,7 @@ module StackifyRubyAPM
|
|
133
145
|
SQL: sql,
|
134
146
|
PROVIDER: 'mysql'
|
135
147
|
)
|
148
|
+
ctx[:URL] = get_host unless !get_host
|
136
149
|
|
137
150
|
result = exec_delete_without_apm(sql, name, binds)
|
138
151
|
|
@@ -156,6 +169,7 @@ module StackifyRubyAPM
|
|
156
169
|
SQL: sql,
|
157
170
|
PROVIDER: 'mysql'
|
158
171
|
)
|
172
|
+
ctx[:URL] = get_host unless !get_host
|
159
173
|
|
160
174
|
result = exec_update_without_apm(sql, name, binds)
|
161
175
|
|
@@ -179,6 +193,7 @@ module StackifyRubyAPM
|
|
179
193
|
SQL: sql,
|
180
194
|
PROVIDER: 'mysql'
|
181
195
|
)
|
196
|
+
ctx[:URL] = get_host unless !get_host
|
182
197
|
|
183
198
|
result = exec_insert_without_apm(sql, name, binds, _pk = nil, _sequence_name = nil)
|
184
199
|
|
@@ -186,6 +201,14 @@ module StackifyRubyAPM
|
|
186
201
|
return result
|
187
202
|
end
|
188
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
|
+
|
189
212
|
end
|
190
213
|
end
|
191
214
|
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
4
4
|
|
5
|
+
require 'stackify_apm/helper/database_helper'
|
6
|
+
|
5
7
|
module StackifyRubyAPM
|
6
8
|
# @api private
|
7
9
|
module Spies
|
@@ -22,15 +24,11 @@ module StackifyRubyAPM
|
|
22
24
|
exec_update_without_apm(sql, name, binds)
|
23
25
|
end
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
COMPONENT_CATEGORY: 'DB Query',
|
29
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
30
|
-
SQL: sql,
|
31
|
-
PROVIDER: 'postgresql'
|
32
|
-
)
|
27
|
+
payload = {sql: sql, binds: binds}
|
28
|
+
statement = query_variables(payload)
|
29
|
+
check_prepared_stmt(statement, payload)
|
33
30
|
|
31
|
+
ctx = Span::Context.new(statement)
|
34
32
|
result = exec_update_without_apm(sql, name, binds)
|
35
33
|
|
36
34
|
StackifyRubyAPM.span name, TYPE, context: ctx do
|
@@ -45,15 +43,11 @@ module StackifyRubyAPM
|
|
45
43
|
exec_delete_without_apm(sql, name, binds)
|
46
44
|
end
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
COMPONENT_CATEGORY: 'DB Query',
|
52
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
53
|
-
SQL: sql,
|
54
|
-
PROVIDER: 'postgresql'
|
55
|
-
)
|
46
|
+
payload = {sql: sql, binds: binds}
|
47
|
+
statement = query_variables(payload)
|
48
|
+
check_prepared_stmt(statement, payload)
|
56
49
|
|
50
|
+
ctx = Span::Context.new(statement)
|
57
51
|
result = exec_delete_without_apm(sql, name, binds)
|
58
52
|
|
59
53
|
StackifyRubyAPM.span name, TYPE, context: ctx do
|
@@ -69,15 +63,11 @@ module StackifyRubyAPM
|
|
69
63
|
exec_query_without_apm(sql, name, binds)
|
70
64
|
end
|
71
65
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
COMPONENT_CATEGORY: 'DB Query',
|
76
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
77
|
-
SQL: sql,
|
78
|
-
PROVIDER: 'postgresql'
|
79
|
-
)
|
66
|
+
payload = {sql: sql, binds: binds}
|
67
|
+
statement = query_variables(payload)
|
68
|
+
check_prepared_stmt(statement, payload)
|
80
69
|
|
70
|
+
ctx = Span::Context.new(statement)
|
81
71
|
result = exec_query_without_apm(sql, name, binds)
|
82
72
|
|
83
73
|
StackifyRubyAPM.span name, TYPE, context: ctx do
|
@@ -85,6 +75,27 @@ module StackifyRubyAPM
|
|
85
75
|
end
|
86
76
|
end
|
87
77
|
# rubocop:enable Lint/UnusedMethodArgument
|
78
|
+
|
79
|
+
def query_variables(payload)
|
80
|
+
props = get_common_db_properties
|
81
|
+
props[:PROVIDER] = 'postgresql'
|
82
|
+
props[:SQL] = payload[:sql]
|
83
|
+
props[:URL] = get_host unless !get_host
|
84
|
+
props
|
85
|
+
end
|
86
|
+
|
87
|
+
def check_prepared_stmt(statement, payload)
|
88
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
89
|
+
check_prepared_stmt_by_placeholder(!!payload[:sql].match(/\$\d/), statement, payload)
|
90
|
+
end
|
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
|
88
99
|
end
|
89
100
|
end
|
90
101
|
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
# Spies for active record when sinatra framework is used and active_record is being extended. (mysql adapter)
|
4
4
|
|
5
|
+
require 'stackify_apm/helper/database_helper'
|
6
|
+
|
5
7
|
module StackifyRubyAPM
|
6
8
|
# @api private
|
7
9
|
module Spies
|
@@ -21,15 +23,11 @@ module StackifyRubyAPM
|
|
21
23
|
exec_query_without_apm(sql, name, binds)
|
22
24
|
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
COMPONENT_CATEGORY: 'DB Query',
|
28
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
29
|
-
SQL: sql,
|
30
|
-
PROVIDER: 'generic'
|
31
|
-
)
|
26
|
+
payload = {sql: sql, binds: binds}
|
27
|
+
statement = query_variables(payload)
|
28
|
+
check_prepared_stmt(statement, payload)
|
32
29
|
|
30
|
+
ctx = Span::Context.new(statement)
|
33
31
|
result = exec_query_without_apm(sql, name, binds)
|
34
32
|
|
35
33
|
StackifyRubyAPM.span name, TYPE, context: ctx do
|
@@ -37,6 +35,18 @@ module StackifyRubyAPM
|
|
37
35
|
end
|
38
36
|
end
|
39
37
|
# rubocop:enable Lint/UnusedMethodArgument
|
38
|
+
|
39
|
+
def query_variables(payload)
|
40
|
+
props = get_common_db_properties
|
41
|
+
props[:SQL] = payload[:sql]
|
42
|
+
props
|
43
|
+
end
|
44
|
+
|
45
|
+
def check_prepared_stmt(statement, payload)
|
46
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
47
|
+
check_prepared_stmt_by_placeholder(payload[:sql].include?('?'), statement, payload)
|
48
|
+
end
|
49
|
+
end
|
40
50
|
end
|
41
51
|
end
|
42
52
|
end
|
@@ -14,15 +14,21 @@ module StackifyRubyAPM
|
|
14
14
|
def log_message_task(level, msg, call_trace)
|
15
15
|
return log_message_task_without_apm(level, msg, call_trace) unless StackifyRubyAPM.current_transaction
|
16
16
|
|
17
|
-
|
18
|
-
|
17
|
+
begin
|
18
|
+
trans_id = StackifyRubyAPM.current_transaction.id
|
19
|
+
log_uuid = SecureRandom.uuid
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
# build span context
|
22
|
+
ctx = Span::Context.new(
|
23
|
+
CATEGORY: 'Stackify',
|
24
|
+
SUBCATEGORY: 'Log',
|
25
|
+
ID: log_uuid # matching the MsgObject id
|
26
|
+
)
|
27
|
+
rescue Exception => e
|
28
|
+
StackifyRubyAPM.agent.error "[StackifyLoggerSpy] Error: creating span context."
|
29
|
+
StackifyRubyAPM.agent.error "[StackifyLoggerSpy] #{e.inspect}"
|
30
|
+
return log_message_task_without_apm(level, msg, call_trace)
|
31
|
+
end
|
26
32
|
|
27
33
|
# create log span
|
28
34
|
StackifyRubyAPM.span(msg, 'stackify.log', context: ctx) do
|
@@ -34,15 +40,21 @@ module StackifyRubyAPM
|
|
34
40
|
def log_exception_task(level, ex)
|
35
41
|
return log_exception_task_without_apm(level, ex) unless StackifyRubyAPM.current_transaction
|
36
42
|
|
37
|
-
|
38
|
-
|
43
|
+
begin
|
44
|
+
trans_id = StackifyRubyAPM.agent.current_transaction.id
|
45
|
+
log_uuid = SecureRandom.uuid
|
39
46
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
47
|
+
# build span context
|
48
|
+
ctx = Span::Context.new(
|
49
|
+
CATEGORY: 'Stackify',
|
50
|
+
SUBCATEGORY: 'Log',
|
51
|
+
ID: log_uuid # matching the MsgObject id
|
52
|
+
)
|
53
|
+
rescue Exception => e
|
54
|
+
StackifyRubyAPM.agent.error "[StackifyLoggerSpy] Error: creating span context."
|
55
|
+
StackifyRubyAPM.agent.error "[StackifyLoggerSpy] #{e.inspect}"
|
56
|
+
return log_exception_task_without_apm(level, ex)
|
57
|
+
end
|
46
58
|
|
47
59
|
# create log span
|
48
60
|
StackifyRubyAPM.span(ex.message, 'stackify.log', context: ctx) do
|
@@ -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
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Monkey patch for the Yell::Logger class for logging log messages.
|
4
|
+
#
|
5
|
+
module StackifyRubyAPM
|
6
|
+
# @api private
|
7
|
+
module Spies
|
8
|
+
# @api private
|
9
|
+
class YellSpy
|
10
|
+
SEVERITIES = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL', 'UNKNOWN'].freeze
|
11
|
+
|
12
|
+
def install
|
13
|
+
Yell::Logger.module_eval do
|
14
|
+
alias_method 'add_without_apm', 'add'
|
15
|
+
|
16
|
+
# Log messages
|
17
|
+
def add(options, *messages, &block)
|
18
|
+
return add_without_apm(options, *messages, &block) unless StackifyRubyAPM.current_transaction
|
19
|
+
|
20
|
+
begin
|
21
|
+
name = 'yell;'
|
22
|
+
type = 'ext.yell'
|
23
|
+
log_message = []
|
24
|
+
exception = []
|
25
|
+
|
26
|
+
messages.each { |msg|
|
27
|
+
case msg
|
28
|
+
when ::String
|
29
|
+
log_message.push(msg)
|
30
|
+
when ::Exception
|
31
|
+
log_message.push(msg.message)
|
32
|
+
exception.push("(#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }")
|
33
|
+
else
|
34
|
+
log_message.push(msg.inspect)
|
35
|
+
end
|
36
|
+
}
|
37
|
+
|
38
|
+
ctx = Span::Context.new(
|
39
|
+
CATEGORY: 'Log',
|
40
|
+
SUBCATEGORY: 'Yell',
|
41
|
+
LEVEL: SEVERITIES[options.severity],
|
42
|
+
MESSAGE: log_message.to_s,
|
43
|
+
PREFIX: 'TRUE'
|
44
|
+
)
|
45
|
+
|
46
|
+
if exception.length > 0
|
47
|
+
ctx.EXCEPTION = exception.to_s
|
48
|
+
end
|
49
|
+
rescue Exception => e
|
50
|
+
StackifyRubyAPM.agent.error "[YellSpy] Error: creating span context."
|
51
|
+
StackifyRubyAPM.agent.error "[YellSpy] #{e.inspect}"
|
52
|
+
return add_without_apm(options, *messages, &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
StackifyRubyAPM.span name, type, context: ctx do
|
56
|
+
add_without_apm(options, *messages, &block)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
register 'Yell', 'yell', YellSpy.new
|
64
|
+
end
|
65
|
+
end
|