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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ec496ca2f97d6531e0e5059845fb078d60e194f0b2896a5148cc570f8de66c13
4
- data.tar.gz: 5dbc4a02c01e54b3d1276932f5d7528da2751d734a15926517595528b00dd0a8
3
+ metadata.gz: 5d95a01fea8c43d40a4cf1f0f541f539e31d9e022d985e70096d3b01260cbab8
4
+ data.tar.gz: c4a871133a02ba479ceea744f9f868ab34910c291e947fe62cc644330f6935c0
5
5
  SHA512:
6
- metadata.gz: 76c13b39665912b23fa8bd42cb75af0cfa455e83735814f167c768f380b96f411f4267670b8708f15d0aa6de9698d58055fba04ba6f8286dfb1efe51fb724361
7
- data.tar.gz: 2aa04cf139250db11e987a38ad213863a0d4dab9427561a1a2f63240a42005b37ab1dd9e8ae62df54159d6a05f9d7039df116fa41eea71f00ed69adfc173ebc3
6
+ metadata.gz: d4ca5f2806b494bc98ecb9828a01dbb3e459328401c8a880a4239d0ff8ad16073ace3a7e52ec02fb93b633f14f1b6493dd46daa381ee0ef7fc9ac23a1a319cdb
7
+ data.tar.gz: 873b62a9ef92ef3ea222ea7ed2fbfff26e41b2114ea030ac668646db394e0093feab0588d08e390776fcc38b8d6ff152cf6df1d472b886be0f102a71f5d0ab90
@@ -214,7 +214,10 @@ module StackifyRubyAPM
214
214
  httparty
215
215
  stackify_logger
216
216
  sidekiq
217
- delayed_job
217
+ delayed_job
218
+ faraday
219
+ sucker_punch
220
+ dynamo_db
218
221
  ]
219
222
  end
220
223
 
@@ -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 SQL_PARAMETERS to the existing object properties.
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[:SQL_PARAMETERS] = sqlParam.to_json if sqlParam.count > 0
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[: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
+ 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
- :SQL_PARAMETERS,
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
- :REQUEST_BODY,
37
- :REQUEST_SIZE_BYTES,
38
- :REQUEST_HEADERS,
39
- :RESPONSE_BODY,
40
- :RESPONSE_SIZE_BYTES,
41
- :RESPONSE_HEADERS
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
- @REQUEST_BODY = body.to_s
49
- @REQUEST_SIZE_BYTES = body.to_s.length.to_s
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
- @REQUEST_HEADERS = to_json_list(headers)
56
+ @PREFIX_REQUEST_HEADERS = to_json_list(headers)
54
57
  end
55
58
 
56
59
  def update_response_body(body)
57
- @RESPONSE_BODY = body.to_s
58
- @RESPONSE_SIZE_BYTES = body.to_s.length.to_s
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
- @RESPONSE_HEADERS = to_json_list(headers)
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
@@ -34,7 +34,8 @@ module StackifyRubyAPM
34
34
  CATEGORY: 'Log',
35
35
  SUBCATEGORY: 'Log4r',
36
36
  LEVEL: Log4r::LNAMES[logevent.level] || 'ANY',
37
- MESSAGE: log_message
37
+ MESSAGE: log_message,
38
+ PREFIX: 'TRUE'
38
39
  )
39
40
 
40
41
  if exception
@@ -96,7 +96,8 @@ module StackifyRubyAPM
96
96
  CATEGORY: 'Log',
97
97
  SUBCATEGORY: 'Logger',
98
98
  LEVEL: severity || 'ANY',
99
- MESSAGE: log_message
99
+ MESSAGE: log_message,
100
+ PREFIX: 'TRUE'
100
101
  )
101
102
 
102
103
  if exception
@@ -40,7 +40,8 @@ module StackifyRubyAPM
40
40
  CATEGORY: 'Log',
41
41
  SUBCATEGORY: 'Logging',
42
42
  LEVEL: LVL_LABEL[event.level] || 'ANY',
43
- MESSAGE: log_message
43
+ MESSAGE: log_message,
44
+ PREFIX: 'TRUE'
44
45
  )
45
46
 
46
47
  if exception
@@ -55,7 +55,9 @@ module StackifyRubyAPM
55
55
  #
56
56
  ctx = Span::Context.new(
57
57
  CATEGORY: 'MongoDB',
58
- MONGODB_COLLECTION: col
58
+ MONGODB_COLLECTION: col,
59
+ OPERATION: event.command_name.to_s,
60
+ URL: event.address.to_s
59
61
  )
60
62
 
61
63
  # Creates new span from Mongo event
@@ -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
- redis_nspace = !redis_details.blank? ? redis_details[0] : ''
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 !redis_details.blank? && redis_details[1]
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
- redis_key = args[0..1].join('/') if args.length > 1 && !args[1].include?('=')
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
@@ -39,7 +39,8 @@ module StackifyRubyAPM
39
39
  CATEGORY: 'Log',
40
40
  SUBCATEGORY: 'Yell',
41
41
  LEVEL: SEVERITIES[options.severity],
42
- MESSAGE: log_message.to_s
42
+ MESSAGE: log_message.to_s,
43
+ PREFIX: 'TRUE'
43
44
  )
44
45
 
45
46
  if exception.length > 0
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Sets the version of the APM
4
4
  module StackifyRubyAPM
5
- VERSION = '1.12.3'.freeze
5
+ VERSION = '1.14.4'.freeze
6
6
  end
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.12.3
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-07-30 00:00:00.000000000 Z
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