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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/stackify_apm/config.rb +32 -5
  3. data/lib/stackify_apm/context.rb +4 -1
  4. data/lib/stackify_apm/context/prefix.rb +30 -0
  5. data/lib/stackify_apm/context/request/headers.rb +30 -0
  6. data/lib/stackify_apm/context_builder.rb +1 -0
  7. data/lib/stackify_apm/helper/database_helper.rb +38 -0
  8. data/lib/stackify_apm/instrumenter_helper.rb +87 -0
  9. data/lib/stackify_apm/middleware.rb +21 -3
  10. data/lib/stackify_apm/normalizers/active_record.rb +16 -8
  11. data/lib/stackify_apm/root_info.rb +6 -0
  12. data/lib/stackify_apm/serializers/transactions.rb +5 -0
  13. data/lib/stackify_apm/span/context.rb +39 -1
  14. data/lib/stackify_apm/spies.rb +4 -2
  15. data/lib/stackify_apm/spies/action_dispatch.rb +6 -1
  16. data/lib/stackify_apm/spies/curb.rb +41 -20
  17. data/lib/stackify_apm/spies/curb/easy.rb +220 -92
  18. data/lib/stackify_apm/spies/curb/multi.rb +26 -12
  19. data/lib/stackify_apm/spies/custom_instrumenter.rb +25 -4
  20. data/lib/stackify_apm/spies/httparty.rb +45 -24
  21. data/lib/stackify_apm/spies/httpclient.rb +41 -20
  22. data/lib/stackify_apm/spies/httprb.rb +39 -18
  23. data/lib/stackify_apm/spies/log4r.rb +59 -0
  24. data/lib/stackify_apm/spies/logger.rb +116 -0
  25. data/lib/stackify_apm/spies/logging.rb +65 -0
  26. data/lib/stackify_apm/spies/net_http.rb +38 -20
  27. data/lib/stackify_apm/spies/redis.rb +36 -30
  28. data/lib/stackify_apm/spies/sequel.rb +28 -11
  29. data/lib/stackify_apm/spies/sinatra_activerecord/mysql_adapter.rb +27 -25
  30. data/lib/stackify_apm/spies/sinatra_activerecord/postgresql_adapter.rb +27 -24
  31. data/lib/stackify_apm/spies/sinatra_activerecord/sqlite_adapter.rb +18 -8
  32. data/lib/stackify_apm/spies/stackify_logger.rb +28 -16
  33. data/lib/stackify_apm/spies/yell.rb +64 -0
  34. data/lib/stackify_apm/util.rb +10 -0
  35. data/lib/stackify_apm/version.rb +1 -1
  36. metadata +8 -2
@@ -125,6 +125,11 @@ module StackifyRubyAPM
125
125
 
126
126
  span_context = span.context && span.context.to_h
127
127
 
