atatus 1.4.0 → 1.6.2

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: 651694b5c78acd1f1582c30f1b28715b6a653c2b125a75613a19b7ae86361d9b
4
- data.tar.gz: 4a8e5ee631f32b09942bb6ae53a72531c4e7ffe2677194ee7f19f81dfd4c9eeb
3
+ metadata.gz: 48a2777c09d7af196314fb322c9a55feadb46f50d90ffd88976ff978eb5039a2
4
+ data.tar.gz: 59f1f63ebd4ad84f23359cc2c96ccb62e0c0eabceaa6b48bf63c711c3383bf64
5
5
  SHA512:
6
- metadata.gz: 0400c2f1f8bdd57366d49d5a05f8d4dc49bc804e5dc263cfe9771043a021a47c08d7544af1adb9408a2c517c7839d20e6e7bb48329038e684c35a61bbf0db210
7
- data.tar.gz: 76eb02d1bf4cebf184ff8df44f71d553f64fe9e9dfb75aeb4c3e214a97a3dbc6efc7797a34321f019a0fc15be06800ef575efae6dc580aa1061037aeb1c13f4d
6
+ metadata.gz: 1a705d56af3228c31ce400a16eae3d961fe2bbcae949db3effc4828682563bd4ce3070adb14613cb096caa48d71e8ccce2969dc21f4b0c910c73ca99b28bf566
7
+ data.tar.gz: 30461593c406cf6f7b8f2e08c9bef4aa64b9f60f0f4c2b3f0bff9de1cff8a26f5cf25e07507b263e8638a37345916f15d479eb11bcb3e58f69a7f34d79d51d70
data/CHANGELOG.md CHANGED
@@ -4,6 +4,27 @@ All notable changes to this project will be documented in this file.
4
4
 
5
5
  This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## 1.6.2 (Mon, 31 Jan 2022)
8
+
9
+ - Fixed config environment.
10
+ - Supported ignore failure patterns, ignore exceptions and ignore transactions.
11
+
12
+
13
+ ## 1.6.1 (Wed, 29 Dec 2021)
14
+
15
+ - Fixed a specific case where span duration goes less than 0.
16
+
17
+
18
+ ## 1.6.0 (Fri, 24 Dec 2021)
19
+
20
+ - Added support for set custom data.
21
+ - Fixed the span timing issue.
22
+
23
+
24
+ ## 1.5.0 (Thu, 27 May 2021)
25
+
26
+ - Fixed issue in status code conversion.
27
+
7
28
 
8
29
  ## 1.4.0 (Tue, 15 Sept 2020)
9
30
 
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- All components of this product are Copyright (c) 2020 Atatus. All rights reserved.
1
+ All components of this product are Copyright (c) 2022 Atatus. All rights reserved.
2
2
 
3
3
  Except as otherwise expressly provided in this Agreement,
4
4
  End User shall not (and shall not permit any third party to):
@@ -7,7 +7,7 @@ require 'atatus/collector/hist'
7
7
  require 'atatus/collector/layer'
8
8
  require 'atatus/collector/transport'
9
9
 
10
- SpanTiming = Struct.new(:start, :end)
10
+ SpanTiming = Struct.new(:name, :type, :subtype, :start, :end, :duration, :id, :transaction_id)
11
11
 
12
12
  module Atatus
13
13
  module Collector
@@ -42,6 +42,7 @@ module Atatus
42
42
  @metrics_lock = Mutex.new
43
43
  @metrics_agg = []
44
44
 
45
+ @hostinfo_response = {}
45
46
  @transport = Atatus::BaseTransport.new(config)
46
47
  @collect_counter = 0
47
48
  @running = false
@@ -79,13 +80,38 @@ module Atatus
79
80
 
80
81
  def add_error(error)
81
82
  ensure_worker_running
