atatus 1.6.0 → 1.7.0
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/CHANGELOG.md +16 -0
- data/LICENSE +1 -1
- data/lib/atatus/agent.rb +8 -0
- data/lib/atatus/collector/base.rb +197 -24
- data/lib/atatus/collector/builder.rb +10 -1
- data/lib/atatus/collector/transport.rb +43 -2
- data/lib/atatus/config.rb +3 -0
- data/lib/atatus/context/company.rb +38 -0
- data/lib/atatus/context.rb +3 -0
- data/lib/atatus/instrumenter.rb +10 -0
- data/lib/atatus/metrics.rb +0 -1
- data/lib/atatus/spies/sequel.rb +42 -41
- data/lib/atatus/transaction.rb +8 -0
- data/lib/atatus/version.rb +1 -1
- data/lib/atatus.rb +16 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b14ce033d2727c9e1773987897f569026bfd7bb45ff3387ab7bed2d8e5dc912
|
4
|
+
data.tar.gz: 7d006a8ccc31f1cbb59d700eae5d7d83760c174e3dd8b0be7fc97e328feff8f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8ee79aac253e143ea0867530643b800a226277dd644ca514a2aa07fbc656065f2a316eb3da46a5630e90ae2bb3041f984331453f475a6fa1a5afcccb349f1df
|
7
|
+
data.tar.gz: df8621294a91c15d6afec8ac6fc76aba8f40376deb989b213b7a6cc5c6d8e6b91fb40c517fcb227f8ddfb0cd1c5dfc1e6f14908aa655d7491df0f41a5fa17eea
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,22 @@ 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.7.0 (Fri, 15 Jul 2022)
|
8
|
+
|
9
|
+
- Added support for analytics.
|
10
|
+
- Fixed sequel instrumentation.
|
11
|
+
|
12
|
+
|
13
|
+
## 1.6.2 (Mon, 31 Jan 2022)
|
14
|
+
|
15
|
+
- Fixed config environment.
|
16
|
+
- Supported ignore failure patterns, ignore exceptions and ignore transactions.
|
17
|
+
|
18
|
+
|
19
|
+
## 1.6.1 (Wed, 29 Dec 2021)
|
20
|
+
|
21
|
+
- Fixed a specific case where span duration goes less than 0.
|
22
|
+
|
7
23
|
|
8
24
|
## 1.6.0 (Fri, 24 Dec 2021)
|
9
25
|
|
data/LICENSE
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
All components of this product are Copyright (c)
|
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):
|
data/lib/atatus/agent.rb
CHANGED
@@ -247,6 +247,14 @@ module Atatus
|
|
247
247
|
instrumenter.set_user(user)
|
248
248
|
end
|
249
249
|
|
250
|
+
def set_company(company)
|
251
|
+
instrumenter.set_company(company)
|
252
|
+
end
|
253
|
+
|
254
|
+
def set_response_body(response_body)
|
255
|
+
instrumenter.set_response_body(response_body)
|
256
|
+
end
|
257
|
+
|
250
258
|
def build_context(rack_env:, for_type:)
|
251
259
|
@context_builder.build(rack_env: rack_env, for_type: for_type)
|
252
260
|
end
|
@@ -42,6 +42,12 @@ module Atatus
|
|
42
42
|
@metrics_lock = Mutex.new
|
43
43
|
@metrics_agg = []
|
44
44
|
|
45
|
+
@analytics = @config.analytics
|
46
|
+
@analytics_lock = Mutex.new
|
47
|
+
@analytics_agg = []
|
48
|
+
|
49
|
+
@hostinfo_response = {}
|
50
|
+
@hostinfo_response["analytics"] = true
|
45
51
|
@transport = Atatus::BaseTransport.new(config)
|
46
52
|
@collect_counter = 0
|
47
53
|
@running = false
|
@@ -79,13 +85,38 @@ module Atatus
|
|
79
85
|
|
80
86
|
def add_error(error)
|
81
87
|
ensure_worker_running
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
88
|
+
ignore_error = false
|
89
|
+
if
|
90
|
+
!error.exception.nil? &&
|
91
|
+
!error.exception.type.nil? &&
|
92
|
+
!error.exception.message.nil?
|
93
|
+
then
|
94
|
+
if @hostinfo_response.key?("ignoreExceptionPatterns")
|
95
|
+
@hostinfo_response['ignoreExceptionPatterns'].each do |k, v|
|
96
|
+
if error.exception.type.match(k)
|
97
|
+
exception_values = v
|
98
|
+
if exception_values.length == 0
|
99
|
+
ignore_error = true
|
100
|
+
else
|
101
|
+
exception_values.each do |value|
|
102
|
+
if error.exception.message.include?(value)
|
103
|
+
ignore_error = true
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
break
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
if ignore_error == false
|
113
|
+
@errors_lock.synchronize do
|
114
|
+
if @errors_aggs.length < 20
|
115
|
+
@errors_aggs.push(error)
|
116
|
+
else
|
117
|
+
i = rand(20)
|
118
|
+
@errors_aggs[i] = error
|
119
|
+
end
|
89
120
|
end
|
90
121
|
end
|
91
122
|
end
|
@@ -128,6 +159,95 @@ module Atatus
|
|
128
159
|
end
|
129
160
|
end
|
130
161
|
|
162
|
+
def add_analytics(txn)
|
163
|
+
analytics_txn = {}
|
164
|
+
analytics_txn[:timestamp] = Util.ms(txn.timestamp).to_i
|
165
|
+
analytics_txn[:txnId] = ""
|
166
|
+
analytics_txn[:txnId] = txn.id if !txn.id.nil?
|
167
|
+
analytics_txn[:traceId] = ""
|
168
|
+
analytics_txn[:traceId] = txn.trace_id if !txn.trace_id.nil?
|
169
|
+
analytics_txn[:name] = txn.name
|
170
|
+
analytics_txn[:duration] = Util.ms(txn.duration)
|
171
|
+
|
172
|
+
if !txn.context.nil?
|
173
|
+
if !txn.context.request.nil?
|
174
|
+
r = txn.context.request
|
175
|
+
|
176
|
+
analytics_txn[:method] = r.method if !r.method.nil?
|
177
|
+
|
178
|
+
if !r.headers.nil?
|
179
|
+
analytics_txn[:requestHeaders] = r.headers
|
180
|
+
analytics_txn[:userAgent] = r.headers['User-Agent'] if r.headers.key?('User-Agent')
|
181
|
+
end
|
182
|
+
|
183
|
+
if !r.body.nil?
|
184
|
+
if !r.body.empty?
|
185
|
+
if r.body != "[SKIPPED]"
|
186
|
+
analytics_txn[:requestBody] = r.body.to_json
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
if !r.url.nil?
|
192
|
+
analytics_txn[:url] = r.url.full
|
193
|
+
end
|
194
|
+
|
195
|
+
if !r.socket.nil?
|
196
|
+
analytics_txn[:ip] = r.socket.remote_addr
|
197
|
+
end
|
198
|
+
|
199
|
+
end
|
200
|
+
|
201
|
+
if
|
202
|
+
defined?(txn.context.response_body) &&
|
203
|
+
!txn.context.response_body.nil?
|
204
|
+
then
|
205
|
+
analytics_txn[:responseBody] = txn.context.response_body
|
206
|
+
end
|
207
|
+
|
208
|
+
if !txn.context.response.nil?
|
209
|
+
if !txn.context.response.headers.nil?
|
210
|
+
analytics_txn[:responseHeaders] = txn.context.response.headers
|
211
|
+
end
|
212
|
+
if !txn.context.response.status_code.nil?
|
213
|
+
analytics_txn[:statusCode] = txn.context.response.status_code.to_i
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
if
|
218
|
+
defined?(txn.context.custom) &&
|
219
|
+
!txn.context.custom.nil? &&
|
220
|
+
!txn.context.custom.empty?
|
221
|
+
then
|
222
|
+
analytics_txn[:customData] = txn.context.custom
|
223
|
+
end
|
224
|
+
|
225
|
+
if
|
226
|
+
defined?(txn.context.user) &&
|
227
|
+
!txn.context.user.nil? &&
|
228
|
+
!txn.context.user.empty?
|
229
|
+
then
|
230
|
+
analytics_txn[:userId] = txn.context.user.id
|
231
|
+
analytics_txn[:userEmail] = txn.context.user.email
|
232
|
+
analytics_txn[:userName] = txn.context.user.username
|
233
|
+
end
|
234
|
+
|
235
|
+
if
|
236
|
+
defined?(txn.context.company) &&
|
237
|
+
!txn.context.company.nil? &&
|
238
|
+
!txn.context.company.empty?
|
239
|
+
then
|
240
|
+
analytics_txn[:companyId] = txn.context.company.id
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
@analytics_lock.synchronize do
|
245
|
+
if @analytics_agg.length < 10000
|
246
|
+
@analytics_agg << analytics_txn
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
131
251
|
def add_span(span)
|
132
252
|
ensure_worker_running
|
133
253
|
|
@@ -156,6 +276,19 @@ module Atatus
|
|
156
276
|
return
|
157
277
|
end
|
158
278
|
|
279
|
+
ignore_txn = false
|
280
|
+
if @hostinfo_response.key?("ignoreTxnNamePatterns")
|
281
|
+
@hostinfo_response['ignoreTxnNamePatterns'].each do |k|
|
282
|
+
if txn.name.match(k)
|
283
|
+
ignore_txn = true
|
284
|
+
break
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
if ignore_txn == true
|
289
|
+
return
|
290
|
+
end
|
291
|
+
|
159
292
|
return if txn.name.empty?
|
160
293
|
return if txn.duration <= 0
|
161
294
|
|
@@ -229,6 +362,9 @@ module Atatus
|
|
229
362
|
end
|
230
363
|
k += 1
|
231
364
|
end
|
365
|
+
if spans_tuple[j].duration <= 0
|
366
|
+
spans_tuple[j].duration = 1
|
367
|
+
end
|
232
368
|
end
|
233
369
|
|
234
370
|
if !@txns_agg[txn.name].spans.key?(spans_tuple[j].name)
|
@@ -293,29 +429,55 @@ module Atatus
|
|
293
429
|
!txn.context.response.status_code.nil?
|
294
430
|
then
|
295
431
|
status_code = txn.context.response.status_code.to_i
|
296
|
-
|
432
|
+
ignore_status_code = false
|
297
433
|
if status_code >= 400 && status_code != 404
|
298
|
-
if
|
299
|
-
@
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
434
|
+
if @hostinfo_response.key?("ignoreHTTPFailurePatterns")
|
435
|
+
@hostinfo_response['ignoreHTTPFailurePatterns'].each do |k, v|
|
436
|
+
if txn.name.match(k)
|
437
|
+
status_code_array_s = v
|
438
|
+
if status_code_array_s.length == 0
|
439
|
+
ignore_status_code = true
|
440
|
+
else
|
441
|
+
status_code_array_s.each do |code|
|
442
|
+
if code == txn.context.response.status_code.to_s
|
443
|
+
ignore_status_code = true
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|
447
|
+
break
|
448
|
+
end
|
305
449
|
end
|
306
450
|
end
|
451
|
+
if ignore_status_code == false
|
452
|
+
if !@error_metrics_agg.key?(txn.name)
|
453
|
+
@error_metrics_agg[txn.name] = {status_code => 1}
|
454
|
+
else
|
455
|
+
if !@error_metrics_agg[txn.name].key?(status_code)
|
456
|
+
@error_metrics_agg[txn.name][status_code] = 1
|
457
|
+
else
|
458
|
+
@error_metrics_agg[txn.name][status_code] += 1
|
459
|
+
end
|
460
|
+
end
|
307
461
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
462
|
+
trace_id = ""
|
463
|
+
trace_id = txn.trace_id if !txn.trace_id.nil?
|
464
|
+
if @error_requests_agg.length < 20
|
465
|
+
@error_requests_agg.push({'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context})
|
466
|
+
else
|
467
|
+
i = rand(20)
|
468
|
+
@error_requests_agg[i] = {'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context}
|
469
|
+
end
|
315
470
|
end
|
316
471
|
end
|
317
472
|
end
|
318
473
|
|
474
|
+
if @hostinfo_response.key?("analytics")
|
475
|
+
if @hostinfo_response["analytics"] == true && @analytics == true
|
476
|
+
if background == false
|
477
|
+
add_analytics txn
|
478
|
+
end
|
479
|
+
end
|
480
|
+
end
|
319
481
|
end
|
320
482
|
end
|
321
483
|
|
@@ -353,13 +515,12 @@ module Atatus
|
|
353
515
|
end
|
354
516
|
|
355
517
|
if @collect_counter % 30 == 0
|
356
|
-
@transport.hostinfo(start_time)
|
518
|
+
@hostinfo_response = @transport.hostinfo(start_time)
|
357
519
|
@collect_counter = 0
|
358
520
|
end
|
359
521
|
@collect_counter += 1
|
360
522
|
|
361
523
|
end_time = (Time.now.to_f * 1000).to_i
|
362
|
-
debug '%s: data collector', pid_str
|
363
524
|
|
364
525
|
txns_data = nil
|
365
526
|
txn_hist_data = nil
|
@@ -368,6 +529,7 @@ module Atatus
|
|
368
529
|
error_requests_data = nil
|
369
530
|
errors_data = nil
|
370
531
|
metrics_data = nil
|
532
|
+
analytics_data = nil
|
371
533
|
|
372
534
|
@txns_lock.synchronize do
|
373
535
|
txns_data = @txns_agg
|
@@ -386,6 +548,11 @@ module Atatus
|
|
386
548
|
@error_requests_agg = []
|
387
549
|
end
|
388
550
|
|
551
|
+
@analytics_lock.synchronize do
|
552
|
+
analytics_data = @analytics_agg
|
553
|
+
@analytics_agg = []
|
554
|
+
end
|
555
|
+
|
389
556
|
@errors_lock.synchronize do
|
390
557
|
errors_data = @errors_aggs
|
391
558
|
@errors_aggs = []
|
@@ -412,6 +579,12 @@ module Atatus
|
|
412
579
|
@transport.errors(start_time, end_time, errors_data) unless errors_data.empty?
|
413
580
|
|
414
581
|
@transport.metrics(start_time, end_time, metrics_data) unless metrics_data.empty?
|
582
|
+
|
583
|
+
if @hostinfo_response.key?("analytics")
|
584
|
+
if @hostinfo_response["analytics"] == true && @analytics == true
|
585
|
+
@transport.analytics(start_time, end_time, analytics_data) unless analytics_data.empty?
|
586
|
+
end
|
587
|
+
end
|
415
588
|
end
|
416
589
|
end
|
417
590
|
end
|
@@ -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
|
@@ -91,6 +92,14 @@ module Atatus
|
|
91
92
|
payload
|
92
93
|
end
|
93
94
|
|
95
|
+
def analytics(start_time, end_time, analytics_data)
|
96
|
+
payload = common()
|
97
|
+
payload[:startTime] = start_time
|
98
|
+
payload[:endTime] = end_time
|
99
|
+
payload[:requests] = analytics_data
|
100
|
+
payload
|
101
|
+
end
|
102
|
+
|
94
103
|
private
|
95
104
|
|
96
105
|
def keyword_field(value)
|
@@ -14,6 +14,7 @@ module Atatus
|
|
14
14
|
ERROR_ENDPOINT = "/track/apm/error".freeze
|
15
15
|
ERROR_METRIC_ENDPOINT = "/track/apm/error_metric".freeze
|
16
16
|
METRIC_ENDPOINT = "/track/apm/metric".freeze
|
17
|
+
ANALYTICS_ENDPOINT = "/track/apm/analytics/txn".freeze
|
17
18
|
|
18
19
|
def initialize(config)
|
19
20
|
@config = config
|
@@ -24,17 +25,25 @@ module Atatus
|
|
24
25
|
@notify_host = "https://apm-rx.atatus.com"
|
25
26
|
end
|
26
27
|
|
28
|
+
@analytics_notify_host = @config.analytics_notify_host
|
29
|
+
uri = URI(@analytics_notify_host)
|
30
|
+
if not uri.kind_of?(URI::HTTPS) and not uri.kind_of?(URI::HTTP)
|
31
|
+
@analytics_notify_host = "https://an-rx.atatus.com"
|
32
|
+
end
|
33
|
+
|
27
34
|
@builder = Atatus::Builder.new(config)
|
28
35
|
@headers = {}
|
29
36
|
@headers['Content-Type'] = "application/json"
|
30
37
|
|
31
38
|
@blocked = false
|
32
39
|
@capture_percentiles = false
|
40
|
+
@hostinfo_response = {}
|
33
41
|
end
|
34
42
|
|
35
43
|
def hostinfo(start_time)
|
36
44
|
payload = @builder.hostinfo(start_time)
|
37
45
|
post(HOSTINFO_ENDPOINT, payload)
|
46
|
+
@hostinfo_response
|
38
47
|
end
|
39
48
|
|
40
49
|
def txns(start_time, end_time, data)
|
@@ -69,6 +78,11 @@ module Atatus
|
|
69
78
|
post(METRIC_ENDPOINT, payload)
|
70
79
|
end
|
71
80
|
|
81
|
+
def analytics(start_time, end_time, analytics_data)
|
82
|
+
payload = @builder.analytics(start_time, end_time, analytics_data)
|
83
|
+
post(ANALYTICS_ENDPOINT, payload)
|
84
|
+
end
|
85
|
+
|
72
86
|
private
|
73
87
|
|
74
88
|
def post(endpoint, data)
|
@@ -78,7 +92,12 @@ module Atatus
|
|
78
92
|
end
|
79
93
|
|
80
94
|
begin
|
81
|
-
|
95
|
+
notify_host = @notify_host
|
96
|
+
if endpoint == ANALYTICS_ENDPOINT
|
97
|
+
notify_host = @analytics_notify_host
|
98
|
+
end
|
99
|
+
|
100
|
+
uri = URI(notify_host + endpoint)
|
82
101
|
uri.query = URI.encode_www_form({"license_key": @config.license_key, "agent_name": AGENT_NAME, "agent_version": VERSION})
|
83
102
|
|
84
103
|
request = Net::HTTP::Post.new(uri.request_uri, @headers)
|
@@ -88,7 +107,7 @@ module Atatus
|
|
88
107
|
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
89
108
|
response = http.start { |http| http.request(request) }
|
90
109
|
rescue SystemCallError, Timeout::Error, EOFError, SocketError => e
|
91
|
-
error format('Atatus transport [%s%s] failed with exception: %s',
|
110
|
+
error format('Atatus transport [%s%s] failed with exception: %s', notify_host, endpoint, e.message)
|
92
111
|
return
|
93
112
|
end
|
94
113
|
|
@@ -107,9 +126,31 @@ module Atatus
|
|
107
126
|
|
108
127
|
resp = JSON.parse response.body
|
109
128
|
if resp
|
129
|
+
if resp.key?("analytics")
|
130
|
+
@hostinfo_response['analytics'] = resp["analytics"]
|
131
|
+
end
|
132
|
+
|
110
133
|
if resp.key?("capturePercentiles")
|
111
134
|
@capture_percentiles = resp["capturePercentiles"]
|
135
|
+
@hostinfo_response['capturePercentiles'] = @capture_percentiles
|
112
136
|
end
|
137
|
+
|
138
|
+
if resp.key?("extRequestPatterns")
|
139
|
+
@hostinfo_response['extRequestPatterns'] = resp["extRequestPatterns"]
|
140
|
+
end
|
141
|
+
|
142
|
+
if resp.key?("ignoreTxnNamePatterns")
|
143
|
+
@hostinfo_response['ignoreTxnNamePatterns'] = resp["ignoreTxnNamePatterns"]
|
144
|
+
end
|
145
|
+
|
146
|
+
if resp.key?("ignoreHTTPFailurePatterns")
|
147
|
+
@hostinfo_response['ignoreHTTPFailurePatterns'] = resp["ignoreHTTPFailurePatterns"]
|
148
|
+
end
|
149
|
+
|
150
|
+
if resp.key?("ignoreExceptionPatterns")
|
151
|
+
@hostinfo_response['ignoreExceptionPatterns'] = resp["ignoreExceptionPatterns"]
|
152
|
+
end
|
153
|
+
|
113
154
|
end
|
114
155
|
else
|
115
156
|
true
|
data/lib/atatus/config.rb
CHANGED
@@ -34,7 +34,9 @@ module Atatus
|
|
34
34
|
option :app_name, type: :string
|
35
35
|
option :license_key, type: :string
|
36
36
|
option :notify_host, type: :string, default: 'https://apm-rx.atatus.com'
|
37
|
+
option :analytics_notify_host, type: :string, default: 'https://an-rx.atatus.com'
|
37
38
|
option :trace_threshold, type: :int, default: 2000
|
39
|
+
option :analytics, type: :bool, default: false
|
38
40
|
option :config_file, type: :string, default: 'config/atatus.yml'
|
39
41
|
option :server_url, type: :url, default: ''
|
40
42
|
option :secret_token, type: :string
|
@@ -52,6 +54,7 @@ module Atatus
|
|
52
54
|
option :current_user_email_method, type: :string, default: 'email'
|
53
55
|
option :current_user_id_method, type: :string, default: 'id'
|
54
56
|
option :current_user_username_method, type: :string, default: 'username'
|
57
|
+
option :current_company_id_method, type: :string, default: 'id'
|
55
58
|
option :custom_key_filters, type: :list, default: [], converter: RegexpList.new
|
56
59
|
option :default_labels, type: :dict, default: {}
|
57
60
|
option :disable_metrics, type: :list, default: [], converter: WildcardPatternList.new
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Atatus
|
4
|
+
class Context
|
5
|
+
# @api private
|
6
|
+
class Company
|
7
|
+
def initialize(id: nil)
|
8
|
+
@id = id
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.infer(config, record)
|
12
|
+
return unless record
|
13
|
+
|
14
|
+
new(
|
15
|
+
id: safe_get(record, config.current_company_id_method)&.to_s
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_accessor :id
|
20
|
+
|
21
|
+
def empty?
|
22
|
+
!id
|
23
|
+
end
|
24
|
+
|
25
|
+
def any?
|
26
|
+
!empty?
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
private
|
31
|
+
|
32
|
+
def safe_get(record, method_name)
|
33
|
+
record.respond_to?(method_name) ? record.send(method_name) : nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/atatus/context.rb
CHANGED
@@ -22,6 +22,7 @@ require 'atatus/context/request/socket'
|
|
22
22
|
require 'atatus/context/request/url'
|
23
23
|
require 'atatus/context/response'
|
24
24
|
require 'atatus/context/user'
|
25
|
+
require 'atatus/context/company'
|
25
26
|
|
26
27
|
module Atatus
|
27
28
|
# @api private
|
@@ -42,6 +43,8 @@ module Atatus
|
|
42
43
|
attr_reader :custom
|
43
44
|
attr_reader :labels
|
44
45
|
attr_reader :service
|
46
|
+
attr_accessor :company
|
47
|
+
attr_accessor :response_body
|
45
48
|
|
46
49
|
# rubocop:disable Metrics/CyclomaticComplexity
|
47
50
|
def empty?
|
data/lib/atatus/instrumenter.rb
CHANGED
@@ -253,6 +253,16 @@ module Atatus
|
|
253
253
|
current_transaction.set_user(user)
|
254
254
|
end
|
255
255
|
|
256
|
+
def set_company(company)
|
257
|
+
return unless current_transaction
|
258
|
+
current_transaction.set_company(company)
|
259
|
+
end
|
260
|
+
|
261
|
+
def set_response_body(response_body)
|
262
|
+
return unless current_transaction
|
263
|
+
current_transaction.set_response_body(response_body)
|
264
|
+
end
|
265
|
+
|
256
266
|
def inspect
|
257
267
|
'<Atatus::Instrumenter ' \
|
258
268
|
"current_transaction=#{current_transaction.inspect}" \
|
data/lib/atatus/metrics.rb
CHANGED
data/lib/atatus/spies/sequel.rb
CHANGED
@@ -28,59 +28,60 @@ module Atatus
|
|
28
28
|
ACTION = 'query'
|
29
29
|
|
30
30
|
def self.summarizer
|
31
|
-
@summarizer ||= Sql.
|
31
|
+
@summarizer ||= Sql::Signature::Summarizer.new
|
32
32
|
end
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
def log_connection_yield(sql, connection, args = nil, &block)
|
43
|
-
unless Atatus.current_transaction
|
44
|
-
return log_connection_yield_without_apm(
|
45
|
-
sql, connection, args, &block
|
46
|
-
)
|
47
|
-
end
|
34
|
+
# @api private
|
35
|
+
module Ext
|
36
|
+
# rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
37
|
+
def log_connection_yield(sql, connection, args = nil, &block)
|
38
|
+
unless Atatus.current_transaction
|
39
|
+
return super(sql, connection, args, &block)
|
40
|
+
end
|
48
41
|
|
49
|
-
|
42
|
+
subtype = database_type.to_s
|
50
43
|
|
51
|
-
|
52
|
-
|
44
|
+
name =
|
45
|
+
Atatus::Spies::SequelSpy.summarizer.summarize sql
|
53
46
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
47
|
+
context = Atatus::Span::Context.new(
|
48
|
+
db: { statement: sql, type: 'sql', user: opts[:user] },
|
49
|
+
destination: { service: { resource: subtype } }
|
50
|
+
)
|
58
51
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
end
|
73
|
-
end
|
52
|
+
span = Atatus.start_span(
|
53
|
+
name,
|
54
|
+
TYPE,
|
55
|
+
subtype: subtype,
|
56
|
+
action: ACTION,
|
57
|
+
context: context
|
58
|
+
)
|
59
|
+
super(sql, connection, args, &block).tap do |result|
|
60
|
+
if /^(UPDATE|DELETE)/.match?(name)
|
61
|
+
if connection.respond_to?(:changes)
|
62
|
+
span.context.db.rows_affected = connection.changes
|
63
|
+
elsif result.is_a?(Integer)
|
64
|
+
span.context.db.rows_affected = result
|
74
65
|
end
|
75
|
-
ensure
|
76
|
-
Atatus.end_span
|
77
66
|
end
|
78
67
|
end
|
79
|
-
|
68
|
+
rescue
|
69
|
+
span&.outcome = Span::Outcome::FAILURE
|
70
|
+
raise
|
71
|
+
ensure
|
72
|
+
span&.outcome ||= Span::Outcome::SUCCESS
|
73
|
+
Atatus.end_span
|
80
74
|
end
|
75
|
+
# rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
|
76
|
+
end
|
77
|
+
|
78
|
+
def install
|
79
|
+
require 'sequel/database/logging'
|
80
|
+
|
81
|
+
::Sequel::Database.prepend(Ext)
|
81
82
|
end
|
82
83
|
end
|
83
84
|
|
84
85
|
register 'Sequel', 'sequel', SequelSpy.new
|
85
86
|
end
|
86
|
-
end
|
87
|
+
end
|
data/lib/atatus/transaction.rb
CHANGED
@@ -148,6 +148,14 @@ module Atatus
|
|
148
148
|
context.user = Context::User.infer(@config, user)
|
149
149
|
end
|
150
150
|
|
151
|
+
def set_company(company)
|
152
|
+
context.company = Context::Company.infer(@config, company)
|
153
|
+
end
|
154
|
+
|
155
|
+
def set_response_body(response_body)
|
156
|
+
context.response_body = response_body
|
157
|
+
end
|
158
|
+
|
151
159
|
def inspect
|
152
160
|
"<Atatus::Transaction id:#{id}" \
|
153
161
|
" name:#{name.inspect} type:#{type.inspect}>"
|
data/lib/atatus/version.rb
CHANGED
data/lib/atatus.rb
CHANGED
@@ -376,6 +376,22 @@ module Atatus
|
|
376
376
|
agent&.set_user(user)
|
377
377
|
end
|
378
378
|
|
379
|
+
# Provide a company to the current transaction
|
380
|
+
#
|
381
|
+
# @param company [Object] An object representing a company
|
382
|
+
# @return [Object] Given company
|
383
|
+
def set_company(company)
|
384
|
+
agent&.set_company(company)
|
385
|
+
end
|
386
|
+
|
387
|
+
# Provide the response body to the current transaction
|
388
|
+
#
|
389
|
+
# @param response_body [String] A string containing the response body
|
390
|
+
# @return [String] Given response body
|
391
|
+
def set_response_body(response_body)
|
392
|
+
agent&.set_response_body(response_body.to_s)
|
393
|
+
end
|
394
|
+
|
379
395
|
# Provide a filter to transform payloads before sending them off
|
380
396
|
#
|
381
397
|
# @param key [Symbol] Unique filter key
|
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
|
+
version: 1.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atatus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-07-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -74,6 +74,7 @@ files:
|
|
74
74
|
- lib/atatus/config/regexp_list.rb
|
75
75
|
- lib/atatus/config/wildcard_pattern_list.rb
|
76
76
|
- lib/atatus/context.rb
|
77
|
+
- lib/atatus/context/company.rb
|
77
78
|
- lib/atatus/context/request.rb
|
78
79
|
- lib/atatus/context/request/socket.rb
|
79
80
|
- lib/atatus/context/request/url.rb
|