atatus 1.3.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/Gemfile +72 -22
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +2 -2
  6. data/lib/atatus/agent.rb +78 -29
  7. data/lib/atatus/central_config/cache_control.rb +18 -1
  8. data/lib/atatus/central_config.rb +72 -27
  9. data/lib/atatus/child_durations.rb +64 -0
  10. data/lib/atatus/collector/base.rb +102 -43
  11. data/lib/atatus/collector/builder.rb +134 -4
  12. data/lib/atatus/collector/hist.rb +54 -0
  13. data/lib/atatus/collector/layer.rb +1 -0
  14. data/lib/atatus/collector/transport.rb +41 -11
  15. data/lib/atatus/config/bytes.rb +17 -0
  16. data/lib/atatus/config/duration.rb +17 -0
  17. data/lib/atatus/config/options.rb +29 -9
  18. data/lib/atatus/config/regexp_list.rb +17 -0
  19. data/lib/atatus/config/wildcard_pattern_list.rb +64 -0
  20. data/lib/atatus/config.rb +129 -28
  21. data/lib/atatus/context/request/socket.rb +18 -1
  22. data/lib/atatus/context/request/url.rb +17 -0
  23. data/lib/atatus/context/request.rb +17 -0
  24. data/lib/atatus/context/response.rb +27 -2
  25. data/lib/atatus/context/user.rb +17 -0
  26. data/lib/atatus/context.rb +32 -1
  27. data/lib/atatus/context_builder.rb +19 -4
  28. data/lib/atatus/deprecations.rb +17 -0
  29. data/lib/atatus/error/exception.rb +24 -0
  30. data/lib/atatus/error/log.rb +17 -0
  31. data/lib/atatus/error.rb +27 -0
  32. data/lib/atatus/error_builder.rb +21 -2
  33. data/lib/atatus/grape.rb +62 -0
  34. data/lib/atatus/graphql.rb +91 -0
  35. data/lib/atatus/grpc.rb +99 -0
  36. data/lib/atatus/instrumenter.rb +135 -30
  37. data/lib/atatus/internal_error.rb +17 -0
  38. data/lib/atatus/logging.rb +17 -2
  39. data/lib/atatus/metadata/process_info.rb +17 -0
  40. data/lib/atatus/metadata/service_info.rb +21 -6
  41. data/lib/atatus/metadata/system_info/container_info.rb +49 -10
  42. data/lib/atatus/metadata/system_info/hw_info.rb +1 -1
  43. data/lib/atatus/metadata/system_info.rb +22 -3
  44. data/lib/atatus/metadata.rb +17 -0
  45. data/lib/atatus/metrics/breakdown_set.rb +31 -0
  46. data/lib/atatus/metrics/{cpu_mem.rb → cpu_mem_set.rb} +110 -63
  47. data/lib/atatus/metrics/metric.rb +140 -0
  48. data/lib/atatus/metrics/set.rb +123 -0
  49. data/lib/atatus/metrics/span_scoped_set.rb +56 -0
  50. data/lib/atatus/metrics/transaction_set.rb +26 -0
  51. data/lib/atatus/metrics/vm_set.rb +58 -0
  52. data/lib/atatus/metrics.rb +69 -27
  53. data/lib/atatus/metricset.rb +48 -4
  54. data/lib/atatus/middleware.rb +28 -8
  55. data/lib/atatus/naively_hashable.rb +17 -0
  56. data/lib/atatus/normalizers/grape/endpoint_run.rb +65 -0
  57. data/lib/atatus/normalizers/grape.rb +22 -0
  58. data/lib/atatus/normalizers/rails/action_controller.rb +44 -0
  59. data/lib/atatus/normalizers/rails/action_mailer.rb +43 -0
  60. data/lib/atatus/normalizers/{action_view.rb → rails/action_view.rb} +17 -0
  61. data/lib/atatus/normalizers/rails/active_record.rb +80 -0
  62. data/lib/atatus/normalizers/rails.rb +27 -0
  63. data/lib/atatus/normalizers.rb +23 -9
  64. data/lib/atatus/opentracing.rb +75 -42
  65. data/lib/atatus/rails.rb +29 -13
  66. data/lib/atatus/railtie.rb +19 -6
  67. data/lib/atatus/resque.rb +29 -0
  68. data/lib/atatus/sinatra.rb +53 -0
  69. data/lib/atatus/span/context/db.rb +43 -0
  70. data/lib/atatus/span/context/destination.rb +77 -0
  71. data/lib/atatus/span/context/http.rb +43 -0
  72. data/lib/atatus/span/context.rb +43 -28
  73. data/lib/atatus/span.rb +44 -15
  74. data/lib/atatus/span_helpers.rb +18 -1
  75. data/lib/atatus/spies/action_dispatch.rb +27 -6
  76. data/lib/atatus/spies/delayed_job.rb +26 -5
  77. data/lib/atatus/spies/dynamo_db.rb +62 -0
  78. data/lib/atatus/spies/elasticsearch.rb +53 -7
  79. data/lib/atatus/spies/faraday.rb +54 -20
  80. data/lib/atatus/spies/http.rb +36 -6
  81. data/lib/atatus/spies/json.rb +18 -0
  82. data/lib/atatus/spies/mongo.rb +41 -10
  83. data/lib/atatus/spies/net_http.rb +52 -11
  84. data/lib/atatus/spies/rake.rb +42 -23
  85. data/lib/atatus/spies/redis.rb +17 -0
  86. data/lib/atatus/spies/resque.rb +57 -0
  87. data/lib/atatus/spies/sequel.rb +54 -17
  88. data/lib/atatus/spies/shoryuken.rb +69 -0
  89. data/lib/atatus/spies/sidekiq.rb +46 -25
  90. data/lib/atatus/spies/sinatra.rb +20 -4
  91. data/lib/atatus/spies/sneakers.rb +74 -0
  92. data/lib/atatus/spies/sucker_punch.rb +58 -0
  93. data/lib/atatus/spies/tilt.rb +20 -1
  94. data/lib/atatus/spies.rb +33 -15
  95. data/lib/atatus/sql/signature.rb +169 -0
  96. data/lib/atatus/sql/tokenizer.rb +264 -0
  97. data/lib/atatus/sql/tokens.rb +63 -0
  98. data/lib/atatus/sql.rb +36 -0
  99. data/lib/atatus/sql_summarizer.rb +24 -6
  100. data/lib/atatus/stacktrace/frame.rb +17 -3
  101. data/lib/atatus/stacktrace.rb +17 -0
  102. data/lib/atatus/stacktrace_builder.rb +23 -3
  103. data/lib/atatus/subscriber.rb +23 -4
  104. data/lib/atatus/trace_context/traceparent.rb +111 -0
  105. data/lib/atatus/trace_context/tracestate.rb +148 -0
  106. data/lib/atatus/trace_context.rb +84 -51
  107. data/lib/atatus/transaction.rb +74 -18
  108. data/lib/atatus/transport/base.rb +44 -27
  109. data/lib/atatus/transport/connection/http.rb +58 -35
  110. data/lib/atatus/transport/connection/proxy_pipe.rb +24 -5
  111. data/lib/atatus/transport/connection.rb +28 -72
  112. data/lib/atatus/transport/filters/hash_sanitizer.rb +77 -0
  113. data/lib/atatus/transport/filters/secrets_filter.rb +30 -55
  114. data/lib/atatus/transport/filters.rb +18 -1
  115. data/lib/atatus/transport/headers.rb +83 -0
  116. data/lib/atatus/transport/serializers/context_serializer.rb +30 -3
  117. data/lib/atatus/transport/serializers/error_serializer.rb +17 -2
  118. data/lib/atatus/transport/serializers/metadata_serializer.rb +44 -22
  119. data/lib/atatus/transport/serializers/metricset_serializer.rb +34 -6
  120. data/lib/atatus/transport/serializers/span_serializer.rb +47 -12
  121. data/lib/atatus/transport/serializers/transaction_serializer.rb +18 -2
  122. data/lib/atatus/transport/serializers.rb +17 -5
  123. data/lib/atatus/transport/user_agent.rb +48 -0
  124. data/lib/atatus/transport/worker.rb +31 -7
  125. data/lib/atatus/util/inflector.rb +17 -0
  126. data/lib/atatus/util/lru_cache.rb +17 -0
  127. data/lib/atatus/util/throttle.rb +17 -0
  128. data/lib/atatus/util.rb +18 -1
  129. data/lib/atatus/version.rb +19 -1
  130. data/lib/atatus.rb +84 -16
  131. metadata +46 -26
  132. data/Rakefile +0 -19
  133. data/bench/.gitignore +0 -2
  134. data/bench/app.rb +0 -53
  135. data/bench/benchmark.rb +0 -36
  136. data/bench/report.rb +0 -55
  137. data/bench/rubyprof.rb +0 -39
  138. data/bench/stackprof.rb +0 -23
  139. data/bin/build_docs +0 -5
  140. data/bin/console +0 -15
  141. data/bin/setup +0 -8
  142. data/bin/with_framework +0 -7
  143. data/lib/atatus/metrics/vm.rb +0 -60
  144. data/lib/atatus/normalizers/action_controller.rb +0 -27
  145. data/lib/atatus/normalizers/action_mailer.rb +0 -26
  146. data/lib/atatus/normalizers/active_record.rb +0 -45
  147. data/lib/atatus/util/prefixed_logger.rb +0 -18
  148. data/vendor/.gitkeep +0 -0