82
-
83
- @errors_lock.synchronize do
84
- if @errors_aggs.length < 20
85
- @errors_aggs.push(error)
86
- else
87
- i = rand(20)
88
- @errors_aggs[i] = error
83
+ ignore_error = false
84
+ if
85
+ !error.exception.nil? &&
86
+ !error.exception.type.nil? &&
87
+ !error.exception.message.nil?
88
+ then
89
+ if @hostinfo_response.key?("ignoreExceptionPatterns")
90
+ @hostinfo_response['ignoreExceptionPatterns'].each do |k, v|
91
+ if error.exception.type.match(k)
92
+ exception_values = v
93
+ if exception_values.length == 0
94
+ ignore_error = true
95
+ else
96
+ exception_values.each do |value|
97
+ if error.exception.message.include?(value)
98
+ ignore_error = true
99
+ end
100
+ end
101
+ end
102
+ break
103
+ end
104
+ end
105
+ end
106
+ end
107
+ if ignore_error == false
108
+ @errors_lock.synchronize do
109
+ if @errors_aggs.length < 20
110
+ @errors_aggs.push(error)
111
+ else
112
+ i = rand(20)
113
+ @errors_aggs[i] = error
114
+ end
89
115
  end
90
116
  end
91
117
  end
@@ -156,6 +182,19 @@ module Atatus
156
182
  return
157
183
  end
158
184
 
185
+ ignore_txn = false
186
+ if @hostinfo_response.key?("ignoreTxnNamePatterns")
187
+ @hostinfo_response['ignoreTxnNamePatterns'].each do |k|
188
+ if txn.name.match(k)
189
+ ignore_txn = true
190
+ break
191
+ end
192
+ end
193
+ end
194
+ if ignore_txn == true
195
+ return
196
+ end
197
+
159
198
  return if txn.name.empty?
160
199
  return if txn.duration <= 0
161
200
 
@@ -204,16 +243,7 @@ module Atatus
204
243
 
205
244
  if span.timestamp >= txn.timestamp
206
245
  start = Util.ms(span.timestamp - txn.timestamp)
207
- spans_tuple.push(SpanTiming.new(start, start + Util.ms(span.duration)))
208
- if !@txns_agg[txn.name].spans.key?(span.name)
209
- kind = Layer.span_kind(span.type)
210
- type = Layer.span_type(span.subtype)
211
- @txns_agg[txn.name].spans[span.name] = Layer.new(type, kind, span.duration)
212
- @txns_agg[txn.name].spans[span.name].id = span.id
213
- @txns_agg[txn.name].spans[span.name].pid = span.transaction_id
214
- else
215
- @txns_agg[txn.name].spans[span.name].aggregate! span.duration
216
- end
246
+ spans_tuple.push(SpanTiming.new(span.name, span.type, span.subtype, start, start + Util.ms(span.duration), span.duration, span.id, span.transaction_id))
217
247
  end
218
248
  end
219
249
  end
@@ -222,6 +252,40 @@ module Atatus
222
252
  ruby_time = Util.ms(txn.duration)
223
253
  else
224
254
  spans_tuple.sort! {| a, b | a[:start] <=> b[:start] }
255
+ j = 0
256
+ while j < spans_tuple.length
257
+ if spans_tuple[j].subtype == 'controller' || spans_tuple[j].subtype == 'view' || spans_tuple[j].subtype == 'tilt'
258
+ k = j+1
259
+ while k < spans_tuple.length
260
+ if spans_tuple[k].start >= spans_tuple[j].end
261
+ break
262
+ else
263
+ if spans_tuple[k].end <= spans_tuple[j].end
264
+ spans_tuple[j].duration -= Util.us(spans_tuple[k].end - spans_tuple[k].start)
265
+ else
266
+ spans_tuple[j].duration -= Util.us(spans_tuple[j].end - spans_tuple[k].start)
267
+ end
268
+ end
269
+ k += 1
270
+ end
271
+ if spans_tuple[j].duration <= 0
272
+ spans_tuple[j].duration = 1
273
+ end
274
+ end
275
+
276
+ if !@txns_agg[txn.name].spans.key?(spans_tuple[j].name)
277
+ kind = Layer.span_kind(spans_tuple[j].type)
278
+ type = Layer.span_type(spans_tuple[j].subtype)
279
+ @txns_agg[txn.name].spans[spans_tuple[j].name] = Layer.new(type, kind, spans_tuple[j].duration)
280
+ @txns_agg[txn.name].spans[spans_tuple[j].name].id = spans_tuple[j].id
281
+ @txns_agg[txn.name].spans[spans_tuple[j].name].pid = spans_tuple[j].transaction_id
282
+ else
283
+ @txns_agg[txn.name].spans[spans_tuple[j].name].aggregate! spans_tuple[j].duration
284
+ end
285
+
286
+ j += 1
287
+ end
288
+
225
289
  ruby_time = spans_tuple[0].start