128
+ if span_context && !span_context[:SQL].nil? && span_context[:SQL].length > 100_000
129
+ span_context[:SQL] = span_context[:SQL][0..99_999]
130
+ span_context[:SQL_TRUNCATED] = 'true'
131
+ end
132
+
128
133
  {
129
134
  id: span.id,
130
135
  parent_id: span.parent_id,
@@ -17,6 +17,8 @@ module StackifyRubyAPM
17
17
  :COMPONENT_CATEGORY,
18
18
  :COMPONENT_DETAIL,
19
19
  :SQL,
20
+ :SQL_PARAMETERS,
21
+ :SQL_TRUNCATED,
20
22
  :MONGODB_COLLECTION,
21
23
  :METHOD,
22
24
  :URL,
@@ -27,11 +29,47 @@ module StackifyRubyAPM
27
29
  :CACHENAME,
28
30
  :THREAD_ID,
29
31
  :ID,
30
- :TRACKED_FUNC
32
+ :TRACKED_FUNC,
33
+ :LEVEL,
34
+ :MESSAGE,
35
+ :EXCEPTION,
36
+ :REQUEST_BODY,
37
+ :REQUEST_SIZE_BYTES,
38
+ :REQUEST_HEADERS,
39
+ :RESPONSE_BODY,
40
+ :RESPONSE_SIZE_BYTES,
41
+ :RESPONSE_HEADERS
31
42
  # rubocop:disable Style/VariableName
32
43
  def update_status(status)
33
44
  @STATUS = status
34
45
  end
46
+
47
+ def update_request_body(body)
48
+ @REQUEST_BODY = body.to_s
49
+ @REQUEST_SIZE_BYTES = body.to_s.length.to_s
50
+ end
51
+
52
+ def update_request_headers(headers)
53
+ @REQUEST_HEADERS = to_json_list(headers)
54
+ end
55
+
56
+ def update_response_body(body)
57
+ @RESPONSE_BODY = body.to_s
58
+ @RESPONSE_SIZE_BYTES = body.to_s.length.to_s
59
+ end
60
+
61
+ def update_response_headers(headers)
62
+ @RESPONSE_HEADERS = to_json_list(headers)
63
+ end
64
+
65
+ private
66
+ def to_json_list(header)
67
+ list_header = []
68
+ header.each do |key, value|
69
+ list_header << {key => value}
70
+ end
71
+ list_header.to_json
72
+ end
35
73
  # rubocop:enable Style/VariableName
36
74
  end
37
75
  end
@@ -85,8 +85,10 @@ module StackifyRubyAPM
85
85
  end
86
86
 
87
87
  def self.class_exists?(class_name)
88
- klass = Module.const_get(class_name)
89
- return klass.is_a?(Class)
88
+ if class_name
89
+ klass = Module.const_get(class_name)
90
+ return klass.is_a?(Class)
91
+ end
90
92
  rescue NameError
91
93
  return false
92
94
  end
@@ -14,7 +14,12 @@ module StackifyRubyAPM
14
14
  def render_exception(env, exception)
15
15
  # Creates exception log report
16
16
  #
17
- StackifyRubyAPM.report(exception)
17
+ begin
18
+ StackifyRubyAPM.report(exception)
19
+ rescue Exception => e
20
+ StackifyRubyAPM.agent.error '[ActionDispatchSpy] Error: repoting exception.'
21
+ StackifyRubyAPM.agent.error "[ActionDispatchSpy] #{e.inspect}"
22
+ end
18
23
  render_exception_without_apm env, exception
19
24
  end
20
25
  end
@@ -13,30 +13,51 @@ module StackifyRubyAPM
13
13
  def self.http(verb, url, _post_body = nil, _put_data = nil, &block)
14
14
  req = nil
15
15
  return http_without_apm(verb, url, _post_body = nil, _put_data = nil, &block) unless StackifyRubyAPM.current_transaction
16
- # Data configuration
17
- #
18
- method = verb
19
- uri = url.strip
20
- name = "#{method} #{uri}"
21
- type = "ext.Curb.#{method}"
22
- # Submits HTTP request
23
- #
24
- req = http_without_apm(verb, url, _post_body = nil, _put_data = nil, &block)
25
- # Builds span context
26
- #
27
- status_code = req.status.sub(/^0-9/, '').to_i
28
16
 
29
- ctx = Span::Context.new(
30
- CATEGORY: 'Web External',
31
- SUBCATEGORY: 'Execute',
32
- URL: uri,
33
- STATUS: status_code,
34
- METHOD: method
35
- )
17
+ begin
18
+ # Data configuration
19
+ #
20
+ method = verb
21
+ uri = url.strip
22
+ name = "#{method} #{uri}"
23
+ type = "ext.Curb.#{method}"
24
+
25
+ ctx = Span::Context.new(
26
+ CATEGORY: 'Web External',
27
+ SUBCATEGORY: 'Execute',
28
+ URL: uri,
29
+ STATUS: '',
30
+ METHOD: method
31
+ )
32
+ rescue Exception => e
33
+ StackifyRubyAPM.agent.error "[CurbSpy] Error: creating span context."
34
+ StackifyRubyAPM.agent.error "[CurbSpy] #{e.inspect}"
35
+ return http_without_apm(verb, url, _post_body = nil, _put_data = nil, &block)
36
+ end
37
+
36
38
  # Creates new span from HTTP result
37
39
  #
38
40
  StackifyRubyAPM.span name, type, context: ctx do
39
- req
41
+ # Submits HTTP request
42
+ #
43
+ res = http_without_apm(verb, url, _post_body = nil, _put_data = nil, &block)
44
+ begin
45
+ # Builds span context
46
+ #
47
+ status_code = res.status.sub(/^0-9/, '').to_i
48
+ ctx.update_status(status_code)
49
+
50
+ if StackifyRubyAPM.agent.config.prefix_enabled
51
+ ctx.update_request_body(_post_body || _put_data || "")
52
+ ctx.update_request_headers(res.headers || Hash.new)
53
+ ctx.update_response_body(res.body || "")
54
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
55
+ end
56
+ rescue Exception => e
57
+ StackifyRubyAPM.agent.error '[NetHTTPSpy] Error: getting status code or updating request/response context.'
58
+ StackifyRubyAPM.agent.error "[NetHTTPSpy] #{e.inspect}"
59
+ end
60
+ res
40
61
  end
41
62
  end
42
63
  end
@@ -19,132 +19,260 @@ module StackifyRubyAPM
19
19
  def self.perform(*args)
20
20
  req = nil
21
21
  return perform_without_apm(*args) unless StackifyRubyAPM.current_transaction
22
- # Data configuration
23
- @_apm_http_verb ||= :GET
24
- method = @_apm_http_verb
25
- uri = args[0].strip
26
- name = "#{method} #{uri}"
27
- type = "ext.Curb.Easy.#{method}"
28
- # Submits HTTP request
29
- #
30
- req = perform_without_apm(*args)
31
- # Builds span context
32
- #
33
- status_code = req.status.sub(/^0-9/, '').to_i
34
- ctx = Span::Context.new(
35
- CATEGORY: 'Web External',
36
- SUBCATEGORY: 'Execute',
37
- URL: uri,
38
- STATUS: status_code,
39
- METHOD: method
40
- )
22
+
23
+ begin
24
+ # Data configuration
25
+ @_apm_http_verb ||= :GET
26
+ method = @_apm_http_verb
27
+ uri = args[0].strip
28
+ name = "#{method} #{uri}"
29
+ type = "ext.Curb.Easy.#{method}"
30
+
31
+ # Builds span context
32
+ #
33
+ ctx = Span::Context.new(
34
+ CATEGORY: 'Web External',
35
+ SUBCATEGORY: 'Execute',
36
+ URL: uri,
37
+ STATUS: '',
38
+ METHOD: method
39
+ )
40
+ rescue Exception => e
41
+ StackifyRubyAPM.agent.error "[CurbEasySpy] Error: creating span context."
42
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
43
+ return perform_without_apm(*args)
44
+ end
45
+
41
46
  # Creates new span from HTTP result
42
47
  StackifyRubyAPM.span name, type, context: ctx do
43
- req
48
+ # Submits HTTP request
49
+ #
50
+ res = perform_without_apm(*args)
51
+
52
+ begin
53
+ status_code = res.status.sub(/^0-9/, '').to_i
54
+ ctx.update_status(status_code)
55
+
56
+ if StackifyRubyAPM.agent.config.prefix_enabled
57
+ ctx.update_request_body("")
58
+ ctx.update_request_headers(res.headers || Hash.new)
59
+ ctx.update_response_body(res.body || "")
60
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
61
+ end
62
+ rescue Exception => e
63
+ StackifyRubyAPM.agent.error '[CurbEasySpy] Error: getting status code or updating request/response context.'
64
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
65
+ end
66
+ res
44
67
  end
45
68
  end
46
69
 
47
70
  def self.http_post(*args)
48
71
  req = nil
49
72
  return http_post_without_apm(*args) unless StackifyRubyAPM.current_transaction
50
- # Data configuration
51
- #
52
- @_apm_http_verb = :POST
53
- method = @_apm_http_verb
54
- uri = args[0].strip
55
- name = "#{method} #{uri}"
56
- type = "ext.Curb.Easy.#{method}"
57
- req = http_post_without_apm(*args)
58
- status_code = req.status.sub(/^0-9/, '').to_i
59
-
60
- ctx = Span::Context.new(
61
- CATEGORY: 'Web External',
62
- SUBCATEGORY: 'Execute',
63
- URL: uri,
64
- STATUS: status_code,
65
- METHOD: method
66
- )
73
+
74
+ begin
75
+ # Data configuration
76
+ #
77
+ @_apm_http_verb = :POST
78
+ method = @_apm_http_verb
79
+ uri = args[0].strip
80
+ name = "#{method} #{uri}"
81
+ type = "ext.Curb.Easy.#{method}"
82
+
83
+ ctx = Span::Context.new(
84
+ CATEGORY: 'Web External',
85
+ SUBCATEGORY: 'Execute',
86
+ URL: uri,
87
+ STATUS: '',
88
+ METHOD: method
89
+ )
90
+ rescue Exception => e
91
+ StackifyRubyAPM.agent.error "[CurbEasySpy] Error: creating span context."
92
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
93
+ return http_post_without_apm(*args)
94
+ end
95
+
67
96
  # Creates new span from HTTP result
68
97
  StackifyRubyAPM.span name, type, context: ctx do
69
- req
98
+ res = http_post_without_apm(*args)
99
+
100
+ begin
101
+ status_code = res.status.sub(/^0-9/, '').to_i
102
+ ctx.update_status(status_code)
103
+
104
+ if StackifyRubyAPM.agent.config.prefix_enabled
105
+ if args.length == 2
106
+ request_body = args[1].to_s
107
+ elsif args.length > 2
108
+ request_body = {}
109
+ contents = args[1..-1]
110
+ contents.each do |data|
111
+ request_body[data.name] = data.content
112
+ end
113
+ request_body = request_body.to_json
114
+ else
115
+ request_body = ""
116
+ end
117
+
118
+ ctx.update_request_body(request_body)
119
+ ctx.update_request_headers(res.headers || Hash.new)
120
+ ctx.update_response_body(res.body || "")
121
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
122
+ end
123
+ rescue Exception => e
124
+ StackifyRubyAPM.agent.error '[CurbEasySpy] Error: getting status code or updating request/response context.'
125
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
126
+ end
127
+
128
+ res
70
129
  end
71
130
  end
72
131
 
73
132
  def self.http_put(url, data)
74
133
  req = nil
75
134
  return http_put_without_apm(url, data) unless StackifyRubyAPM.current_transaction
76
- # Data configuration
77
- #
78
- @_apm_http_verb = :PUT
79
- method = @_apm_http_verb
80
- uri = url.strip
81
- name = "#{method} #{uri}"
82
- type = "ext.Curb.Easy.#{method}"
83
- req = http_put_without_apm(url, data)
84
- status_code = req.status.sub(/^0-9/, '').to_i
85
-
86
- ctx = Span::Context.new(
87
- CATEGORY: 'Web External',
88
- SUBCATEGORY: 'Execute',
89
- URL: uri,
90
- STATUS: status_code,
91
- METHOD: method
92
- )
135
+
136
+ begin
137
+ # Data configuration
138
+ #
139
+ @_apm_http_verb = :PUT
140
+ method = @_apm_http_verb
141
+ uri = url.strip
142
+ name = "#{method} #{uri}"
143
+ type = "ext.Curb.Easy.#{method}"
144
+
145
+ ctx = Span::Context.new(
146
+ CATEGORY: 'Web External',
147
+ SUBCATEGORY: 'Execute',
148
+ URL: uri,
149
+ STATUS: '',
150
+ METHOD: method
151
+ )
152
+ rescue Exception => e
153
+ StackifyRubyAPM.agent.error "[CurbEasySpy] Error: creating span context."
154
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
155
+ return http_put_without_apm(url, data)
156
+ end
157
+
93
158
  # Creates new span from HTTP result
94
159
  StackifyRubyAPM.span name, type, context: ctx do
95
- req
160
+ res = http_put_without_apm(url, data)
161
+
162
+ begin
163
+ status_code = res.status.sub(/^0-9/, '').to_i
164
+ ctx.update_status(status_code)
165
+
166
+ if StackifyRubyAPM.agent.config.prefix_enabled
167
+ ctx.update_request_body(data)
168
+ ctx.update_request_headers(res.headers || Hash.new)
169
+ ctx.update_response_body(res.body || "")
170
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
171
+ end
172
+ rescue Exception => e
173
+ StackifyRubyAPM.agent.error '[CurbEasySpy] Error: getting status code or updating request/response context.'
174
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
175
+ end
176
+
177
+ res
96
178
  end
97
179
  end
98
180
 
99
181
  def self.http_get(*args)
100
182
  req = nil
101
183
  return http_get_without_apm(*args) unless StackifyRubyAPM.current_transaction
102
- # Data configuration
103
- #
104
- @_apm_http_verb = :GET
105
- method = @_apm_http_verb
106
- uri = args[0].strip
107
- name = "#{method} #{uri}"
108
- type = "ext.Curb.Easy.#{method}"
109
- req = http_get_without_apm(*args)
110
- status_code = req.status.sub(/^0-9/, '').to_i
111
-
112
- ctx = Span::Context.new(
113
- CATEGORY: 'Web External',
114
- SUBCATEGORY: 'Execute',
115
- URL: uri,
116
- STATUS: status_code,
117
- METHOD: method
118
- )
184
+
185
+ begin
186
+ # Data configuration
187
+ #
188
+ @_apm_http_verb = :GET
189
+ method = @_apm_http_verb
190
+ uri = args[0].strip
191
+ name = "#{method} #{uri}"
192
+ type = "ext.Curb.Easy.#{method}"
193
+
194
+ ctx = Span::Context.new(
195
+ CATEGORY: 'Web External',
196
+ SUBCATEGORY: 'Execute',
197
+ URL: uri,
198
+ STATUS: '',
199
+ METHOD: method
200
+ )
201
+ rescue Exception => e
202
+ StackifyRubyAPM.agent.error "[CurbEasySpy] Error: creating span context."
203
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
204
+ return http_get_without_apm(*args)
205
+ end
206
+
119
207
  # Creates new span from HTTP result
120
208
  StackifyRubyAPM.span name, type, context: ctx do
121
- req
209
+ res = http_get_without_apm(*args)
210
+
211
+ begin
212
+ status_code = res.status.sub(/^0-9/, '').to_i
213
+ ctx.update_status(status_code)
214
+
215
+ if StackifyRubyAPM.agent.config.prefix_enabled
216
+ ctx.update_request_body("")
217
+ ctx.update_request_headers(res.headers || Hash.new)
218
+ ctx.update_response_body(res.body || "")
219
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
220
+ end
221
+ rescue Exception => e
222
+ StackifyRubyAPM.agent.error '[CurbEasySpy] Error: getting status code or updating request/response context.'
223
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
224
+ end
225
+
226
+ res
122
227
  end
123
228
  end
124
229
 
125
230
  def self.http_delete(*args)
126
231
  req = nil
127
232
  return http_delete_without_apm(*args) unless StackifyRubyAPM.current_transaction
128
- # Data configuration
129
- #
130
- @_apm_http_verb = :DELETE
131
- method = @_apm_http_verb
132
- uri = args[0].strip
133
- name = "#{method} #{uri}"
134
- type = "ext.Curb.Easy.#{method}"
135
- req = http_delete_without_apm(*args)
136
- status_code = req.status.sub(/^0-9/, '').to_i
137
-
138
- ctx = Span::Context.new(
139
- CATEGORY: 'Web External',
140
- SUBCATEGORY: 'Execute',
141
- URL: uri,
142
- STATUS: status_code,
143
- METHOD: method
144
- )
233
+
234
+ begin
235
+ # Data configuration
236
+ #
237
+ @_apm_http_verb = :DELETE
238
+ method = @_apm_http_verb
239
+ uri = args[0].strip
240
+ name = "#{method} #{uri}"
241
+ type = "ext.Curb.Easy.#{method}"
242
+
243
+ ctx = Span::Context.new(
244
+ CATEGORY: 'Web External',
245
+ SUBCATEGORY: 'Execute',
246
+ URL: uri,
247
+ STATUS: '',
248
+ METHOD: method
249
+ )
250
+ rescue Exception => e
251
+ StackifyRubyAPM.agent.error "[CurbEasySpy] Error: creating span context."
252
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
253
+ return http_delete_without_apm(*args)
254
+ end
255
+
145
256
  # Creates new span from HTTP result
146
257
  StackifyRubyAPM.span name, type, context: ctx do
147
- req
258
+ res = http_delete_without_apm(*args)
259
+
260
+ begin
261
+ status_code = res.status.sub(/^0-9/, '').to_i
262
+ ctx.update_status(status_code)
263
+
264
+ if StackifyRubyAPM.agent.config.prefix_enabled
265
+ ctx.update_request_body("")
266
+ ctx.update_request_headers(res.headers || Hash.new)
267
+ ctx.update_response_body(res.body || "")
268
+ ctx.update_response_headers(res.proxy_headers || Hash.new)
269
+ end
270
+ rescue Exception => e
271
+ StackifyRubyAPM.agent.error '[CurbEasySpy] Error: getting status code or updating request/response context.'
272
+ StackifyRubyAPM.agent.error "[CurbEasySpy] #{e.inspect}"
273
+ end
274
+
275
+ res
148
276
  end
149
277
  end
150
278
  end