@@ -0,0 +1,64 @@
1
+ # Licensed to Elasticsearch B.V. under one or more contributor
2
+ # license agreements. See the NOTICE file distributed with
3
+ # this work for additional information regarding copyright
4
+ # ownership. Elasticsearch B.V. licenses this file to you under
5
+ # the Apache License, Version 2.0 (the "License"); you may
6
+ # not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ # frozen_string_literal: true
19
+
20
+ module Atatus
21
+ # @api private
22
+ module ChildDurations
23
+ # @api private
24
+ module Methods
25
+ def child_durations
26
+ @child_durations ||= Durations.new
27
+ end
28
+
29
+ def child_started
30
+ child_durations.start
31
+ end
32
+
33
+ def child_stopped
34
+ child_durations.stop
35
+ end
36
+ end
37
+
38
+ # @api private
39
+ class Durations
40
+ def initialize
41
+ @nesting_level = 0
42
+ @start = nil
43
+ @duration = 0
44
+ @mutex = Mutex.new
45
+ end
46
+
47
+ attr_reader :duration
48
+
49
+ def start
50
+ @mutex.synchronize do
51
+ @nesting_level += 1
52
+ @start = Util.micros if @nesting_level == 1
53
+ end
54
+ end
55
+
56
+ def stop
57
+ @mutex.synchronize do
58
+ @nesting_level -= 1
59
+ @duration = (Util.micros - @start) if @nesting_level == 0
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,11 +1,13 @@
1
1
  require 'json'
