atatus 1.4.0 → 1.6.2

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 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