atatus 1.0.1 → 1.0.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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/atatus/collector/base.rb +127 -148
- data/lib/atatus/collector/builder.rb +244 -180
- data/lib/atatus/collector/layer.rb +58 -0
- data/lib/atatus/collector/transport.rb +61 -21
- data/lib/atatus/config.rb +2 -1
- data/lib/atatus/metadata/system_info/hw_info.rb +1 -1
- data/lib/atatus/version.rb +1 -1
- 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: 0ebfb72781685c274fbd7f4516df59c2ba5dc6533bc887dfbad3a3b6b93e08f6
|
4
|
+
data.tar.gz: 756f210e8bb7136aa87806fbdb3dcf1e1a9bd5986e8717322b26fba4148a9613
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a309c3b2ad681d3dc7a0a95b655e80ef0184a8b6522bf3f724b1266f65a0904e963043e21518711e3582d10757a7ab0c8c8550fd4df53d0a68442496291a352
|
7
|
+
data.tar.gz: 65c1dd53f5b6115b27edded97df2240af6e2d6217517fb59641792a60d185b6916a1bf442cb5fa277ece9711bca96a6a56acec0948edc7d6282ece771140c64e
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,13 @@ 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.0.2 (Thu, 21 Nov 2019)
|
8
|
+
|
9
|
+
- Changed Linux memory size to bytes.
|
10
|
+
- Set type to agent name if framework is not deducted.
|
11
|
+
- Code refactoring for checking existence of properties.
|
12
|
+
|
13
|
+
|
7
14
|
## 1.0.1 (Wed, 13 Nov 2019)
|
8
15
|
|
9
16
|
- Fixed Instrumenting classes only when there are defined.
|
@@ -1,81 +1,19 @@
|
|
1
|
+
require 'json'
|
1
2
|
require 'atatus'
|
2
|
-
require 'atatus/transaction'
|
3
3
|
require 'atatus/config'
|
4
|
-
|
4
|
+
require 'atatus/transaction'
|
5
|
+
require 'atatus/collector/layer'
|
5
6
|
require 'atatus/collector/transport'
|
6
|
-
require 'json'
|
7
7
|
|
8
8
|
module Atatus
|
9
9
|
module Collector
|
10
|
-
class Layer
|
11
|
-
attr_reader :count, :min, :max, :total, :type, :kind, :id, :pid
|
12
|
-
attr_writer :id, :pid
|
13
|
-
|
14
|
-
def initialize(type, kind, duration)
|
15
|
-
@type = type
|
16
|
-
@kind = kind
|
17
|
-
@count = 1
|
18
|
-
@min = duration
|
19
|
-
@max = duration
|
20
|
-
@total = duration
|
21
|
-
end
|
22
|
-
|
23
|
-
def aggregate!(duration)
|
24
|
-
@count += 1
|
25
|
-
@min = duration if duration < @min
|
26
|
-
@max = duration if duration > @max
|
27
|
-
@total += duration
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.span_kind(value)
|
31
|
-
return KINDS.fetch(value, value)
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.span_type(value)
|
35
|
-
return TYPES.fetch(value, value)
|
36
|
-
end
|
37
|
-
|
38
|
-
private
|
39
|
-
KINDS = {
|
40
|
-
'db' => 'Database',
|
41
|
-
'cache' => 'Database',
|
42
|
-
'ext' => 'Remote',
|
43
|
-
'websocket' => 'Remote',
|
44
|
-
'template' => 'Template'
|
45
|
-
}.freeze
|
46
|
-
|
47
|
-
TYPES = {
|
48
|
-
'mysql' => 'MySQL',
|
49
|
-
'mysql2' => 'MySQL',
|
50
|
-
'postgresql' => 'Postgres',
|
51
|
-
'mssql' => 'MS SQL',
|
52
|
-
'mongodb' => 'MongoDB',
|
53
|
-
'redis' => 'Redis',
|
54
|
-
'graphql' => 'GraphQL',
|
55
|
-
'elasticsearch' => 'Elasticsearch',
|
56
|
-
'cassandra' => 'Cassandra',
|
57
|
-
'http' => 'External Requests',
|
58
|
-
'http2' => 'External Requests',
|
59
|
-
'http_rb' => 'External Requests',
|
60
|
-
'net_http' => 'External Requests'
|
61
|
-
}.freeze
|
62
|
-
end
|
63
|
-
|
64
10
|
class Txn < Layer
|
65
|
-
attr_reader :spans
|
66
|
-
|
67
11
|
def initialize(type, kind, duration)
|
68
12
|
super(type, kind, duration)
|
69
|
-
@spans =
|
13
|
+
@spans = {}
|
70
14
|
end
|
71
15
|
|
72
|
-
|
73
|
-
if !@spans.has_key?(span_name)
|
74
|
-
@spans[key] = Layer.new(type, kind, duration)
|
75
|
-
else
|
76
|
-
@spans[key].aggregate! duration
|
77
|
-
end
|
78
|
-
end
|
16
|
+
attr_reader :spans
|
79
17
|
end
|
80
18
|
|
81
19
|
class Base
|
@@ -85,21 +23,22 @@ module Atatus
|
|
85
23
|
# info 'Initializing Collector'
|
86
24
|
@config = config
|
87
25
|
@spans = Hash.new {|h,k| h[k]=[]}
|
88
|
-
@running = false
|
89
|
-
uri = URI("https://apm-rx.atatus.com/")
|
90
|
-
@transport = Atatus::BaseTransport.new(config, uri.host, uri.port)
|
91
|
-
@txn_lock = Mutex.new
|
92
|
-
@txn_aggs = Hash.new {}
|
93
|
-
@trace_aggs = Array.new()
|
94
|
-
@error_metrics = Hash.new {}
|
95
|
-
@error_requests = Array.new()
|
96
26
|
|
97
|
-
@
|
98
|
-
@
|
27
|
+
@txns_lock = Mutex.new
|
28
|
+
@txns_agg = {}
|
29
|
+
@traces_agg = []
|
30
|
+
@error_metrics_agg = {}
|
31
|
+
@error_requests_agg = []
|
32
|
+
|
33
|
+
@errors_lock = Mutex.new
|
34
|
+
@errors_aggs = []
|
99
35
|
|
100
36
|
@metrics_lock = Mutex.new
|
101
|
-
@
|
37
|
+
@metrics_agg = []
|
38
|
+
|
39
|
+
@transport = Atatus::BaseTransport.new(config)
|
102
40
|
@collect_counter = 0
|
41
|
+
@running = false
|
103
42
|
end
|
104
43
|
|
105
44
|
attr_reader :config
|
@@ -130,80 +69,113 @@ module Atatus
|
|
130
69
|
def add_error(error)
|
131
70
|
ensure_worker_running
|
132
71
|
|
133
|
-
@
|
134
|
-
if @
|
135
|
-
@
|
72
|
+
@errors_lock.synchronize do
|
73
|
+
if @errors_aggs.length < 20
|
74
|
+
@errors_aggs.push(error)
|
136
75
|
else
|
137
76
|
i = rand(20)
|
138
|
-
@
|
77
|
+
@errors_aggs[i] = error
|
139
78
|
end
|
140
79
|
end
|
141
|
-
# puts error.to_yaml
|
142
80
|
end
|
143
81
|
|
144
82
|
def add_metrics(metricset)
|
145
83
|
ensure_worker_running
|
84
|
+
|
85
|
+
metric_added = false
|
146
86
|
metric = {}
|
147
|
-
|
87
|
+
|
88
|
+
if %i[system.cpu.total.norm.pct system.memory.actual.free system.memory.total system.process.cpu.total.norm.pct system.process.memory.size system.process.memory.rss.bytes].all? {|s| metricset.samples.key? s}
|
89
|
+
then
|
148
90
|
metric[:'system.cpu.total.norm.pct'] = metricset.samples[:'system.cpu.total.norm.pct']
|
149
91
|
metric[:'system.memory.actual.free'] = metricset.samples[:'system.memory.actual.free']
|
150
92
|
metric[:'system.memory.total'] = metricset.samples[:'system.memory.total']
|
151
93
|
metric[:'system.process.cpu.total.norm.pct'] = metricset.samples[:'system.process.cpu.total.norm.pct']
|
152
94
|
metric[:'system.process.memory.size'] = metricset.samples[:'system.process.memory.size']
|
153
95
|
metric[:'system.process.memory.rss.bytes'] = metricset.samples[:'system.process.memory.rss.bytes']
|
96
|
+
metric_added = true
|
154
97
|
end
|
155
98
|
|
156
|
-
if metricset.samples.key?
|
99
|
+
if %i[ruby.gc.count ruby.threads ruby.heaps.slots.live ruby.heap.slots.free ruby.heap.allocations.total].all? {|s| metricset.samples.key? s}
|
100
|
+
then
|
157
101
|
metric[:'ruby.gc.count'] = metricset.samples[:'ruby.gc.count']
|
158
102
|
metric[:'ruby.threads'] = metricset.samples[:'ruby.threads']
|
159
103
|
metric[:'ruby.heap.slots.live'] = metricset.samples[:'ruby.heap.slots.live']
|
160
104
|
metric[:'ruby.heap.slots.free'] = metricset.samples[:'ruby.heap.slots.free']
|
161
105
|
metric[:'ruby.heap.allocations.total'] = metricset.samples[:'ruby.heap.allocations.total']
|
106
|
+
metric_added = true
|
162
107
|
end
|
163
108
|
|
164
|
-
|
165
|
-
@
|
109
|
+
if metric_added
|
110
|
+
@metrics_lock.synchronize do
|
111
|
+
@metrics_agg << metric
|
112
|
+
end
|
166
113
|
end
|
167
|
-
# puts metric.to_yaml
|
168
114
|
end
|
169
115
|
|
170
116
|
def add_span(span)
|
171
117
|
ensure_worker_running
|
172
118
|
|
119
|
+
if
|
120
|
+
span.transaction_id.nil? ||
|
121
|
+
span.name.nil? ||
|
122
|
+
span.type.nil? ||
|
123
|
+
span.subtype.nil? ||
|
124
|
+
span.duration.nil?
|
125
|
+
then
|
126
|
+
return
|
127
|
+
end
|
128
|
+
|
173
129
|
@spans[span.transaction_id] << span if span.transaction_id
|
174
|
-
# puts span.to_yaml
|
175
130
|
end
|
176
131
|
|
177
132
|
def add_txn(txn)
|
178
133
|
ensure_worker_running
|
179
134
|
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
135
|
+
if
|
136
|
+
txn.name.nil? ||
|
137
|
+
txn.id.nil? ||
|
138
|
+
txn.duration.nil?
|
139
|
+
then
|
140
|
+
return
|
141
|
+
end
|
142
|
+
|
143
|
+
return if txn.name.empty?
|
144
|
+
|
145
|
+
@txns_lock.synchronize do
|
146
|
+
if !@txns_agg.key?(txn.name)
|
147
|
+
@txns_agg[txn.name] = Txn.new(@config.framework_name, "Ruby", txn.duration)
|
148
|
+
@txns_agg[txn.name].id = txn.id
|
149
|
+
@txns_agg[txn.name].pid = txn.id
|
188
150
|
else
|
189
|
-
@
|
151
|
+
@txns_agg[txn.name].aggregate! txn.duration
|
190
152
|
end
|
191
153
|
|
192
154
|
spans_present = false
|
193
|
-
if @spans.
|
155
|
+
if @spans.key?(txn.id)
|
194
156
|
@spans[txn.id].each do |span|
|
195
|
-
|
196
|
-
|
157
|
+
if
|
158
|
+
span.name.nil? ||
|
159
|
+
span.type.nil? ||
|
160
|
+
span.subtype.nil? ||
|
161
|
+
span.duration.nil?
|
162
|
+
then
|
163
|
+
next
|
164
|
+
end
|
165
|
+
|
166
|
+
next if span.name.empty?
|
167
|
+
|
168
|
+
if !@txns_agg[txn.name].spans.key?(span.name)
|
197
169
|
kind = Layer.span_kind(span.type)
|
198
170
|
type = Layer.span_type(span.subtype)
|
199
|
-
@
|
200
|
-
@
|
201
|
-
@
|
171
|
+
@txns_agg[txn.name].spans[span.name] = Layer.new(type, kind, span.duration)
|
172
|
+
@txns_agg[txn.name].spans[span.name].id = span.id
|
173
|
+
@txns_agg[txn.name].spans[span.name].pid = span.transaction_id
|
202
174
|
else
|
203
|
-
@
|
175
|
+
@txns_agg[txn.name].spans[span.name].aggregate! span.duration
|
204
176
|
end
|
177
|
+
spans_present = true
|
205
178
|
end
|
206
|
-
spans_present = true
|
207
179
|
end
|
208
180
|
|
209
181
|
if spans_present
|
@@ -211,11 +183,11 @@ module Atatus
|
|
211
183
|
trace_txn = txn
|
212
184
|
trace_txn.spans = @spans[txn.id]
|
213
185
|
|
214
|
-
if @
|
215
|
-
@
|
186
|
+
if @traces_agg.length < 5
|
187
|
+
@traces_agg.push(trace_txn)
|
216
188
|
else
|
217
189
|
i = rand(5)
|
218
|
-
@
|
190
|
+
@traces_agg[i] = trace_txn
|
219
191
|
end
|
220
192
|
end
|
221
193
|
end
|
@@ -224,25 +196,30 @@ module Atatus
|
|
224
196
|
@spans.delete(txn.id)
|
225
197
|
end
|
226
198
|
|
227
|
-
|
199
|
+
if
|
200
|
+
!txn.context.nil? &&
|
201
|
+
!txn.context.response.nil? &&
|
202
|
+
!txn.context.response.status_code.nil?
|
203
|
+
then
|
204
|
+
status_code = txn.context.response.status_code
|
228
205
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
else
|
233
|
-
if !@error_metrics[txn_name].has_key?(status_code)
|
234
|
-
@error_metrics[txn_name][status_code] = 1
|
206
|
+
if status_code >= 400 && status_code != 404
|
207
|
+
if !@error_metrics_agg.key?(txn.name)
|
208
|
+
@error_metrics_agg[txn.name] = {status_code => 1}
|
235
209
|
else
|
236
|
-
|
210
|
+
if !@error_metrics_agg[txn.name].key?(status_code)
|
211
|
+
@error_metrics_agg[txn.name][status_code] = 1
|
212
|
+
else
|
213
|
+
@error_metrics_agg[txn.name][status_code] += 1
|
214
|
+
end
|
237
215
|
end
|
238
|
-
end
|
239
216
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
217
|
+
if @error_requests_agg.length < 20
|
218
|
+
@error_requests_agg.push({'name' => txn.name, 'context' => txn.context})
|
219
|
+
else
|
220
|
+
i = rand(20)
|
221
|
+
@error_requests_agg[i] = {'name' => txn.name, 'context' => txn.context}
|
222
|
+
end
|
246
223
|
end
|
247
224
|
end
|
248
225
|
|
@@ -257,7 +234,7 @@ module Atatus
|
|
257
234
|
debug '%s: Starting collector worker', pid_str
|
258
235
|
|
259
236
|
while @running
|
260
|
-
start_time = Time.now
|
237
|
+
start_time = (Time.now.to_f * 1000).to_i
|
261
238
|
sleep(60)
|
262
239
|
collect start_time
|
263
240
|
end
|
@@ -269,8 +246,6 @@ module Atatus
|
|
269
246
|
end
|
270
247
|
|
271
248
|
def collect(start_time)
|
272
|
-
# puts @config.to_yaml
|
273
|
-
# return
|
274
249
|
if @config.license_key.nil? || @config.app_name.nil?
|
275
250
|
if @config.license_key.nil? && @config.app_name.nil?
|
276
251
|
error '%s: Atatus configuration license_key and app_name are missing', pid_str
|
@@ -290,44 +265,48 @@ module Atatus
|
|
290
265
|
end
|
291
266
|
@collect_counter += 1
|
292
267
|
|
293
|
-
end_time = Time.now
|
268
|
+
end_time = (Time.now.to_f * 1000).to_i
|
294
269
|
debug '%s: Collecting transactions', pid_str
|
295
270
|
|
296
|
-
|
297
|
-
|
298
|
-
error_data = nil
|
271
|
+
txns_data = nil
|
272
|
+
traces_data = nil
|
299
273
|
error_metrics_data = nil
|
300
274
|
error_requests_data = nil
|
275
|
+
errors_data = nil
|
301
276
|
metrics_data = nil
|
302
277
|
|
303
|
-
@
|
304
|
-
|
305
|
-
@
|
278
|
+
@txns_lock.synchronize do
|
279
|
+
txns_data = @txns_agg
|
280
|
+
@txns_agg = {}
|
306
281
|
|
307
|
-
|
308
|
-
@
|
282
|
+
traces_data = @traces_agg
|
283
|
+
@traces_agg = []
|
309
284
|
|
310
|
-
error_metrics_data = @
|
311
|
-
@
|
285
|
+
error_metrics_data = @error_metrics_agg
|
286
|
+
@error_metrics_agg = {}
|
312
287
|
|
313
|
-
error_requests_data = @
|
314
|
-
@
|
288
|
+
error_requests_data = @error_requests_agg
|
289
|
+
@error_requests_agg = []
|
315
290
|
end
|
316
291
|
|
317
|
-
@
|
318
|
-
|
319
|
-
@
|
292
|
+
@errors_lock.synchronize do
|
293
|
+
errors_data = @errors_aggs
|
294
|
+
@errors_aggs = []
|
320
295
|
end
|
321
296
|
|
322
297
|
@metrics_lock.synchronize do
|
323
|
-
metrics_data = @
|
324
|
-
@
|
298
|
+
metrics_data = @metrics_agg
|
299
|
+
@metrics_agg = []
|
325
300
|
end
|
326
301
|
|
327
|
-
@transport.
|
328
|
-
|
302
|
+
@transport.txns(start_time, end_time, txns_data) unless txns_data.empty?
|
303
|
+
|
304
|
+
@transport.traces(start_time, end_time, traces_data) unless traces_data.empty?
|
305
|
+
|
329
306
|
@transport.error_metrics(start_time, end_time, error_metrics_data, error_requests_data) unless error_metrics_data.empty?
|
330
|
-
|
307
|
+
|
308
|
+
@transport.errors(start_time, end_time, errors_data) unless errors_data.empty?
|
309
|
+
|
331
310
|
@transport.metrics(start_time, end_time, metrics_data) unless metrics_data.empty?
|
332
311
|
end
|
333
312
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'socket'
|
2
2
|
require 'atatus/metadata'
|
3
|
-
|
3
|
+
require 'yaml'
|
4
4
|
module Atatus
|
5
5
|
class Builder
|
6
6
|
AGENT_NAME = 'Ruby'
|
@@ -8,6 +8,15 @@ module Atatus
|
|
8
8
|
def initialize(config)
|
9
9
|
@config = config
|
10
10
|
@metadata = Metadata::SystemInfo.new(config)
|
11
|
+
@container_id = nil
|
12
|
+
if
|
13
|
+
!@metadata.container.nil? &&
|
14
|
+
@metadata.container.key?(:id)
|
15
|
+
then
|
16
|
+
@container_id = @metadata.container[:id]
|
17
|
+
end
|
18
|
+
|
19
|
+
@real_hostname = Socket.gethostname
|
11
20
|
end
|
12
21
|
|
13
22
|
attr_reader :config
|
@@ -20,49 +29,47 @@ module Atatus
|
|
20
29
|
name: AGENT_NAME,
|
21
30
|
version: VERSION
|
22
31
|
},
|
23
|
-
# tags: @config.default_tags,
|
24
|
-
uniqueHostname: Socket.gethostname,
|
25
32
|
hostname: @metadata.hostname,
|
26
33
|
hostId: @metadata.hwinfo.hostid
|
27
34
|
}
|
28
|
-
|
29
|
-
common[:containerId] = @
|
35
|
+
if !@container_id.nil?
|
36
|
+
common[:containerId] = @container_id
|
30
37
|
end
|
31
38
|
common
|
32
39
|
end
|
33
40
|
|
41
|
+
def hostinfo(start_time)
|
42
|
+
payload = common()
|
43
|
+
payload[:timestamp] = start_time
|
44
|
+
payload[:environment] = build_hostinfo_obj()
|
45
|
+
payload
|
46
|
+
end
|
47
|
+
|
34
48
|
def txns(start_time, end_time, data)
|
35
49
|
payload = common()
|
36
|
-
payload[:startTime] =
|
37
|
-
payload[:endTime] =
|
50
|
+
payload[:startTime] = start_time
|
51
|
+
payload[:endTime] = end_time
|
38
52
|
payload[:transactions] = build_txns_obj(data)
|
39
53
|
payload
|
40
54
|
end
|
41
55
|
|
42
56
|
def traces(start_time, end_time, data)
|
43
57
|
payload = common()
|
44
|
-
payload[:startTime] =
|
45
|
-
payload[:endTime] =
|
58
|
+
payload[:startTime] = start_time
|
59
|
+
payload[:endTime] = end_time
|
46
60
|
payload[:traces] = build_traces_obj(data)
|
47
61
|
payload
|
48
62
|
end
|
49
63
|
|
50
64
|
def error_metrics(start_time, end_time, metrics_data, requests_data)
|
51
65
|
payload = common()
|
52
|
-
payload[:startTime] =
|
53
|
-
payload[:endTime] =
|
66
|
+
payload[:startTime] = start_time
|
67
|
+
payload[:endTime] = end_time
|
54
68
|
payload[:errorMetrics] = build_error_metrics_obj(metrics_data)
|
55
69
|
payload[:errorRequests] = build_error_requests_obj(requests_data)
|
56
70
|
payload
|
57
71
|
end
|
58
72
|
|
59
|
-
def hostinfo(start_time)
|
60
|
-
payload = common()
|
61
|
-
payload[:timestamp] = (start_time.to_f * 1000).to_i
|
62
|
-
payload[:environment] = build_hostinfo_obj()
|
63
|
-
payload
|
64
|
-
end
|
65
|
-
|
66
73
|
def errors(start_time, end_time, error_data)
|
67
74
|
payload = common()
|
68
75
|
payload[:errors] = build_errors_obj(error_data)
|
@@ -71,8 +78,8 @@ module Atatus
|
|
71
78
|
|
72
79
|
def metrics(start_time, end_time, metric_data)
|
73
80
|
payload = common()
|
74
|
-
payload[:startTime] =
|
75
|
-
payload[:endTime] =
|
81
|
+
payload[:startTime] = start_time
|
82
|
+
payload[:endTime] = end_time
|
76
83
|
payload[:ruby] = metric_data
|
77
84
|
payload
|
78
85
|
end
|
@@ -83,99 +90,45 @@ module Atatus
|
|
83
90
|
Util.truncate(value)
|
84
91
|
end
|
85
92
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
'accept-encoding': context.request.headers['Accept-Encoding'],
|
93
|
-
'accept-language': context.request.headers['Accept-Language'],
|
94
|
-
host: context.request.url.hostname,
|
95
|
-
port: (context.request.url.port).to_i,
|
96
|
-
method: context.request.method,
|
97
|
-
userAgent: context.request.headers['User-Agent'],
|
98
|
-
path: context.request.url.pathname
|
99
|
-
}
|
100
|
-
unless context.response.nil?
|
101
|
-
unless context.response.status_code.nil?
|
102
|
-
request[:statusCode] = context.response.status_code
|
103
|
-
end
|
104
|
-
end
|
105
|
-
request
|
93
|
+
def build_hostinfo_obj()
|
94
|
+
environment = {}
|
95
|
+
environment[:gems] = build_hostinfo_gems()
|
96
|
+
environment[:host] = build_hostinfo_env_host()
|
97
|
+
environment[:settings] = build_hostinfo_env_settings()
|
98
|
+
environment
|
106
99
|
end
|
107
100
|
|
108
|
-
def
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
101
|
+
def build_hostinfo_env_host()
|
102
|
+
host_info = {
|
103
|
+
cpu: [@metadata.hwinfo.cpuinfo],
|
104
|
+
ram: @metadata.hwinfo.meminfo,
|
105
|
+
hostname: @real_hostname,
|
106
|
+
bootId: @metadata.hwinfo.hostid,
|
107
|
+
hostId: @metadata.hwinfo.hostid,
|
108
|
+
os: @metadata.osinfo.os,
|
109
|
+
kernel: @metadata.osinfo.kernel
|
110
|
+
}
|
111
|
+
if !@container_id.nil?
|
112
|
+
host_info[:containerId] = @container_id
|
117
113
|
end
|
118
|
-
|
114
|
+
host_info
|
119
115
|
end
|
120
116
|
|
121
|
-
def
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
exception = {}
|
132
|
-
exception[:class] = v.exception.type
|
133
|
-
exception[:message] = v.exception.message
|
134
|
-
exception[:stacktrace] = []
|
135
|
-
unless v.exception.stacktrace.nil?
|
136
|
-
unless v.exception.stacktrace.frames.nil?
|
137
|
-
v.exception.stacktrace.frames.each do |f|
|
138
|
-
frame = {}
|
139
|
-
frame[:f] = f.filename
|
140
|
-
frame[:m] = f.function
|
141
|
-
frame[:ln] = f.lineno
|
142
|
-
if f.library_frame == false
|
143
|
-
frame[:inp] = true
|
144
|
-
unless f.context_line.nil?
|
145
|
-
frame[:code] = []
|
146
|
-
|
147
|
-
unless f.pre_context.nil?
|
148
|
-
psize = f.pre_context.size
|
149
|
-
lineno = 0
|
150
|
-
if f.lineno - psize >= 0
|
151
|
-
lineno = f.lineno - psize
|
152
|
-
end
|
153
|
-
f.pre_context.each do |c|
|
154
|
-
frame[:code].push([lineno.to_s, c])
|
155
|
-
lineno += 1
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
frame[:code].push([f.lineno.to_s, f.context_line])
|
117
|
+
def build_hostinfo_env_settings()
|
118
|
+
{
|
119
|
+
agentVersion: VERSION,
|
120
|
+
appName: @config.app_name,
|
121
|
+
framework: @config.framework_name,
|
122
|
+
frameworkVersion: @config.framework_version,
|
123
|
+
logLevel: @config.log_level,
|
124
|
+
ruby: RUBY_VERSION
|
125
|
+
}
|
126
|
+
end
|
160
127
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
frame[:code].push([lineno.to_s, c])
|
166
|
-
lineno += 1
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
exception[:stacktrace] << frame
|
172
|
-
end
|
173
|
-
end
|
174
|
-
end
|
175
|
-
error[:exceptions] << exception
|
176
|
-
errors << error
|
177
|
-
end
|
178
|
-
errors
|
128
|
+
def build_hostinfo_gems()
|
129
|
+
Bundler.rubygems.all_specs.map {|spec| [spec.name, spec.version.to_s]}.sort.to_h
|
130
|
+
rescue => e
|
131
|
+
{}
|
179
132
|
end
|
180
133
|
|
181
134
|
def build_metric(name, value)
|
@@ -190,6 +143,38 @@ module Atatus
|
|
190
143
|
}
|
191
144
|
end
|
192
145
|
|
146
|
+
def build_request(context)
|
147
|
+
request = {}
|
148
|
+
return request unless context
|
149
|
+
|
150
|
+
if !context.request.nil?
|
151
|
+
r = context.request
|
152
|
+
request[:method] = r.method if !r.method.nil?
|
153
|
+
if !r.headers.nil?
|
154
|
+
h = r.headers
|
155
|
+
request[:accept] = h['Accept'] if h.key?('Accept')
|
156
|
+
request[:'accept-encoding'] = h['Accept-Encoding'] if h.key?('Accept-Encoding')
|
157
|
+
request[:'accept-language'] = h['Accept-Language'] if h.key?('Accept-Language')
|
158
|
+
request[:'userAgent'] = h['User-Agent'] if h.key?('User-Agent')
|
159
|
+
end
|
160
|
+
|
161
|
+
if !r.url.nil?
|
162
|
+
u = r.url
|
163
|
+
request[:host] = u.hostname if !u.hostname.nil?
|
164
|
+
request[:port] = (u.port).to_i if !u.port.nil?
|
165
|
+
request[:path] = u.pathname if !u.pathname.nil?
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
if !context.response.nil?
|
170
|
+
if !context.response.status_code.nil?
|
171
|
+
request[:statusCode] = context.response.status_code
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
request
|
176
|
+
end
|
177
|
+
|
193
178
|
def build_txns_obj(data)
|
194
179
|
txns = []
|
195
180
|
data.each do |t, v|
|
@@ -207,49 +192,60 @@ module Atatus
|
|
207
192
|
def build_traces_obj(data)
|
208
193
|
traces = []
|
209
194
|
data.each do |txn|
|
195
|
+
if
|
196
|
+
txn.name.nil? ||
|
197
|
+
txn.timestamp.nil? ||
|
198
|
+
txn.duration.nil?
|
199
|
+
then
|
200
|
+
next
|
201
|
+
end
|
202
|
+
|
210
203
|
trace = {}
|
211
204
|
trace[:name] = txn.name
|
212
|
-
trace[:type] = @config.framework_name
|
213
|
-
trace[:kind] =
|
205
|
+
trace[:type] = @config.framework_name || AGENT_NAME
|
206
|
+
trace[:kind] = AGENT_NAME
|
214
207
|
trace[:start] = txn.timestamp
|
215
208
|
trace[:duration] = Util.ms(txn.duration)
|
216
|
-
|
209
|
+
if !txn.context.nil?
|
210
|
+
trace[:request] = build_request(txn.context)
|
211
|
+
end
|
217
212
|
trace[:entries] = []
|
218
213
|
trace[:funcs] = []
|
219
214
|
i = 0
|
220
215
|
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
entry[:
|
232
|
-
entry[:ly] = {}
|
233
|
-
entry[:ly][:name] = span.name
|
234
|
-
entry[:ly][:type] = Atatus::Collector::Layer.span_type(span.subtype)
|
235
|
-
entry[:ly][:kind] = Atatus::Collector::Layer.span_kind(span.type)
|
236
|
-
unless span.context.nil?
|
237
|
-
unless span.context.db.nil?
|
238
|
-
unless span.context.db.statement.nil?
|
239
|
-
entry[:dt] = {}
|
240
|
-
entry[:dt][:query] = span.context.db.statement
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
244
|
-
trace[:entries] << entry
|
245
|
-
func_index = trace[:funcs].index(span.name)
|
246
|
-
if func_index.nil?
|
247
|
-
trace[:funcs] << span.name
|
248
|
-
func_index = i
|
249
|
-
i = i + 1
|
250
|
-
end
|
251
|
-
entry[:i] = func_index
|
216
|
+
if
|
217
|
+
!txn.spans.nil? &&
|
218
|
+
!txn.spans.empty?
|
219
|
+
then
|
220
|
+
txn.spans.each do |span|
|
221
|
+
entry = {}
|
222
|
+
entry[:lv] = 1
|
223
|
+
if span.timestamp >= txn.timestamp
|
224
|
+
entry[:so] = Util.ms(span.timestamp - txn.timestamp)
|
225
|
+
else
|
226
|
+
entry[:so] = 0
|
252
227
|
end
|
228
|
+
entry[:du] = Util.ms(span.duration)
|
229
|
+
entry[:ly] = {}
|
230
|
+
entry[:ly][:name] = span.name
|
231
|
+
entry[:ly][:type] = Atatus::Collector::Layer.span_type(span.subtype)
|
232
|
+
entry[:ly][:kind] = Atatus::Collector::Layer.span_kind(span.type)
|
233
|
+
if
|
234
|
+
!span.context.nil? &&
|
235
|
+
!span.context.db.nil? &&
|
236
|
+
!span.context.db.statement.nil?
|
237
|
+
then
|
238
|
+
entry[:dt] = {}
|
239
|
+
entry[:dt][:query] = span.context.db.statement
|
240
|
+
end
|
241
|
+
trace[:entries] << entry
|
242
|
+
func_index = trace[:funcs].index(span.name)
|
243
|
+
if func_index.nil?
|
244
|
+
trace[:funcs] << span.name
|
245
|
+
func_index = i
|
246
|
+
i = i + 1
|
247
|
+
end
|
248
|
+
entry[:i] = func_index
|
253
249
|
end
|
254
250
|
end
|
255
251
|
|
@@ -263,55 +259,123 @@ module Atatus
|
|
263
259
|
metrics_data.each do |t, v|
|
264
260
|
error_metric = {}
|
265
261
|
error_metric[:name] = t
|
266
|
-
error_metric[:type] = @config.framework_name
|
267
|
-
error_metric[:kind] =
|
262
|
+
error_metric[:type] = @config.framework_name || AGENT_NAME
|
263
|
+
error_metric[:kind] = AGENT_NAME
|
268
264
|
error_metric[:statusCodes] = v
|
269
265
|
error_metrics << error_metric
|
270
266
|
end
|
271
267
|
error_metrics
|
272
268
|
end
|
273
269
|
|
274
|
-
def
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
hostId: @metadata.hwinfo.hostid,
|
290
|
-
os: @metadata.osinfo.os,
|
291
|
-
kernel: @metadata.osinfo.kernel
|
292
|
-
}
|
293
|
-
unless @metadata.container.nil?
|
294
|
-
host_info[:containerId] = @metadata.container[:id] if @metadata.container.key?(:id)
|
270
|
+
def build_error_requests_obj(requests_data)
|
271
|
+
error_requests = []
|
272
|
+
requests_data.each do |v|
|
273
|
+
if
|
274
|
+
!v.key?('name') ||
|
275
|
+
!v.key?('context')
|
276
|
+
then
|
277
|
+
next
|
278
|
+
end
|
279
|
+
error_request = {}
|
280
|
+
error_request[:name] = v['name']
|
281
|
+
error_request[:type] = @config.framework_name || AGENT_NAME
|
282
|
+
error_request[:kind] = AGENT_NAME
|
283
|
+
error_request[:request] = build_request(v['context'])
|
284
|
+
error_requests << error_request
|
295
285
|
end
|
296
|
-
|
286
|
+
error_requests
|
297
287
|
end
|
298
288
|
|
299
|
-
def
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
end
|
289
|
+
def build_errors_obj(data)
|
290
|
+
errors = []
|
291
|
+
data.each do |v|
|
292
|
+
if
|
293
|
+
v.timestamp.nil? ||
|
294
|
+
v.exception.nil?
|
295
|
+
then
|
296
|
+
next
|
297
|
+
end
|
309
298
|
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
299
|
+
if
|
300
|
+
v.exception.type.nil? ||
|
301
|
+
v.exception.message.nil?
|
302
|
+
then
|
303
|
+
next
|
304
|
+
end
|
305
|
+
|
306
|
+
error = {}
|
307
|
+
error[:timestamp] = v.timestamp
|
308
|
+
|
309
|
+
if
|
310
|
+
!v.transaction.nil? &&
|
311
|
+
v.transaction.key?(:name)
|
312
|
+
then
|
313
|
+
error[:transaction] = v.transaction[:name]
|
314
|
+
end
|
315
|
+
|
316
|
+
if !v.context.nil?
|
317
|
+
error[:request] = build_request(v.context)
|
318
|
+
end
|
319
|
+
error[:exceptions] = []
|
320
|
+
exception = {}
|
321
|
+
exception[:class] = v.exception.type
|
322
|
+
exception[:message] = v.exception.message
|
323
|
+
exception[:stacktrace] = []
|
324
|
+
if
|
325
|
+
!v.exception.stacktrace.nil? &&
|
326
|
+
!v.exception.stacktrace.frames.nil?
|
327
|
+
then
|
328
|
+
v.exception.stacktrace.frames.each do |f|
|
329
|
+
if
|
330
|
+
f.filename.nil? ||
|
331
|
+
f.function.nil? ||
|
332
|
+
f.lineno.nil? ||
|
333
|
+
f.library_frame.nil?
|
334
|
+
then
|
335
|
+
next
|
336
|
+
end
|
337
|
+
|
338
|
+
frame = {}
|
339
|
+
frame[:f] = f.filename
|
340
|
+
frame[:m] = f.function
|
341
|
+
frame[:ln] = f.lineno
|
342
|
+
if f.library_frame == false
|
343
|
+
frame[:inp] = true
|
344
|
+
if !f.context_line.nil?
|
345
|
+
frame[:code] = []
|
346
|
+
|
347
|
+
if !f.pre_context.nil?
|
348
|
+
psize = f.pre_context.size
|
349
|
+
lineno = 0
|
350
|
+
if f.lineno - psize >= 0
|
351
|
+
lineno = f.lineno - psize
|
352
|
+
end
|
353
|
+
f.pre_context.each do |c|
|
354
|
+
frame[:code].push([lineno.to_s, c])
|
355
|
+
lineno += 1
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
frame[:code].push([f.lineno.to_s, f.context_line])
|
360
|
+
|
361
|
+
if !f.post_context.nil?
|
362
|
+
psize = f.post_context.size
|
363
|
+
lineno = f.lineno + 1
|
364
|
+
f.post_context.each do |c|
|
365
|
+
frame[:code].push([lineno.to_s, c])
|
366
|
+
lineno += 1
|
367
|
+
end
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
exception[:stacktrace] << frame
|
372
|
+
end
|
373
|
+
end
|
374
|
+
error[:exceptions] << exception
|
375
|
+
errors << error
|
376
|
+
end
|
377
|
+
errors
|
315
378
|
end
|
379
|
+
|
316
380
|
end
|
317
381
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
|
2
|
+
module Atatus
|
3
|
+
module Collector
|
4
|
+
class Layer
|
5
|
+
def initialize(type, kind, duration)
|
6
|
+
@type = type
|
7
|
+
@kind = kind
|
8
|
+
@count = 1
|
9
|
+
@min = duration
|
10
|
+
@max = duration
|
11
|
+
@total = duration
|
12
|
+
end
|
13
|
+
|
14
|
+
attr_reader :type, :kind, :count, :min, :max, :total
|
15
|
+
attr_accessor :id, :pid
|
16
|
+
|
17
|
+
def aggregate!(duration)
|
18
|
+
@count += 1
|
19
|
+
@min = duration if duration < @min
|
20
|
+
@max = duration if duration > @max
|
21
|
+
@total += duration
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.span_kind(value)
|
25
|
+
return KINDS.fetch(value, value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.span_type(value)
|
29
|
+
return TYPES.fetch(value, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
KINDS = {
|
34
|
+
'db' => 'Database',
|
35
|
+
'cache' => 'Database',
|
36
|
+
'ext' => 'Remote',
|
37
|
+
'websocket' => 'Remote',
|
38
|
+
'template' => 'Template'
|
39
|
+
}.freeze
|
40
|
+
|
41
|
+
TYPES = {
|
42
|
+
'mysql' => 'MySQL',
|
43
|
+
'mysql2' => 'MySQL',
|
44
|
+
'postgresql' => 'Postgres',
|
45
|
+
'mssql' => 'MS SQL',
|
46
|
+
'mongodb' => 'MongoDB',
|
47
|
+
'redis' => 'Redis',
|
48
|
+
'graphql' => 'GraphQL',
|
49
|
+
'elasticsearch' => 'Elasticsearch',
|
50
|
+
'cassandra' => 'Cassandra',
|
51
|
+
'http' => 'External Requests',
|
52
|
+
'http2' => 'External Requests',
|
53
|
+
'http_rb' => 'External Requests',
|
54
|
+
'net_http' => 'External Requests'
|
55
|
+
}.freeze
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -2,11 +2,10 @@ require 'json'
|
|
2
2
|
require 'thread'
|
3
3
|
require 'net/http'
|
4
4
|
require 'atatus/collector/builder'
|
5
|
-
require 'json'
|
6
5
|
|
7
6
|
module Atatus
|
8
7
|
class BaseTransport
|
9
|
-
|
8
|
+
include Logging
|
10
9
|
|
11
10
|
TXN_ENDPOINT = '/track/apm/txn'.freeze
|
12
11
|
TRACE_ENDPOINT = '/track/apm/trace'.freeze
|
@@ -15,23 +14,32 @@ module Atatus
|
|
15
14
|
ERROR_METRIC_ENDPOINT = "/track/apm/error_metric".freeze
|
16
15
|
METRIC_ENDPOINT = "/track/apm/metric".freeze
|
17
16
|
|
18
|
-
def initialize(config
|
17
|
+
def initialize(config)
|
19
18
|
@config = config
|
20
|
-
@hostname = hostname
|
21
|
-
@port = port
|
22
19
|
|
23
|
-
@
|
20
|
+
@notify_host = @config.notify_host
|
21
|
+
@uri = URI(@notify_host)
|
22
|
+
if not @uri.kind_of?(URI::HTTPS) and not @uri.kind_of?(URI::HTTP)
|
23
|
+
@notify_host = "https://apm-rx.atatus.com"
|
24
|
+
@uri = URI(@notify_host)
|
25
|
+
end
|
24
26
|
|
27
|
+
@builder = Atatus::Builder.new(config)
|
25
28
|
@headers = {}
|
26
29
|
@headers['Content-Type'] = "application/json"
|
27
30
|
end
|
28
31
|
|
29
|
-
def
|
32
|
+
def hostinfo(start_time)
|
33
|
+
payload = @builder.hostinfo(start_time)
|
34
|
+
post(HOSTINFO_ENDPOINT, payload)
|
35
|
+
end
|
36
|
+
|
37
|
+
def txns(start_time, end_time, data)
|
30
38
|
payload = @builder.txns(start_time, end_time, data)
|
31
39
|
post(TXN_ENDPOINT, payload)
|
32
40
|
end
|
33
41
|
|
34
|
-
def
|
42
|
+
def traces(start_time, end_time, data)
|
35
43
|
payload = @builder.traces(start_time, end_time, data)
|
36
44
|
post(TRACE_ENDPOINT, payload)
|
37
45
|
end
|
@@ -41,11 +49,6 @@ module Atatus
|
|
41
49
|
post(ERROR_METRIC_ENDPOINT, payload)
|
42
50
|
end
|
43
51
|
|
44
|
-
def hostinfo(start_time)
|
45
|
-
payload = @builder.hostinfo(start_time)
|
46
|
-
post(HOSTINFO_ENDPOINT, payload)
|
47
|
-
end
|
48
|
-
|
49
52
|
def errors(start_time, end_time, error_data)
|
50
53
|
payload = @builder.errors(start_time, end_time, error_data)
|
51
54
|
post(ERROR_ENDPOINT, payload)
|
@@ -59,14 +62,51 @@ module Atatus
|
|
59
62
|
private
|
60
63
|
|
61
64
|
def post(endpoint, data)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
# puts ::JSON.pretty_generate(data, :max_nesting => false)
|
66
|
+
if @blocked == true and endpoint != HOSTINFO_ENDPOINT
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
begin
|
71
|
+
request = Net::HTTP::Post.new(endpoint, @headers)
|
72
|
+
request.body = ::JSON.dump(data)
|
73
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
74
|
+
http.use_ssl = true
|
75
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
76
|
+
response = http.start { |http| http.request(request) }
|
77
|
+
rescue SystemCallError, Timeout::Error, EOFError, SocketError => e
|
78
|
+
puts "Atatus transport [#{@notify_host}#{endpoint}] failed with exception: #{e}"
|
79
|
+
end
|
80
|
+
|
81
|
+
if @blocked == true
|
82
|
+
@blocked = false
|
83
|
+
end
|
84
|
+
|
85
|
+
case response
|
86
|
+
when Net::HTTPSuccess
|
87
|
+
true
|
88
|
+
when Net::HTTPBadRequest
|
89
|
+
if not response.body
|
90
|
+
error format('Atatus transport status 400, failed without content')
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
94
|
+
resp = JSON.parse response.body
|
95
|
+
if resp
|
96
|
+
if resp.key?(:blocked)
|
97
|
+
@blocked = resp[:blocked]
|
98
|
+
if @blocked == true
|
99
|
+
if resp.key?(:errorMessage)
|
100
|
+
error format('Atatus blocked from sending data as: %s', resp[:errorMessage])
|
101
|
+
return
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
error format('Atatus transport status 400, failed with content: %s', response.message)
|
108
|
+
else
|
109
|
+
end
|
70
110
|
end
|
71
111
|
end
|
72
112
|
end
|
data/lib/atatus/config.rb
CHANGED
@@ -22,9 +22,10 @@ module Atatus
|
|
22
22
|
# rubocop:disable Metrics/LineLength, Layout/ExtraSpacing
|
23
23
|
option :app_name, type: :string
|
24
24
|
option :license_key, type: :string
|
25
|
+
option :notify_host, type: :string, default: 'https://apm-rx.atatus.com'
|
25
26
|
option :trace_threshold, type: :int, default: 2000
|
26
27
|
option :config_file, type: :string, default: 'config/atatus.yml'
|
27
|
-
option :server_url, type: :string, default: '
|
28
|
+
option :server_url, type: :string, default: ''
|
28
29
|
option :secret_token, type: :string
|
29
30
|
|
30
31
|
option :active, type: :bool, default: true
|
@@ -92,7 +92,7 @@ module Atatus
|
|
92
92
|
def read_from_meminfo!
|
93
93
|
return unless File.exist?(LINUX_MEMINFO_PATH)
|
94
94
|
meminfo = File.read(LINUX_MEMINFO_PATH)
|
95
|
-
self.meminfo_total = meminfo.scan(TOTAL_MEMORY_REGEX).flatten.first.to_i
|
95
|
+
self.meminfo_total = (meminfo.scan(TOTAL_MEMORY_REGEX).flatten.first.to_i) * 1024 # to bytes
|
96
96
|
end
|
97
97
|
# rubocop:enable Metrics/MethodLength, Metrics/PerceivedComplexity
|
98
98
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
|
data/lib/atatus/version.rb
CHANGED
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.0.
|
4
|
+
version: 1.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Atatus
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-11-
|
11
|
+
date: 2019-11-21 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/central_config/cache_control.rb
|
75
75
|
- lib/atatus/collector/base.rb
|
76
76
|
- lib/atatus/collector/builder.rb
|
77
|
+
- lib/atatus/collector/layer.rb
|
77
78
|
- lib/atatus/collector/transport.rb
|
78
79
|
- lib/atatus/config.rb
|
79
80
|
- lib/atatus/config/bytes.rb
|