2
2
  require 'atatus'
3
3
  require 'atatus/config'
4
+ require 'atatus/child_durations'
4
5
  require 'atatus/transaction'
6
+ require 'atatus/collector/hist'
5
7
  require 'atatus/collector/layer'
6
8
  require 'atatus/collector/transport'
7
9
 
8
- SpanTiming = Struct.new(:start, :end)
10
+ SpanTiming = Struct.new(:name, :type, :subtype, :start, :end, :duration, :id, :transaction_id)
9
11
 
10
12
  module Atatus
11
13
  module Collector
@@ -29,6 +31,7 @@ module Atatus
29
31
 
30
32
  @txns_lock = Mutex.new
31
33
  @txns_agg = {}
34
+ @txn_hist_agg = {}
32
35
  @traces_agg = []
33
36
  @error_metrics_agg = {}
34
37
  @error_requests_agg = []
@@ -39,7 +42,7 @@ module Atatus
39
42
  @metrics_lock = Mutex.new
40
43
  @metrics_agg = []
41
44
 
42
- @transport = Atatus::BaseTransport.new(config)
45
+ @transport = Atatus::BaseTransport.new(config)
43
46
  @collect_counter = 0
44
47
  @running = false
45
48
  end
@@ -69,6 +72,11 @@ module Atatus
69
72
  error "Backtrace:\n" + e.backtrace.join("\n")
70
73
  end
71
74
 