226
290
  span_end = spans_tuple[0].end
227
291
  j = 0
@@ -270,24 +334,45 @@ module Atatus
270
334
  !txn.context.response.nil? &&
271
335
  !txn.context.response.status_code.nil?
272
336
  then
273
- status_code = txn.context.response.status_code
274
-
337
+ status_code = txn.context.response.status_code.to_i
338
+ ignore_status_code = false
275
339
  if status_code >= 400 && status_code != 404
276
- if !@error_metrics_agg.key?(txn.name)
277
- @error_metrics_agg[txn.name] = {status_code => 1}
278
- else
279
- if !@error_metrics_agg[txn.name].key?(status_code)
280
- @error_metrics_agg[txn.name][status_code] = 1
281
- else
282
- @error_metrics_agg[txn.name][status_code] += 1
340
+ if @hostinfo_response.key?("ignoreHTTPFailurePatterns")
341
+ @hostinfo_response['ignoreHTTPFailurePatterns'].each do |k, v|
342
+ if txn.name.match(k)
343
+ status_code_array_s = v
344
+ if status_code_array_s.length == 0
345
+ ignore_status_code = true
346
+ else
347
+ status_code_array_s.each do |code|
348
+ if code == txn.context.response.status_code.to_s
349
+ ignore_status_code = true
350
+ end
351
+ end
352
+ end
353
+ break
354
+ end
283
355
  end
284
356
  end
357
+ if ignore_status_code == false
358
+ if !@error_metrics_agg.key?(txn.name)
359
+ @error_metrics_agg[txn.name] = {status_code => 1}
360
+ else
361
+ if !@error_metrics_agg[txn.name].key?(status_code)
362
+ @error_metrics_agg[txn.name][status_code] = 1
363
+ else
364
+ @error_metrics_agg[txn.name][status_code] += 1
365
+ end
366
+ end
285
367
 
