stackify-ruby-apm 1.11.1 → 1.12.3
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 +32 -5
- 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 +38 -0
- data/lib/stackify_apm/instrumenter_helper.rb +87 -0
- data/lib/stackify_apm/middleware.rb +21 -3
- data/lib/stackify_apm/normalizers/active_record.rb +16 -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 +39 -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/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 +59 -0
- data/lib/stackify_apm/spies/logger.rb +116 -0
- data/lib/stackify_apm/spies/logging.rb +65 -0
- data/lib/stackify_apm/spies/net_http.rb +38 -20
- data/lib/stackify_apm/spies/redis.rb +36 -30
- data/lib/stackify_apm/spies/sequel.rb +28 -11
- data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +27 -25
- data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +27 -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/yell.rb +64 -0
- data/lib/stackify_apm/util.rb +10 -0
- data/lib/stackify_apm/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ec496ca2f97d6531e0e5059845fb078d60e194f0b2896a5148cc570f8de66c13
|
4
|
+
data.tar.gz: 5dbc4a02c01e54b3d1276932f5d7528da2751d734a15926517595528b00dd0a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76c13b39665912b23fa8bd42cb75af0cfa455e83735814f167c768f380b96f411f4267670b8708f15d0aa6de9698d58055fba04ba6f8286dfb1efe51fb724361
|
7
|
+
data.tar.gz: 2aa04cf139250db11e987a38ad213863a0d4dab9427561a1a2f63240a42005b37ab1dd9e8ae62df54159d6a05f9d7039df116fa41eea71f00ed69adfc173ebc3
|
data/lib/stackify_apm/config.rb
CHANGED
@@ -26,7 +26,7 @@ module StackifyRubyAPM
|
|
26
26
|
environment_name: ENV['RAILS_ENV'] || ENV['RACK_ENV'],
|
27
27
|
already_instrumented_flag: false,
|
28
28
|
rum_auto_injection: false,
|
29
|
-
rum_enabled:
|
29
|
+
rum_enabled: true,
|
30
30
|
rum_cookie_path: '/',
|
31
31
|
rum_cookie_name: '.Stackify.Rum',
|
32
32
|
transport: StackifyRubyAPM::TRACE_LOG,
|
@@ -70,7 +70,8 @@ module StackifyRubyAPM
|
|
70
70
|
transport_http_endpoint: 'https://localhost:10601',
|
71
71
|
|
72
72
|
queue: true,
|
73
|
-
lambda_handler: ''
|
73
|
+
lambda_handler: '',
|
74
|
+
prefix_enabled: false
|
74
75
|
}.freeze
|
75
76
|
|
76
77
|
ENV_TO_KEY = {
|
@@ -97,7 +98,8 @@ module StackifyRubyAPM
|
|
97
98
|
'STACKIFY_FLUSH_INTERVAL' => 'flush_interval_seconds',
|
98
99
|
'STACKIFY_DISABLED_SPIES' => [:list, 'disabled_spies'],
|
99
100
|
'STACKIFY_QUEUE' => [:bool, 'queue'],
|
100
|
-
'STACKIFY_LAMBDA_HANDLER' => 'lambda_handler'
|
101
|
+
'STACKIFY_LAMBDA_HANDLER' => 'lambda_handler',
|
102
|
+
'STACKIFY_PREFIX_ENABLED' => [:bool, 'prefix_enabled']
|
101
103
|
}.freeze
|
102
104
|
|
103
105
|
def initialize(options = {})
|
@@ -105,6 +107,7 @@ module StackifyRubyAPM
|
|
105
107
|
set_from_args(options)
|
106
108
|
set_from_config_file
|
107
109
|
set_from_env
|
110
|
+
set_prefix_paths if @prefix_enabled
|
108
111
|
yield self if block_given?
|
109
112
|
debug_logger
|
110
113
|
StackifyRubyAPM::Util.host_os == 'WINDOWS' ? load_stackify_props_windows : load_stackify_props_linux
|
@@ -170,6 +173,7 @@ module StackifyRubyAPM
|
|
170
173
|
|
171
174
|
attr_accessor :queue
|
172
175
|
attr_accessor :lambda_handler
|
176
|
+
attr_accessor :prefix_enabled
|
173
177
|
|
174
178
|
attr_reader :client_id
|
175
179
|
attr_reader :device_id
|
@@ -214,6 +218,16 @@ module StackifyRubyAPM
|
|
214
218
|
]
|
215
219
|
end
|
216
220
|
|
221
|
+
def prefix_spies
|
222
|
+
return [] unless @prefix_enabled
|
223
|
+
%w[
|
224
|
+
logger
|
225
|
+
logging
|
226
|
+
log4r
|
227
|
+
yell
|
228
|
+
]
|
229
|
+
end
|
230
|
+
|
217
231
|
def enabled_spies
|
218
232
|
# check if the framework is rails or sinatra
|
219
233
|
sinatra_activerecord_spies = %w[
|
@@ -233,7 +247,7 @@ module StackifyRubyAPM
|
|
233
247
|
available_spies
|
234
248
|
end
|
235
249
|
|
236
|
-
new_available_spies - disabled_spies
|
250
|
+
new_available_spies + prefix_spies - disabled_spies
|
237
251
|
end
|
238
252
|
|
239
253
|
# Default Transport
|
@@ -254,7 +268,11 @@ module StackifyRubyAPM
|
|
254
268
|
|
255
269
|
def assign(options)
|
256
270
|
options.each do |key, value|
|
257
|
-
|
271
|
+
begin
|
272
|
+
send("#{key}=", value)
|
273
|
+
rescue Exception => e
|
274
|
+
info "[Config] Key: '#{key}' doesn't exist."
|
275
|
+
end
|
258
276
|
end
|
259
277
|
end
|
260
278
|
|
@@ -295,6 +313,14 @@ module StackifyRubyAPM
|
|
295
313
|
assign(YAML.load_file(config_file) || {})
|
296
314
|
end
|
297
315
|
|
316
|
+
# set log paths to prefix path if prefix_enabled is true
|
317
|
+
def set_prefix_paths
|
318
|
+
all_user_profile = ENV['ALLUSERSPROFILE'] || "C:\\ProgramData"
|
319
|
+
|
320
|
+
@log_path = StackifyRubyAPM::Util.host_os == 'WINDOWS' ? "#{all_user_profile}\\Stackify\\Agent\\debug\\stackify-ruby-apm-1.log" : "/usr/local/prefix/debug/stackify-ruby-apm-1.log"
|
321
|
+
@log_trace_path = StackifyRubyAPM::Util.host_os == 'WINDOWS' ? "#{all_user_profile}\\Stackify\\Agent\\log\\" : '/usr/local/prefix/log/'
|
322
|
+
end
|
323
|
+
|
298
324
|
# rubocop:disable Naming/AccessorMethodName
|
299
325
|
def set_rails(app)
|
300
326
|
self.application_name ||= format_name(application_name || app.class.parent_name).strip
|
@@ -382,6 +408,7 @@ module StackifyRubyAPM
|
|
382
408
|
info '[Config] environment_name must be String type.' unless @environment_name.is_a?(String) && defined?(@environment_name)
|
383
409
|
info '[Config] transport must be String type.' unless @transport.is_a?(String) && defined?(@transport)
|
384
410
|
info '[Config] Transport should be one of these values: [agent_socket, default, agent_http]. Should be a String.' if defined?(@transport) && !%w[agent_socket default agent_http].include?(@transport.downcase)
|
411
|
+
info '[Config] prefix_enabled must be Boolean type: true/false.' unless [TrueClass, FalseClass].include?(@prefix_enabled.class) && defined?(@prefix_enabled)
|
385
412
|
end
|
386
413
|
# rubocop:enable Metrics/CyclomaticComplexity
|
387
414
|
# rubocop:enable Metrics/PerceivedComplexity
|
data/lib/stackify_apm/context.rb
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
# This class initializes the parameters and variables for the context of Transaction/Span
|
4
4
|
|
5
|
+
require 'stackify_apm/context/prefix'
|
5
6
|
require 'stackify_apm/context/request'
|
7
|
+
require 'stackify_apm/context/request/headers'
|
6
8
|
require 'stackify_apm/context/request/socket'
|
7
9
|
require 'stackify_apm/context/request/url'
|
8
10
|
require 'stackify_apm/context/response'
|
@@ -12,12 +14,13 @@ module StackifyRubyAPM
|
|
12
14
|
class Context
|
13
15
|
include NaivelyHashable
|
14
16
|
|
15
|
-
attr_accessor :request, :response, :aws, :category
|
17
|
+
attr_accessor :request, :response, :aws, :category, :prefix
|
16
18
|
attr_reader :custom, :tags
|
17
19
|
|
18
20
|
def initialize
|
19
21
|
@custom = {}
|
20
22
|
@tags = {}
|
23
|
+
@prefix = Context::Prefix.new
|
21
24
|
end
|
22
25
|
|
23
26
|
# add aws context to context instance
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
class Context
|
5
|
+
# @api private
|
6
|
+
class Prefix
|
7
|
+
include NaivelyHashable
|
8
|
+
|
9
|
+
attr_accessor :response_body, :request_body
|
10
|
+
attr_reader :response_headers, :request_headers
|
11
|
+
|
12
|
+
def request_headers=(headers)
|
13
|
+
@request_headers = to_json_list(headers)
|
14
|
+
end
|
15
|
+
|
16
|
+
def response_headers=(headers)
|
17
|
+
@response_headers = to_json_list(headers)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def to_json_list(header)
|
22
|
+
list_header = []
|
23
|
+
header.each do |key, value|
|
24
|
+
list_header << {key => value}
|
25
|
+
end
|
26
|
+
list_header.to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module StackifyRubyAPM
|
4
|
+
# @api private
|
5
|
+
class Context
|
6
|
+
# @api private
|
7
|
+
class Request
|
8
|
+
# @api private
|
9
|
+
class Headers
|
10
|
+
include NaivelyHashable
|
11
|
+
|
12
|
+
def initialize(req)
|
13
|
+
@values = build_headers req
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :values
|
17
|
+
|
18
|
+
def build_headers req
|
19
|
+
env = req.env
|
20
|
+
headers = Hash[*env.select {|k,v| k.start_with? 'HTTP_'}
|
21
|
+
.collect {|k,v| [k.sub(/^HTTP_/, ''), v]}
|
22
|
+
.collect {|k,v| [k.split('_').collect(&:capitalize).join('-'), v]}
|
23
|
+
.sort
|
24
|
+
.flatten]
|
25
|
+
return headers
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -23,5 +23,43 @@ module DatabaseHelper
|
|
23
23
|
end
|
24
24
|
# rubocop:enable Metrics/CyclomaticComplexity
|
25
25
|
# rubocop:enable Metrics/PerceivedComplexity
|
26
|
+
|
27
|
+
# Check the prepared statement by placeholder if its valid
|
28
|
+
# placeholder - contains the prepared statement pattern.
|
29
|
+
# Placeholder for mysql, sqlite, jdbc oracle, db2 is ?, example "SELECT * FROM posts WHERE author = ? and id = ?"
|
30
|
+
# Placeholder for postgres is $1, $2,...$n, example "SELECT * FROM posts WHERE author = $1 and id = $2"
|
31
|
+
# statement - contains the db properties such as SQL, PROVIDER, etc.
|
32
|
+
# So if there's payload value we append SQL_PARAMETERS to the existing object properties.
|
33
|
+
# payload - contains the payload[:binds] which is the payload value/data of the placeholder.
|
34
|
+
# Example payload: {:sql=>"SELECT * FROM posts WHERE author = ? and id = ?", :db_adapter=>"mysql2::client", :binds=>["J.K. Rowling", 1]}
|
35
|
+
def check_prepared_stmt_by_placeholder(placeholder, statement, payload)
|
36
|
+
sqlParam = []
|
37
|
+
unless payload[:binds].nil?
|
38
|
+
payload[:binds].each_with_index do |record, idx|
|
39
|
+
if record && defined?(record.value)
|
40
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record.value)
|
41
|
+
elsif ((record && record.instance_of?(Array)) && defined?(record[1]))
|
42
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record[1])
|
43
|
+
else
|
44
|
+
StackifyRubyAPM::Util.pushToAryIndex(sqlParam, idx, record)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
statement[:SQL_PARAMETERS] = sqlParam.to_json if sqlParam.count > 0
|
48
|
+
true
|
49
|
+
else
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Common DB span properties shared to sequel, activerecord, etc.
|
55
|
+
def get_common_db_properties
|
56
|
+
{
|
57
|
+
CATEGORY: 'Database',
|
58
|
+
SUBCATEGORY: 'Execute',
|
59
|
+
COMPONENT_CATEGORY: 'DB Query',
|
60
|
+
COMPONENT_DETAIL: 'Execute SQL Query',
|
61
|
+
PROVIDER: 'generic'
|
62
|
+
}
|
63
|
+
end
|
26
64
|
end
|
27
65
|
include DatabaseHelper
|
@@ -189,6 +189,93 @@ module StackifyRubyAPM
|
|
189
189
|
@custom_class_info[current_class.to_s]['controller'] = true if class_path && class_path.include?('controllers')
|
190
190
|
@custom_class_info[current_class.to_s]['model'] = true if class_path && class_path.include?('models')
|
191
191
|
end
|
192
|
+
|
193
|
+
# Monkey patch the single ruby module file.
|
194
|
+
#
|
195
|
+
# tracked_func - trackedFunction variable in stackify.json
|
196
|
+
# current_module - module variable in stackify.json
|
197
|
+
# class_path - file_path variable in stackify.json
|
198
|
+
# options - other options such as trackedFunctionName
|
199
|
+
def self.patched_module(tracked_func, current_module, class_path, **options)
|
200
|
+
current_method = options[:current_method] || nil
|
201
|
+
tracked_function_name = options[:tracked_function_name] || nil
|
202
|
+
transaction = options[:is_transaction] || nil
|
203
|
+
mod_spy = "#{current_module}Spy"
|
204
|
+
|
205
|
+
unless @custom_instrumented[current_module.to_s]
|
206
|
+
@custom_instrumented[current_module.to_s] = {}
|
207
|
+
end
|
208
|
+
|
209
|
+
unless @custom_instrumented[current_module.to_s][current_method.to_s]
|
210
|
+
@custom_instrumented[current_module.to_s][current_method.to_s] = false
|
211
|
+
end
|
212
|
+
|
213
|
+
unless @custom_class_info[current_module.to_s]
|
214
|
+
@custom_class_info[current_module.to_s] = {}
|
215
|
+
end
|
216
|
+
|
217
|
+
unless @custom_class_info[current_module.to_s]['controller']
|
218
|
+
@custom_class_info[current_module.to_s]['controller'] = false
|
219
|
+
end
|
220
|
+
|
221
|
+
unless @custom_class_info[current_module.to_s]['model']
|
222
|
+
@custom_class_info[current_module.to_s]['model'] = false
|
223
|
+
end
|
224
|
+
|
225
|
+
return unless @custom_instrumented[current_module.to_s][current_method.to_s] == false
|
226
|
+
|
227
|
+
eval <<-RUBY
|
228
|
+
module #{mod_spy}
|
229
|
+
def self.install
|
230
|
+
#{current_module}.class_eval do
|
231
|
+
class<< self
|
232
|
+
alias_method "#{current_method}_without_apm", "#{current_method}"
|
233
|
+
|
234
|
+
def #{current_method}(*args, &block)
|
235
|
+
if StackifyRubyAPM.current_transaction.nil? && #{!transaction.nil?}
|
236
|
+
t = StackifyRubyAPM.transaction("custom.#{current_module}.#{current_method}", TRACETYPE)
|
237
|
+
begin
|
238
|
+
req = #{current_method}_without_apm(*args, &block)
|
239
|
+
rescue Exception => e
|
240
|
+
StackifyRubyAPM.report(e)
|
241
|
+
raise e
|
242
|
+
ensure
|
243
|
+
t.submit
|
244
|
+
end
|
245
|
+
return req
|
246
|
+
elsif StackifyRubyAPM.current_transaction
|
247
|
+
name = "Custom Instrument"
|
248
|
+
type = "#{current_module}##{current_method}"
|
249
|
+
ctx = if "#{tracked_func}" == 'true'
|
250
|
+
Span::Context.new(
|
251
|
+
CATEGORY: 'Ruby',
|
252
|
+
TRACKED_FUNC: "#{tracked_function_name}"
|
253
|
+
)
|
254
|
+
else
|
255
|
+
Span::Context.new(
|
256
|
+
CATEGORY: 'Ruby'
|
257
|
+
)
|
258
|
+
end
|
259
|
+
|
260
|
+
StackifyRubyAPM.span name, type, context: ctx do
|
261
|
+
#{current_method}_without_apm(*args, &block)
|
262
|
+
end
|
263
|
+
else
|
264
|
+
return #{current_method}_without_apm(*args, &block)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
StackifyRubyAPM::Spies.register current_module.to_s, class_path.to_s, #{mod_spy}, true, "#{current_method}", "#{tracked_func}", "#{tracked_function_name}"
|
273
|
+
RUBY
|
274
|
+
@custom_instrumented[current_module.to_s][current_method.to_s] = true
|
275
|
+
@custom_class_info[current_module.to_s]['controller'] = true if class_path && class_path.include?('controllers')
|
276
|
+
@custom_class_info[current_module.to_s]['model'] = true if class_path && class_path.include?('models')
|
277
|
+
end
|
278
|
+
|
192
279
|
# rubocop:enable Metrics/CyclomaticComplexity
|
193
280
|
# rubocop:enable Metrics/PerceivedComplexity
|
194
281
|
# rubocop:enable Lint/UselessAssignment
|
@@ -39,7 +39,8 @@ module StackifyRubyAPM
|
|
39
39
|
# rubocop:disable Metrics/PerceivedComplexity
|
40
40
|
def call(env)
|
41
41
|
begin
|
42
|
-
|
42
|
+
context = StackifyRubyAPM.build_context(env)
|
43
|
+
transaction = build_transaction(env, context) if running?
|
43
44
|
resp = @app.call env
|
44
45
|
|
45
46
|
@rack_status = resp[0].to_i
|
@@ -47,6 +48,8 @@ module StackifyRubyAPM
|
|
47
48
|
@rack_body = resp[2]
|
48
49
|
@configuration = config
|
49
50
|
|
51
|
+
build_prefix_context(transaction, context)
|
52
|
+
|
50
53
|
if okay_to_modify?
|
51
54
|
@configuration.already_instrumented_flag = true
|
52
55
|
if @configuration.rum_enabled.is_a?(TrueClass)
|
@@ -92,8 +95,9 @@ module StackifyRubyAPM
|
|
92
95
|
|
93
96
|
# Start of transaction building with params: name, type, context
|
94
97
|
#
|
95
|
-
def build_transaction(env)
|
96
|
-
|
98
|
+
def build_transaction(env, context=nil)
|
99
|
+
context = context || StackifyRubyAPM.build_context(env)
|
100
|
+
StackifyRubyAPM.transaction 'Rack', 'WEBAPP', context: context
|
97
101
|
end
|
98
102
|
|
99
103
|
def running?
|
@@ -129,5 +133,19 @@ module StackifyRubyAPM
|
|
129
133
|
def xhr?
|
130
134
|
@rack_headers['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'
|
131
135
|
end
|
136
|
+
|
137
|
+
# Add prefix instrument data to transaction context if enabled
|
138
|
+
def build_prefix_context(transaction, context)
|
139
|
+
return nil unless @configuration.prefix_enabled.is_a?(TrueClass)
|
140
|
+
|
141
|
+
source = nil
|
142
|
+
body = @rack_body
|
143
|
+
body.each { |fragment| source ? (source << fragment.to_s) : (source = fragment.to_s) }
|
144
|
+
|
145
|
+
transaction.context.prefix.request_body = context && context.request && context.request.body || ""
|
146
|
+
transaction.context.prefix.request_headers = context && context.request && context.request.headers || Hash.new
|
147
|
+
transaction.context.prefix.response_body = source || ""
|
148
|
+
transaction.context.prefix.response_headers = @rack_headers || Hash.new
|
149
|
+
end
|
132
150
|
end
|
133
151
|
end
|
@@ -20,6 +20,7 @@ module StackifyRubyAPM
|
|
20
20
|
return :skip if %w[SCHEMA CACHE].include?(payload[:name])
|
21
21
|
|
22
22
|
statement = query_variables(payload)
|
23
|
+
check_prepared_stmt(statement, payload)
|
23
24
|
name = payload[:sql] || payload[:name] || 'Default'
|
24
25
|
context = Span::Context.new(statement)
|
25
26
|
[name, @type, context]
|
@@ -28,14 +29,10 @@ module StackifyRubyAPM
|
|
28
29
|
private
|
29
30
|
|
30
31
|
def query_variables(payload)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
COMPONENT_DETAIL: 'Execute SQL Query',
|
36
|
-
SQL: payload[:sql],
|
37
|
-
PROVIDER: get_profiler(lookup_adapter)
|
38
|
-
}
|
32
|
+
props = get_common_db_properties
|
33
|
+
props[:PROVIDER] = get_profiler(lookup_adapter)
|
34
|
+
props[:SQL] = payload[:sql]
|
35
|
+
props
|
39
36
|
end
|
40
37
|
|
41
38
|
def lookup_adapter
|
@@ -44,6 +41,17 @@ module StackifyRubyAPM
|
|
44
41
|
debug '[SqlNormalizer] lookup_adapter err: ' + error.inspect.to_s
|
45
42
|
nil
|
46
43
|
end
|
44
|
+
|
45
|
+
def check_prepared_stmt(statement, payload)
|
46
|
+
if StackifyRubyAPM.agent.config.prefix_enabled
|
47
|
+
case get_profiler(lookup_adapter)
|
48
|
+
when 'generic', 'mysql', 'sqlite', 'oracle', 'db2'
|
49
|
+
check_prepared_stmt_by_placeholder(payload[:sql].include?('?'), statement, payload)
|
50
|
+
when 'postgresql'
|
51
|
+
check_prepared_stmt_by_placeholder(!!payload[:sql].match(/\$\d/), statement, payload)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
47
55
|
end
|
48
56
|
end
|
49
57
|
end
|
@@ -47,6 +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[:RESPONSE_BODY] = @transaction.context.prefix.response_body.to_s if @transaction.context.prefix && @transaction.context.prefix.response_body
|
51
|
+
hash[:RESPONSE_SIZE_BYTES] = @transaction.context.prefix.response_body.length.to_s if @transaction.context.prefix && @transaction.context.prefix.response_body
|
52
|
+
hash[:RESPONSE_HEADERS] = @transaction.context.prefix.response_headers.to_s if @transaction.context.prefix && @transaction.context.prefix.response_headers
|
53
|
+
hash[:REQUEST_BODY] = @transaction.context.prefix.request_body.to_s if @transaction.context.prefix && @transaction.context.prefix.request_body
|
54
|
+
hash[:REQUEST_SIZE_BYTES] = @transaction.context.prefix.request_body.length.to_s if @transaction.context.prefix && @transaction.context.prefix.request_body
|
55
|
+
hash[:REQUEST_HEADERS] = @transaction.context.prefix.request_headers.to_s if @transaction.context.prefix && @transaction.context.prefix.request_headers
|
50
56
|
hash
|
51
57
|
end
|
52
58
|
# rubocop:enable Metrics/CyclomaticComplexity
|