75
+ def handle_forking!
76
+ stop
77
+ start
78
+ end
79
+
72
80
  def add_error(error)
73
81
  ensure_worker_running
74
82
 
@@ -84,7 +92,7 @@ module Atatus
84
92
 
85
93
  def add_metrics(metricset)
86
94
  ensure_worker_running
87
-
95
+
88
96
  metric_added = false
89
97
  metric = {}
90
98
 
@@ -99,13 +107,17 @@ module Atatus
99
107
  metric_added = true
100
108
  end
101
109
 
102
- 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}
110
+ if %i[ruby.gc.count ruby.threads ruby.heap.slots.live ruby.heap.slots.free ruby.heap.allocations.total].all? {|s| metricset.samples.key? s}
103
111
  then
104
112
  metric[:'ruby.gc.count'] = metricset.samples[:'ruby.gc.count']
105
113
  metric[:'ruby.threads'] = metricset.samples[:'ruby.threads']
106
114
  metric[:'ruby.heap.slots.live'] = metricset.samples[:'ruby.heap.slots.live']
107
115
  metric[:'ruby.heap.slots.free'] = metricset.samples[:'ruby.heap.slots.free']
108
116
  metric[:'ruby.heap.allocations.total'] = metricset.samples[:'ruby.heap.allocations.total']
117
+ if %i[ruby.gc.time].all? {|s| metricset.samples.key? s}
118
+ then
119
+ metric[:'ruby.gc.time'] = metricset.samples[:'ruby.gc.time']
120
+ end
109
121
  metric_added = true
110
122
  end
111
123
 
@@ -120,10 +132,10 @@ module Atatus
120
132
  ensure_worker_running
121
133
 
122
134
  if
123
- span.transaction_id.nil? ||
124
- span.name.nil? ||
125
- span.type.nil? ||
126
- span.subtype.nil? ||
135
+ span.transaction_id.nil? ||
136
+ span.name.nil? ||
137
+ span.type.nil? ||
138
+ span.subtype.nil? ||
127
139
  span.duration.nil?
128
140
  then
129
141
  return
@@ -135,10 +147,10 @@ module Atatus
135
147
  def add_txn(txn)
136
148
  ensure_worker_running
137
149
 
138
- if
139
- txn.name.nil? ||
140
- txn.id.nil? ||
141
- txn.timestamp.nil? ||
150
+ if
151
+ txn.name.nil? ||
152
+ txn.id.nil? ||
153
+ txn.timestamp.nil? ||
142
154
  txn.duration.nil?
143
155
  then
144
156
  return
@@ -148,14 +160,15 @@ module Atatus
148
160
  return if txn.duration <= 0
149
161
 
150
162
  @txns_lock.synchronize do
151
- if !@txns_agg.key?(txn.name)
152
- txn_type = @config.framework_name || "Ruby"
153
- background = false
154
- if !txn.type.nil?
155
- if txn.type == "Sidekiq"
156
- background = true
157
- end
163
+ txn_type = @config.framework_name || "Ruby"
164
+ background = false
165
+ if !txn.type.nil?
166
+ if txn.type == "Sidekiq"
167
+ background = true
158
168
  end
169
+ end
170
+
171
+ if !@txns_agg.key?(txn.name)
159
172
  @txns_agg[txn.name] = Txn.new(txn_type, "Ruby", txn.duration, background: background)
160
173
  @txns_agg[txn.name].id = txn.id
161
174
  @txns_agg[txn.name].pid = txn.id
@@ -163,17 +176,25 @@ module Atatus
163
176
  @txns_agg[txn.name].aggregate! txn.duration
164
177
  end
165
178
 
179
+ if background == false and txn.duration <= 150*1000*1000.0
180
+ if !@txn_hist_agg.key?(txn.name)
181
+ @txn_hist_agg[txn.name] = TxnHist.new(txn_type, "Ruby", Util.ms(txn.duration))
182
+ else
183
+ @txn_hist_agg[txn.name].aggregate! Util.ms(txn.duration)
184
+ end
185
+ end
186
+
166
187
  spans_present = false
167
188
  ruby_time = 0
168
189
  spans_tuple = []
169
190
  if @spans.key?(txn.id)
170
191
  spans_present = true