286
- if @error_requests_agg.length < 20
287
- @error_requests_agg.push({'name' => txn.name, 'context' => txn.context})
288
- else
289
- i = rand(20)
290
- @error_requests_agg[i] = {'name' => txn.name, 'context' => txn.context}
368
+ trace_id = ""
369
+ trace_id = txn.trace_id if !txn.trace_id.nil?
370
+ if @error_requests_agg.length < 20
371
+ @error_requests_agg.push({'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context})
372
+ else
373
+ i = rand(20)
374
+ @error_requests_agg[i] = {'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context}
375
+ end
291
376
  end
292
377
  end
293
378
  end
@@ -329,7 +414,7 @@ module Atatus
329
414
  end
330
415
 
331
416
  if @collect_counter % 30 == 0
332
- @transport.hostinfo(start_time)
417
+ @hostinfo_response = @transport.hostinfo(start_time)
333
418
  @collect_counter = 0
334
419
  end
335
420
  @collect_counter += 1
@@ -29,7 +29,8 @@ module Atatus
29
29
  version: VERSION
30
30
  },
31
31
  hostname: @metadata.hostname,
32
- hostId: @metadata.hwinfo.hostid
32
+ hostId: @metadata.hwinfo.hostid,
33
+ releaseStage: @config.environment
33
34
  }
34
35
  if !@container_id.nil?
35
36
  common[:containerId] = @container_id
@@ -195,7 +196,7 @@ module Atatus
195
196
 
196
197
  if !context.response.nil?
197
198
  if !context.response.status_code.nil?
198
- request[:statusCode] = context.response.status_code
199
+ request[:statusCode] = context.response.status_code.to_i
199
200
  end
200
201
  end
201
202
 
@@ -237,11 +238,17 @@ module Atatus
237
238
  then
238
239
  next
239
240
  end
241
+ txn_id = ""
242
+ txn_id = txn.id if !txn.id.nil?
243
+ trace_id = ""
244
+ trace_id = txn.trace_id if !txn.trace_id.nil?
240
245
 
241
246
  trace = {}
242
247
  trace[:name] = txn.name
243
248
  trace[:type] = @config.framework_name || AGENT_NAME
244
249
  trace[:kind] = AGENT_NAME
250
+ trace[:txnId] = txn_id
251
+ trace[:traceId] = trace_id
245
252
  trace[:start] = txn.timestamp
246
253
  trace[:duration] = Util.ms(txn.duration)
247
254
  if !txn.context.nil?
@@ -249,6 +256,28 @@ module Atatus
249
256
  end
250
257
  trace[:entries] = []
251
258
  trace[:funcs] = []
259
+
260
+ if
261
+ !txn.context.nil? &&
262
+ defined?(txn.context.custom) &&
263
+ !txn.context.custom.nil? &&
264
+ !txn.context.custom.empty?
265
+ then
266
+ trace[:customData] = txn.context.custom
267
+ end
268
+
269
+ if
270
+ !txn.context.nil? &&
271
+ defined?(txn.context.user) &&
272
+ !txn.context.user.nil? &&
273
+ !txn.context.user.empty?
274
+ then
275
+ trace[:user] = {}
276
+ trace[:user][:id] = txn.context.user.id
277
+ trace[:user][:email] = txn.context.user.email
278
+ trace[:user][:username] = txn.context.user.username
279
+ end
280
+
252
281
  i = 0
253
282
 
254
283
  if
@@ -286,7 +315,7 @@ module Atatus
286
315
  entry[:dt] = {}
287
316
  entry[:dt][:url] = span.context.http.url
288
317
  entry[:dt][:method] = span.context.http.method if defined?(span.context.http.method) && !span.context.http.method.nil?
289
- entry[:dt][:status_code] = span.context.http.status_code if defined?(span.context.http.status_code) && !span.context.http.status_code.nil?
318
+ entry[:dt][:status_code] = span.context.http.status_code.to_s if defined?(span.context.http.status_code) && !span.context.http.status_code.nil?
290
319
  end
291
320
  trace[:entries] << entry
292
321
  func_index = trace[:funcs].index(span.name)
@@ -347,11 +376,39 @@ module Atatus
347
376
  then
348
377
  next
349
378
  end
379
+ txn_id = ""
380
+ txn_id = v['txn_id'] if v.key?('txn_id')
381
+ trace_id = ""
382
+ trace_id = v['trace_id'] if v.key?('trace_id')
350
383
  error_request = {}
351
384
  error_request[:name] = v['name']
352
385
  error_request[:type] = @config.framework_name || AGENT_NAME
353
386
  error_request[:kind] = AGENT_NAME
387
+ error_request[:txnId] = txn_id
388
+ error_request[:traceId] = trace_id
354
389
  error_request[:request] = build_request(v['context'])
390
+
391
+ if
392
+ !v['context'].nil? &&
393
+ defined?(v['context'].custom) &&
394
+ !v['context'].custom.nil? &&
395
+ !v['context'].custom.empty?
396
+ then
397
+ error_request[:customData] = v['context'].custom
398
+ end
399
+
400
+ if
401
+ !v['context'].nil? &&
402
+ defined?(v['context'].user) &&
403
+ !v['context'].user.nil? &&
404
+ !v['context'].user.empty?
405
+ then
406
+ error_request[:user] = {}
407
+ error_request[:user][:id] = v['context'].user.id
408
+ error_request[:user][:email] = v['context'].user.email
409
+ error_request[:user][:username] = v['context'].user.username
410
+ end
411
+
355
412
  error_requests << error_request
356
413
  end
357
414
  error_requests
@@ -384,9 +441,39 @@ module Atatus
384
441
  error[:transaction] = v.transaction[:name]
385
442
  end
386
443
 
444
+ txn_id = ""
445
+ txn_id = v.transaction_id if !v.transaction_id.nil?
446
+ trace_id = ""
447
+ trace_id = v.trace_id if !v.trace_id.nil?
448
+
449
+ error[:txnId] = txn_id
450
+ error[:traceId] = trace_id
451
+
387
452
  if !v.context.nil?
388
453
  error[:request] = build_request(v.context)
389
454
  end
455
+
456
+ if
457
+ !v.context.nil? &&
458
+ defined?(v.context.custom) &&
459
+ !v.context.custom.nil? &&
460
+ !v.context.custom.empty?
461
+ then
462
+ error[:customData] = v.context.custom
463
+ end
464
+
465
+ if
466
+ !v.context.nil? &&
467
+ defined?(v.context.user) &&
468
+ !v.context.user.nil? &&
469
+ !v.context.user.empty?
470
+ then
471
+ error[:user] = {}
472
+ error[:user][:id] = v.context.user.id
473
+ error[:user][:email] = v.context.user.email
474
+ error[:user][:username] = v.context.user.username
475
+ end
476
+
390
477
  error[:exceptions] = []
391
478
  exception = {}
392
479
  exception[:class] = v.exception.type
@@ -409,7 +496,7 @@ module Atatus
409
496
  frame = {}
410
497
  frame[:f] = f.filename
411
498
  frame[:m] = f.function
412
- frame[:ln] = f.lineno
499
+ frame[:ln] = f.lineno.to_i
413
500
  if f.library_frame == false
414
501
  frame[:inp] = true
415
502
  end
@@ -51,6 +51,7 @@ module Atatus
51
51
  'sqlite'=> 'SQLite',
52
52
  'controller' => 'Controller',
53
53
  'view' => 'View',
54
+ 'tilt' => 'Tilt',
54
55
  'http' => 'External Requests',
55
56
  'http2' => 'External Requests',
56
57
  'http_rb' => 'External Requests',
@@ -30,11 +30,13 @@ module Atatus
30
30
 
31
31
  @blocked = false
32
32
  @capture_percentiles = false
33
+ @hostinfo_response = {}
33
34
  end
34
35
 
35
36
  def hostinfo(start_time)
36
37
  payload = @builder.hostinfo(start_time)
37
38
  post(HOSTINFO_ENDPOINT, payload)
39
+ @hostinfo_response
38
40
  end
39
41
 
40
42
  def txns(start_time, end_time, data)
@@ -109,7 +111,25 @@ module Atatus
109
111
  if resp
110
112
  if resp.key?("capturePercentiles")
111
113
  @capture_percentiles = resp["capturePercentiles"]
114
+ @hostinfo_response['capturePercentiles'] = @capture_percentiles
112
115
  end
116
+
117
+ if resp.key?("extRequestPatterns")
118
+ @hostinfo_response['extRequestPatterns'] = resp["extRequestPatterns"]
119
+ end
120
+
121
+ if resp.key?("ignoreTxnNamePatterns")
122
+ @hostinfo_response['ignoreTxnNamePatterns'] = resp["ignoreTxnNamePatterns"]
123
+ end
124
+
125
+ if resp.key?("ignoreHTTPFailurePatterns")
126
+ @hostinfo_response['ignoreHTTPFailurePatterns'] = resp["ignoreHTTPFailurePatterns"]
127
+ end
128
+
129
+ if resp.key?("ignoreExceptionPatterns")
130
+ @hostinfo_response['ignoreExceptionPatterns'] = resp["ignoreExceptionPatterns"]
131
+ end
132
+
113
133
  end
114
134
  else
115
135
  true
@@ -86,6 +86,10 @@ module Atatus
86
86
 
87
87
  Util.reverse_merge!(error.context.labels, transaction.context.labels)
88
88
  Util.reverse_merge!(error.context.custom, transaction.context.custom)
89
+
90
+ return unless transaction.context.user
91
+
92
+ error.context.user = transaction.context.user
89
93
  end
90
94
  end
91
95
  end
@@ -19,5 +19,5 @@
19
19
 
20
20
  module Atatus
21
21
  AGENT_NAME = 'Ruby'
22
- VERSION = '1.4.0'
22
+ VERSION = '1.6.2'
23
23
  end
data/lib/atatus.rb CHANGED
@@ -352,6 +352,14 @@ module Atatus
352
352
  end
353
353
  end
354
354
 
355
+ # Provide further context for the current transaction
356
+ #
357
+ # @param custom [Hash] A hash with custom information. Can be nested.
358
+ # @return [Hash] The current custom context
359
+ def set_custom_data(custom)
360
+ agent&.set_custom_context(custom)
361
+ end
362
+
355
363
  # Provide further context for the current transaction
356
364
  #
357
365
  # @param custom [Hash] A hash with custom information. Can be nested.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: atatus
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Atatus
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-15 00:00:00.000000000 Z
11
+ date: 2022-01-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby