stackify-ruby-apm 1.11.1 → 1.12.3
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/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
|