171
192
  @spans[txn.id].each do |span|
172
- if
173
- span.name.nil? ||
174
- span.type.nil? ||
175
- span.subtype.nil? ||
176
- span.timestamp.nil? ||
193
+ if
194
+ span.name.nil? ||
195
+ span.type.nil? ||
196
+ span.subtype.nil? ||
197
+ span.timestamp.nil? ||
177
198
  span.duration.nil?
178
199
  then
179
200
  next
@@ -183,16 +204,7 @@ module Atatus
183
204
 
184
205
  if span.timestamp >= txn.timestamp
185
206
  start = Util.ms(span.timestamp - txn.timestamp)
186
- spans_tuple.push(SpanTiming.new(start, start + Util.ms(span.duration)))
187
- if !@txns_agg[txn.name].spans.key?(span.name)
188
- kind = Layer.span_kind(span.type)
189
- type = Layer.span_type(span.subtype)
190
- @txns_agg[txn.name].spans[span.name] = Layer.new(type, kind, span.duration)
191
- @txns_agg[txn.name].spans[span.name].id = span.id
192
- @txns_agg[txn.name].spans[span.name].pid = span.transaction_id
193
- else
194
- @txns_agg[txn.name].spans[span.name].aggregate! span.duration
195
- end
207
+ spans_tuple.push(SpanTiming.new(span.name, span.type, span.subtype, start, start + Util.ms(span.duration), span.duration, span.id, span.transaction_id))
196
208
  end
197
209
  end
198
210
  end
@@ -201,6 +213,40 @@ module Atatus
201
213
  ruby_time = Util.ms(txn.duration)
202
214
  else
203
215
  spans_tuple.sort! {| a, b | a[:start] <=> b[:start] }
216
+ j = 0
217
+ while j < spans_tuple.length
218
+ if spans_tuple[j].subtype == 'controller' || spans_tuple[j].subtype == 'view' || spans_tuple[j].subtype == 'tilt'
219
+ k = j+1
220
+ while k < spans_tuple.length
221
+ if spans_tuple[k].start >= spans_tuple[j].end
222
+ break
223
+ else
224
+ if spans_tuple[k].end <= spans_tuple[j].end
225
+ spans_tuple[j].duration -= Util.us(spans_tuple[k].end - spans_tuple[k].start)
226
+ else
227
+ spans_tuple[j].duration -= Util.us(spans_tuple[j].end - spans_tuple[k].start)
228
+ end
229
+ end
230
+ k += 1
231
+ end
232
+ if spans_tuple[j].duration <= 0
233
+ spans_tuple[j].duration = 1
234
+ end
235
+ end
236
+
237
+ if !@txns_agg[txn.name].spans.key?(spans_tuple[j].name)
238
+ kind = Layer.span_kind(spans_tuple[j].type)
239
+ type = Layer.span_type(spans_tuple[j].subtype)
240
+ @txns_agg[txn.name].spans[spans_tuple[j].name] = Layer.new(type, kind, spans_tuple[j].duration)
241
+ @txns_agg[txn.name].spans[spans_tuple[j].name].id = spans_tuple[j].id
242
+ @txns_agg[txn.name].spans[spans_tuple[j].name].pid = spans_tuple[j].transaction_id
243
+ else
244
+ @txns_agg[txn.name].spans[spans_tuple[j].name].aggregate! spans_tuple[j].duration
245
+ end
246
+
247
+ j += 1
248
+ end
249
+
204
250
  ruby_time = spans_tuple[0].start
205
251
  span_end = spans_tuple[0].end
206
252
  j = 0
@@ -244,12 +290,12 @@ module Atatus
244
290
  @spans.delete(txn.id)
245
291
  end
246
292
 
247
- if
248
- !txn.context.nil? &&
249
- !txn.context.response.nil? &&
293
+ if
294
+ !txn.context.nil? &&
295
+ !txn.context.response.nil? &&
250
296
  !txn.context.response.status_code.nil?
251
297
  then
252
- status_code = txn.context.response.status_code
298
+ status_code = txn.context.response.status_code.to_i
253
299
 
254
300
  if status_code >= 400 && status_code != 404
255
301
  if !@error_metrics_agg.key?(txn.name)
@@ -262,11 +308,13 @@ module Atatus
262
308
  end
263
309
  end
264
310
 
311
+ trace_id = ""
312
+ trace_id = txn.trace_id if !txn.trace_id.nil?
265
313
  if @error_requests_agg.length < 20
266
- @error_requests_agg.push({'name' => txn.name, 'context' => txn.context})
314
+ @error_requests_agg.push({'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context})
267
315
  else
268
316
  i = rand(20)
269
- @error_requests_agg[i] = {'name' => txn.name, 'context' => txn.context}
317
+ @error_requests_agg[i] = {'name' => txn.name, 'txn_id' => txn.id, 'trace_id' => trace_id, 'context' => txn.context}
270
318
  end
271
319
  end
272
320
  end
@@ -317,6 +365,7 @@ module Atatus
317
365
  debug '%s: data collector', pid_str
318
366
 
319
367
  txns_data = nil
368
+ txn_hist_data = nil
320
369
  traces_data = nil
321
370
  error_metrics_data = nil
322
371
  error_requests_data = nil
@@ -327,6 +376,9 @@ module Atatus
327
376
  txns_data = @txns_agg
328
377
  @txns_agg = {}
329
378
 
379
+ txn_hist_data = @txn_hist_agg
380
+ @txn_hist_agg = {}
381
+
330
382
  traces_data = @traces_agg
331
383
  @traces_agg = []
332
384
 
@@ -341,7 +393,7 @@ module Atatus
341
393
  errors_data = @errors_aggs
342
394
  @errors_aggs = []
343
395
  end
344
-
396
+
345
397
  @metrics_lock.synchronize do
346
398
  metrics_data = @metrics_agg
347
399
  @metrics_agg = []
@@ -349,7 +401,14 @@ module Atatus
349
401
 
350
402
  @transport.txns(start_time, end_time, txns_data) unless txns_data.empty?
351
403
 
352
- @transport.traces(start_time, end_time, traces_data) unless traces_data.empty?
404
+ @transport.txn_hist(start_time, end_time, txn_hist_data) unless txn_hist_data.empty?
405
+
406
+ unless traces_data.empty?
407
+ traces_data.each do |trace|
408
+ individual_trace_data = [trace]
409
+ @transport.traces(start_time, end_time, individual_trace_data)
410
+ end
411
+ end
353
412
 
354
413
  @transport.error_metrics(start_time, end_time, error_metrics_data, error_requests_data) unless error_metrics_data.empty?
355
414
 
@@ -359,4 +418,4 @@ module Atatus
359
418
  end
360
419
  end
361
420
  end
362
- end
421
+ end
@@ -3,8 +3,7 @@ require 'atatus/metadata'
3
3
  require 'yaml'
4
4
  module Atatus
5
5
  class Builder
6
- AGENT_NAME = 'Ruby'
7
-
6
+
8
7
  def initialize(config)
9
8
  @config = config
10
9
  @metadata = Metadata::SystemInfo.new(config)
@@ -53,6 +52,14 @@ module Atatus
53
52
  payload
54
53
  end
55
54
 
55
+ def txn_hist(start_time, end_time, data)
56
+ payload = common()
57
+ payload[:startTime] = start_time
58
+ payload[:endTime] = end_time
59
+ payload[:transactions] = build_txn_hist_obj(data)
60
+ payload
61
+ end
62
+
56
63
  def traces(start_time, end_time, data)
57
64
  payload = common()
58
65
  payload[:startTime] = start_time
@@ -149,6 +156,20 @@ module Atatus
149
156
  m
150
157
  end
151
158
 
159
+ def build_hist_metric(name, value)
160
+ return unless name
161
+ return unless value
162
+
163
+ m = {
164
+ name: name,
165
+ type: value.type,
166
+ kind: value.kind,
167
+ histogram: value.hist,
168
+ }
169
+
170
+ m
171
+ end
172
+
152
173
  def build_request(context)
153
174
  request = {}
154
175
  return request unless context
@@ -174,7 +195,7 @@ module Atatus
174
195
 
175
196
  if !context.response.nil?
176
197
  if !context.response.status_code.nil?
177
- request[:statusCode] = context.response.status_code
198
+ request[:statusCode] = context.response.status_code.to_i
178
199
  end
179
200
  end
180
201
 
@@ -195,6 +216,17 @@ module Atatus
195
216
  txns
196
217
  end
197
218
 
219
+ def build_txn_hist_obj(data)
220
+ txn_hist = []
221
+ data.each do |t, v|
222
+ hist = build_hist_metric(t, v)
223
+ if hist
224
+ txn_hist << hist
225
+ end
226
+ end
227
+ txn_hist
228
+ end
229
+
198
230
  def build_traces_obj(data)
199
231
  traces = []
200
232
  data.each do |txn|
@@ -205,11 +237,17 @@ module Atatus
205
237
  then
206
238
  next
207
239
  end
240
+ txn_id = ""
241
+ txn_id = txn.id if !txn.id.nil?
242
+ trace_id = ""
243
+ trace_id = txn.trace_id if !txn.trace_id.nil?
208
244
 
209
245
  trace = {}
210
246
  trace[:name] = txn.name
211
247
  trace[:type] = @config.framework_name || AGENT_NAME
212
248
  trace[:kind] = AGENT_NAME
249
+ trace[:txnId] = txn_id
250
+ trace[:traceId] = trace_id
213
251
  trace[:start] = txn.timestamp
214
252
  trace[:duration] = Util.ms(txn.duration)
215
253
  if !txn.context.nil?
@@ -217,6 +255,28 @@ module Atatus
217
255
  end
218
256
  trace[:entries] = []
219
257
  trace[:funcs] = []
258
+
259
+ if
260
+ !txn.context.nil? &&
261
+ defined?(txn.context.custom) &&
262
+ !txn.context.custom.nil? &&
263
+ !txn.context.custom.empty?
264
+ then
265
+ trace[:customData] = txn.context.custom
266
+ end
267
+
268
+ if
269
+ !txn.context.nil? &&
270
+ defined?(txn.context.user) &&
271
+ !txn.context.user.nil? &&
272
+ !txn.context.user.empty?
273
+ then
274
+ trace[:user] = {}
275
+ trace[:user][:id] = txn.context.user.id
276
+ trace[:user][:email] = txn.context.user.email
277
+ trace[:user][:username] = txn.context.user.username
278
+ end
279
+
220
280
  i = 0
221
281
 
222
282
  if
@@ -239,11 +299,23 @@ module Atatus
239
299
  if
240
300
  !span.context.nil? &&
241
301
  !span.context.db.nil? &&
302
+ defined?(span.context.db.statement) &&
242
303
  !span.context.db.statement.nil?
243
304
  then
244
305
  entry[:dt] = {}
245
306
  entry[:dt][:query] = span.context.db.statement
246
307
  end
308
+ if
309
+ !span.context.nil? &&
310
+ !span.context.http.nil? &&
311
+ defined?(span.context.http.url) &&
312
+ !span.context.http.url.nil?
313
+ then
314
+ entry[:dt] = {}
315
+ entry[:dt][:url] = span.context.http.url
316
+ entry[:dt][:method] = span.context.http.method if defined?(span.context.http.method) && !span.context.http.method.nil?
317
+ entry[:dt][:status_code] = span.context.http.status_code.to_s if defined?(span.context.http.status_code) && !span.context.http.status_code.nil?
318
+ end
247
319
  trace[:entries] << entry
248
320
  func_index = trace[:funcs].index(span.name)
249
321
  if func_index.nil?
@@ -303,11 +375,39 @@ module Atatus
303
375
  then
304
376
  next
305
377
  end
378
+ txn_id = ""
379
+ txn_id = v['txn_id'] if v.key?('txn_id')
380
+ trace_id = ""
381
+ trace_id = v['trace_id'] if v.key?('trace_id')
306
382
  error_request = {}
307
383
  error_request[:name] = v['name']
308
384
  error_request[:type] = @config.framework_name || AGENT_NAME
309
385
  error_request[:kind] = AGENT_NAME
386
+ error_request[:txnId] = txn_id
387
+ error_request[:traceId] = trace_id
310
388
  error_request[:request] = build_request(v['context'])
389
+
390
+ if
391
+ !v['context'].nil? &&
392
+ defined?(v['context'].custom) &&
393
+ !v['context'].custom.nil? &&
394
+ !v['context'].custom.empty?
395
+ then
396
+ error_request[:customData] = v['context'].custom
397
+ end
398
+
399
+ if
400
+ !v['context'].nil? &&
401
+ defined?(v['context'].user) &&
402
+ !v['context'].user.nil? &&
403
+ !v['context'].user.empty?
404
+ then
405
+ error_request[:user] = {}
406
+ error_request[:user][:id] = v['context'].user.id
407
+ error_request[:user][:email] = v['context'].user.email
408
+ error_request[:user][:username] = v['context'].user.username
409
+ end
410
+
311
411
  error_requests << error_request
312
412
  end
313
413
  error_requests
@@ -340,9 +440,39 @@ module Atatus
340
440
  error[:transaction] = v.transaction[:name]
341
441
  end
342
442
 
443
+ txn_id = ""
444
+ txn_id = v.transaction_id if !v.transaction_id.nil?
445
+ trace_id = ""
446
+ trace_id = v.trace_id if !v.trace_id.nil?
447
+
448
+ error[:txnId] = txn_id
449
+ error[:traceId] = trace_id
450
+
343
451
  if !v.context.nil?
344
452
  error[:request] = build_request(v.context)
345
453
  end
454
+
455
+ if
456
+ !v.context.nil? &&
457
+ defined?(v.context.custom) &&
458
+ !v.context.custom.nil? &&
459
+ !v.context.custom.empty?
460
+ then
461
+ error[:customData] = v.context.custom
462
+ end
463
+
464
+ if
465
+ !v.context.nil? &&
466
+ defined?(v.context.user) &&
467
+ !v.context.user.nil? &&
468
+ !v.context.user.empty?
469
+ then
470
+ error[:user] = {}
471
+ error[:user][:id] = v.context.user.id
472
+ error[:user][:email] = v.context.user.email
473
+ error[:user][:username] = v.context.user.username
474
+ end
475
+
346
476
  error[:exceptions] = []
347
477
  exception = {}
348
478
  exception[:class] = v.exception.type
@@ -365,7 +495,7 @@ module Atatus
365
495
  frame = {}
366
496
  frame[:f] = f.filename
367
497
  frame[:m] = f.function
368
- frame[:ln] = f.lineno
498
+ frame[:ln] = f.lineno.to_i
369
499
  if f.library_frame == false
370
500
  frame[:inp] = true
371
501
  end
@@ -0,0 +1,54 @@
1
+
2
+ module Atatus
3
+ module Collector
4
+ class TxnHist
5
+ def initialize(type, kind, duration)
6
+ @type = type
7
+ @kind = kind
8
+ @hist = {}
9
+ @hist[find_bin duration] = 1
10
+ end
11
+
12
+ attr_reader :type, :kind, :hist
13
+
14
+ def aggregate!(duration)
15
+ hbin = find_bin duration
16
+ if !@hist.key?(hbin)
17
+ @hist[hbin] = 1
18
+ else
19
+ @hist[hbin] += 1
20
+ end
21
+ end
22
+
23
+ private
24
+ def find_bin(duration)
25
+ seconds = 1000
26
+ hbin = 0
27
+
28
+ if duration < 0
29
+ hbin = 0
30
+ elsif duration < 2*seconds
31
+ hbin = round_bin(duration, 10)
32
+ elsif duration < 10*seconds
33
+ hbin = round_bin(duration, 25)
34
+ elsif duration < 20*seconds
35
+ hbin = round_bin(duration, 50)
36
+ elsif duration < 50*seconds
37
+ hbin = round_bin(duration, 100)
38
+ elsif duration < 80*seconds
39
+ hbin = round_bin(duration, 200)
40
+ elsif duration < 100*seconds
41
+ hbin = round_bin(duration, 250)
42
+ else
43
+ hbin = round_bin(duration, 1000)
44
+ end
45
+
46
+ hbin
47
+ end
48
+
49
+ def round_bin(duration, unit)
50
+ ((duration / unit.to_f).floor) * unit
51
+ end
52
+ end
53
+ end
54
+ 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',