atatus 1.7.0 → 2.0.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.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/Gemfile +49 -13
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +3 -3
  6. data/lib/atatus/agent.rb +10 -7
  7. data/lib/atatus/central_config.rb +19 -8
  8. data/lib/atatus/collector/layer.rb +1 -1
  9. data/lib/atatus/{sql_summarizer.rb → config/log_level_map.rb} +22 -28
  10. data/lib/atatus/config/options.rb +2 -1
  11. data/lib/atatus/config/regexp_list.rb +1 -1
  12. data/lib/atatus/config/round_float.rb +31 -0
  13. data/lib/atatus/config/server_info.rb +50 -0
  14. data/lib/atatus/config/wildcard_pattern_list.rb +3 -1
  15. data/lib/atatus/config.rb +91 -70
  16. data/lib/atatus/context/request/socket.rb +1 -2
  17. data/lib/atatus/context/response.rb +1 -3
  18. data/lib/atatus/context.rb +3 -10
  19. data/lib/atatus/context_builder.rb +3 -3
  20. data/lib/atatus/error.rb +2 -1
  21. data/lib/atatus/error_builder.rb +1 -1
  22. data/lib/atatus/fields.rb +98 -0
  23. data/lib/atatus/graphql.rb +2 -0
  24. data/lib/atatus/grpc.rb +5 -7
  25. data/lib/atatus/instrumenter.rb +29 -25
  26. data/lib/atatus/metadata/cloud_info.rb +156 -0
  27. data/lib/atatus/metadata/service_info.rb +3 -3
  28. data/lib/atatus/metadata/system_info/container_info.rb +20 -8
  29. data/lib/atatus/metadata/system_info.rb +20 -5
  30. data/lib/atatus/metadata.rb +3 -1
  31. data/lib/atatus/metrics/cpu_mem_set.rb +10 -38
  32. data/lib/atatus/metrics/jvm_set.rb +88 -0
  33. data/lib/atatus/metrics/metric.rb +2 -0
  34. data/lib/atatus/metrics.rb +33 -16
  35. data/lib/atatus/middleware.rb +8 -3
  36. data/lib/atatus/naively_hashable.rb +1 -0
  37. data/lib/atatus/normalizers/rails/active_record.rb +25 -7
  38. data/lib/atatus/normalizers.rb +2 -2
  39. data/lib/atatus/opentracing.rb +5 -3
  40. data/lib/atatus/rails.rb +1 -1
  41. data/lib/atatus/span/context/db.rb +1 -1
  42. data/lib/atatus/span/context/destination.rb +58 -32
  43. data/lib/atatus/span/context/http.rb +2 -0
  44. data/lib/atatus/span/context/links.rb +32 -0
  45. data/lib/atatus/{sql.rb → span/context/message.rb} +16 -12
  46. data/lib/atatus/span/context/service.rb +55 -0
  47. data/lib/atatus/span/context.rb +28 -3
  48. data/lib/atatus/span.rb +35 -5
  49. data/lib/atatus/span_helpers.rb +12 -23
  50. data/lib/atatus/spies/action_dispatch.rb +10 -13
  51. data/lib/atatus/spies/azure_storage_table.rb +148 -0
  52. data/lib/atatus/spies/delayed_job.rb +19 -13
  53. data/lib/atatus/spies/dynamo_db.rb +56 -15
  54. data/lib/atatus/spies/elasticsearch.rb +54 -39
  55. data/lib/atatus/spies/faraday.rb +92 -58
  56. data/lib/atatus/spies/http.rb +33 -37
  57. data/lib/atatus/spies/json.rb +5 -9
  58. data/lib/atatus/spies/mongo.rb +26 -19
  59. data/lib/atatus/spies/net_http.rb +53 -51
  60. data/lib/atatus/spies/racecar.rb +77 -0
  61. data/lib/atatus/spies/rake.rb +27 -27
  62. data/lib/atatus/spies/redis.rb +11 -12
  63. data/lib/atatus/spies/resque.rb +18 -23
  64. data/lib/atatus/spies/s3.rb +132 -0
  65. data/lib/atatus/spies/sequel.rb +11 -2
  66. data/lib/atatus/spies/shoryuken.rb +4 -6
  67. data/lib/atatus/spies/sidekiq.rb +23 -31
  68. data/lib/atatus/spies/sinatra.rb +20 -28
  69. data/lib/atatus/spies/sneakers.rb +2 -0
  70. data/lib/atatus/spies/sns.rb +126 -0
  71. data/lib/atatus/spies/sqs.rb +231 -0
  72. data/lib/atatus/spies/sucker_punch.rb +20 -22
  73. data/lib/atatus/spies/tilt.rb +10 -13
  74. data/lib/atatus/spies.rb +20 -0
  75. data/lib/atatus/sql/signature.rb +4 -2
  76. data/lib/atatus/sql/tokenizer.rb +23 -7
  77. data/lib/atatus/stacktrace/frame.rb +1 -0
  78. data/lib/atatus/stacktrace_builder.rb +12 -16
  79. data/lib/atatus/subscriber.rb +1 -0
  80. data/lib/atatus/trace_context/traceparent.rb +5 -8
  81. data/lib/atatus/trace_context/tracestate.rb +16 -14
  82. data/lib/atatus/trace_context.rb +6 -16
  83. data/lib/atatus/transaction.rb +17 -4
  84. data/lib/atatus/transport/base.rb +1 -3
  85. data/lib/atatus/transport/connection/http.rb +11 -3
  86. data/lib/atatus/transport/connection/proxy_pipe.rb +1 -2
  87. data/lib/atatus/transport/connection.rb +3 -2
  88. data/lib/atatus/transport/filters/hash_sanitizer.rb +16 -34
  89. data/lib/atatus/transport/filters/secrets_filter.rb +35 -12
  90. data/lib/atatus/transport/serializers/context_serializer.rb +1 -2
  91. data/lib/atatus/transport/serializers/metadata_serializer.rb +54 -8
  92. data/lib/atatus/transport/serializers/metricset_serializer.rb +2 -2
  93. data/lib/atatus/transport/serializers/span_serializer.rb +55 -9
  94. data/lib/atatus/transport/serializers/transaction_serializer.rb +1 -0
  95. data/lib/atatus/transport/serializers.rb +9 -6
  96. data/lib/atatus/transport/user_agent.rb +16 -9
  97. data/lib/atatus/transport/worker.rb +2 -1
  98. data/lib/atatus/util/deep_dup.rb +65 -0
  99. data/lib/atatus/util/precision_validator.rb +46 -0
  100. data/lib/atatus/util.rb +2 -0
  101. data/lib/atatus/version.rb +1 -1
  102. data/lib/atatus.rb +32 -5
  103. metadata +40 -11
@@ -35,9 +35,11 @@ module Atatus
35
35
  yield
36
36
 
37
37
  transaction&.done :success
38
+ transaction&.outcome = Transaction::Outcome::SUCCESS
38
39
  rescue ::Exception => e
39
40
  Atatus.report(e, handled: false)
40
41
  transaction&.done :error
42
+ transaction&.outcome = Transaction::Outcome::FAILURE
41
43
  raise
42
44
  ensure
43
45
  Atatus.end_transaction
@@ -56,47 +58,37 @@ module Atatus
56
58
  end
57
59
 
58
60
  def install_middleware
59
- if defined?(::Sidekiq)
61
+ Sidekiq.configure_server do |config|
62
+ config.server_middleware do |chain|
63
+ chain.add Middleware
64
+ end
65
+ end
66
+ end
60
67
 
61
- Sidekiq.configure_server do |config|
62
- config.server_middleware do |chain|
63
- chain.add Middleware
68
+ # @api private
69
+ module Ext
70
+ def start
71
+ super.tap do
72
+ # Already running from Railtie if Rails
73
+ if Atatus.running?
74
+ Atatus.agent.config.logger = Sidekiq.logger
75
+ else
76
+ Atatus.start
64
77
  end
65
78
  end
79
+ end
66
80
 
81
+ def terminate
82
+ super.tap do
83
+ Atatus.stop
84
+ end
67
85
  end
68
86
  end
69
87
 
70
88
  def install_processor
71
89
  require 'sidekiq/processor'
72
90
 
73
- if defined?(::Sidekiq) && defined?(::Sidekiq::Processor)
74
-
75
- Sidekiq::Processor.class_eval do
76
- alias start_without_apm start
77
- alias terminate_without_apm terminate
78
-
79
- def start
80
- result = start_without_apm
81
-
82
- # Already running from Railtie if Rails
83
- if Atatus.running?
84
- Atatus.agent.config.logger = Sidekiq.logger
85
- else
86
- Atatus.start
87
- end
88
-
89
- result
90
- end
91
-
92
- def terminate
93
- terminate_without_apm
94
-
95
- Atatus.stop
96
- end
97
- end
98
-
99
- end
91
+ Sidekiq::Processor.prepend(Ext)
100
92
  end
101
93
 
102
94
  def install
@@ -22,42 +22,34 @@ module Atatus
22
22
  module Spies
23
23
  # @api private
24
24
  class SinatraSpy
25
- def install
26
- if defined?(::Sinatra) &&
27
- defined?(::Sinatra::Base) &&
28
- ::Sinatra::Base.private_method_defined?(:dispatch!) &&
29
- ::Sinatra::Base.private_method_defined?(:compile_template)
30
-
31
- ::Sinatra::Base.class_eval do
32
- alias dispatch_without_apm! dispatch!
33
- alias compile_template_without_apm compile_template
34
-
35
- def dispatch!(*args, &block)
36
- dispatch_without_apm!(*args, &block).tap do
37
- next unless (transaction = Atatus.current_transaction)
38
- next unless (route = env['sinatra.route'])
39
-
40
- transaction.name = route
41
- end
42
- end
43
-
44
- def compile_template(engine, data, opts, *args, &block)
45
- opts[:__atatus_template_name] =
46
- case data
47
- when Symbol then data.to_s
48
- else format('Inline %s', engine)
49
- end
25
+ # @api private
26
+ module Ext
27
+ def dispatch!(*args, &block)
28
+ super(*args, &block).tap do
29
+ next unless (transaction = Atatus.current_transaction)
30
+ next unless (route = env['sinatra.route'])
31
+
32
+ transaction.name = route
33
+ end
34
+ end
50
35
 
51
- compile_template_without_apm(engine, data, opts, *args, &block)
36
+ def compile_template(engine, data, opts, *args, &block)
37
+ opts[:__atatus_template_name] =
38
+ case data
39
+ when Symbol then data.to_s
40
+ else format('Inline %s', engine)
52
41
  end
53
- end
54
42
 
43
+ super(engine, data, opts, *args, &block)
55
44
  end
56
45
  end
46
+
47
+ def install
48
+ ::Sinatra::Base.prepend(Ext)
49
+ end
57
50
  end
58
51
 
59
52
  register 'Sinatra::Base', 'sinatra/base', SinatraSpy.new
60
-
61
53
  require 'atatus/spies/tilt'
62
54
  end
63
55
  end
@@ -57,11 +57,13 @@ module Atatus
57
57
 
58
58
  res = @app.call(deserialized_msg, delivery_info, metadata, handler)
59
59
  transaction&.done(:success)
60
+ transaction&.outcome = Transaction::Outcome::SUCCESS
60
61
 
61
62
  res
62
63
  rescue ::Exception => e
63
64
  Atatus.report(e, handled: false)
64
65
  transaction&.done(:error)
66
+ transaction&.outcome = Transaction::Outcome::FAILURE
65
67
  raise
66
68
  ensure
67
69
  Atatus.end_transaction
@@ -0,0 +1,126 @@
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 Spies
23
+ # @api private
24
+ class SNSSpy
25
+ TYPE = 'messaging'
26
+ SUBTYPE = 'sns'
27
+ AP_REGEX = /:accesspoint[\/:].*/
28
+ AP_REGION_REGEX = /^(?:[^:]+:){3}([^:]+).*/
29
+
30
+ def self.without_net_http
31
+ return yield unless defined?(NetHTTPSpy)
32
+
33
+ # rubocop:disable Style/ExplicitBlockArgument
34
+ Atatus::Spies::NetHTTPSpy.disable_in do
35
+ yield
36
+ end
37
+ # rubocop:enable Style/ExplicitBlockArgument
38
+ end
39
+
40
+ def self.get_topic(params)
41
+ return '[PHONENUMBER]' if params[:phone_number]
42
+
43
+ last_after_slash_or_colon(
44
+ params[:topic_arn] || params[:target_arn]
45
+ )
46
+ end
47
+
48
+ def self.last_after_slash_or_colon(arn)
49
+ if index = arn.rindex(AP_REGEX)
50
+ return arn[index+1..-1]
51
+ end
52
+
53
+ if arn.include?('/')
54
+ arn.split('/')[-1]
55
+ else
56
+ arn.split(':')[-1]
57
+ end
58
+ end
59
+
60
+ def self.arn_region(arn)
61
+ if arn && (match = AP_REGION_REGEX.match(arn))
62
+ match[1]
63
+ end
64
+ end
65
+
66
+ def self.span_context(topic, region)
67
+ Atatus::Span::Context.new(
68
+ message: { queue_name: topic },
69
+ destination: {
70
+ service: { resource: "#{SUBTYPE}/#{topic}" },
71
+ cloud: { region: region }
72
+ }
73
+ )
74
+ end
75
+
76
+ # @api private
77
+ module Ext
78
+ def publish(params = {}, options = {})
79
+ unless (transaction = Atatus.current_transaction)
80
+ return super(params, options)
81
+ end
82
+
83
+ topic = Atatus::Spies::SNSSpy.get_topic(params)
84
+ span_name = topic ? "SNS PUBLISH to #{topic}" : 'SNS PUBLISH'
85
+ region = Atatus::Spies::SNSSpy.arn_region(
86
+ params[:topic_arn] || params[:target_arn]
87
+ )
88
+ context = Atatus::Spies::SNSSpy.span_context(
89
+ topic,
90
+ region || config.region
91
+ )
92
+
93
+ Atatus.with_span(
94
+ span_name,
95
+ TYPE,
96
+ subtype: SUBTYPE,
97
+ action: 'publish',
98
+ context: context
99
+ ) do |span|
100
+ trace_context = span&.trace_context || transaction.trace_context
101
+ trace_context.apply_headers do |key, value|
102
+ params[:message_attributes] ||= {}
103
+ params[:message_attributes][key] ||= {}
104
+ params[:message_attributes][key][:string_value] = value
105
+ params[:message_attributes][key][:data_type] = 'String'
106
+ end
107
+
108
+ Atatus::Spies::SNSSpy.without_net_http do
109
+ super(params, options)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def install
116
+ ::Aws::SNS::Client.prepend(Ext)
117
+ end
118
+ end
119
+
120
+ register(
121
+ 'Aws::SNS::Client',
122
+ 'aws-sdk-sns',
123
+ SNSSpy.new
124
+ )
125
+ end
126
+ end
@@ -0,0 +1,231 @@
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 Spies
23
+ # @api private
24
+ class SQSSpy
25
+ TYPE = 'messaging'
26
+ SUBTYPE = 'sqs'
27
+
28
+ REGION_REGEXP = %r{https://sqs\.([a-z0-9-]+)\.amazonaws}
29
+
30
+ def self.without_net_http
31
+ return yield unless defined?(NetHTTPSpy)
32
+
33
+ # rubocop:disable Style/ExplicitBlockArgument
34
+ Atatus::Spies::NetHTTPSpy.disable_in do
35
+ yield
36
+ end
37
+ # rubocop:enable Style/ExplicitBlockArgument
38
+ end
39
+
40
+ def self.queue_name(params)
41
+ if params[:queue_url]
42
+ params[:queue_url].split('/')[-1]
43
+ end
44
+ end
45
+
46
+ def self.region_from_url(url)
47
+ if match = REGION_REGEXP.match(url)
48
+ match[1]
49
+ end
50
+ end
51
+
52
+ def self.span_context(queue_name, region)
53
+ Atatus::Span::Context.new(
54
+ message: { queue_name: queue_name },
55
+ destination: {
56
+ service: { resource: "#{SUBTYPE}/#{queue_name}" },
57
+ cloud: { region: region }
58
+ }
59
+ # span links added here?
60
+ )
61
+ end
62
+
63
+ # @api private
64
+ module Ext
65
+ def self.prepended(mod)
66
+ def send_message(params = {}, options = {})
67
+ unless (transaction = Atatus.current_transaction)
68
+ return super(params, options)
69
+ end
70
+
71
+ queue_name = Atatus::Spies::SQSSpy.queue_name(params)
72
+ span_name = queue_name ? "SQS SEND to #{queue_name}" : 'SQS SEND'
73
+ region = Atatus::Spies::SQSSpy.region_from_url(params[:queue_url])
74
+ context = Atatus::Spies::SQSSpy.span_context(
75
+ queue_name,
76
+ region || config.region
77
+ )
78
+
79
+ Atatus.with_span(
80
+ span_name,
81
+ TYPE,
82
+ subtype: SUBTYPE,
83
+ action: 'send',
84
+ context: context
85
+ ) do |span|
86
+ trace_context = span&.trace_context || transaction.trace_context
87
+ trace_context.apply_headers do |key, value|
88
+ params[:message_attributes] ||= {}
89
+ params[:message_attributes][key] ||= {}
90
+ params[:message_attributes][key][:string_value] = value
91
+ params[:message_attributes][key][:data_type] = 'String'
92
+ end
93
+
94
+ Atatus::Spies::SQSSpy.without_net_http do
95
+ super(params, options)
96
+ end
97
+ end
98
+ end
99
+
100
+ def send_message_batch(params = {}, options = {})
101
+ unless (transaction = Atatus.current_transaction)
102
+ return super(params, options)
103
+ end
104
+
105
+ queue_name = Atatus::Spies::SQSSpy.queue_name(params)
106
+ span_name =
107
+ queue_name ? "SQS SEND_BATCH to #{queue_name}" : 'SQS SEND_BATCH'
108
+ region = Atatus::Spies::SQSSpy.region_from_url(params[:queue_url])
109
+ context = Atatus::Spies::SQSSpy.span_context(
110
+ queue_name,
111
+ region || config.region
112
+ )
113
+
114
+ Atatus.with_span(
115
+ span_name,
116
+ TYPE,
117
+ subtype: SUBTYPE,
118
+ action: 'send_batch',
119
+ context: context
120
+ ) do |span|
121
+ trace_context = span&.trace_context || transaction.trace_context
122
+
123
+ trace_context.apply_headers do |key, value|
124
+ params[:entries].each do |message|
125
+ message[:message_attributes] ||= {}
126
+ message[:message_attributes][key] ||= {}
127
+ message[:message_attributes][key][:string_value] = value
128
+ message[:message_attributes][key][:data_type] = 'String'
129
+ end
130
+ end
131
+
132
+ Atatus::Spies::SQSSpy.without_net_http do
133
+ super(params, options)
134
+ end
135
+ end
136
+ end
137
+
138
+ def receive_message(params = {}, options = {})
139
+ unless Atatus.current_transaction
140
+ return super(params, options)
141
+ end
142
+
143
+ queue_name = Atatus::Spies::SQSSpy.queue_name(params)
144
+ span_name =
145
+ queue_name ? "SQS RECEIVE from #{queue_name}" : 'SQS RECEIVE'
146
+ region = Atatus::Spies::SQSSpy.region_from_url(params[:queue_url])
147
+ context = Atatus::Spies::SQSSpy.span_context(
148
+ queue_name,
149
+ region || config.region
150
+ )
151
+
152
+ Atatus.with_span(
153
+ span_name,
154
+ TYPE,
155
+ subtype: SUBTYPE,
156
+ action: 'receive',
157
+ context: context
158
+ ) do
159
+ Atatus::Spies::SQSSpy.without_net_http do
160
+ super(params, options)
161
+ end
162
+ end
163
+ end
164
+
165
+ def delete_message(params = {}, options = {})
166
+ unless Atatus.current_transaction
167
+ return super(params, options)
168
+ end
169
+
170
+ queue_name = Atatus::Spies::SQSSpy.queue_name(params)
171
+ span_name = queue_name ? "SQS DELETE from #{queue_name}" : 'SQS DELETE'
172
+ region = Atatus::Spies::SQSSpy.region_from_url(params[:queue_url])
173
+ context = Atatus::Spies::SQSSpy.span_context(
174
+ queue_name,
175
+ region || config.region
176
+ )
177
+
178
+ Atatus.with_span(
179
+ span_name,
180
+ TYPE,
181
+ subtype: SUBTYPE,
182
+ action: 'delete',
183
+ context: context
184
+ ) do
185
+ Atatus::Spies::SQSSpy.without_net_http do
186
+ super(params, options)
187
+ end
188
+ end
189
+ end
190
+
191
+ def delete_message_batch(params = {}, options = {})
192
+ unless Atatus.current_transaction
193
+ return super(params, options)
194
+ end
195
+
196
+ queue_name = Atatus::Spies::SQSSpy.queue_name(params)
197
+ span_name =
198
+ queue_name ? "SQS DELETE_BATCH from #{queue_name}" : 'SQS DELETE_BATCH'
199
+ region = Atatus::Spies::SQSSpy.region_from_url(params[:queue_url])
200
+ context = Atatus::Spies::SQSSpy.span_context(
201
+ queue_name,
202
+ region || config.region
203
+ )
204
+
205
+ Atatus.with_span(
206
+ span_name,
207
+ TYPE,
208
+ subtype: SUBTYPE,
209
+ action: 'delete_batch',
210
+ context: context
211
+ ) do
212
+ Atatus::Spies::SQSSpy.without_net_http do
213
+ super(params, options)
214
+ end
215
+ end
216
+ end
217
+ end
218
+ end
219
+
220
+ def install
221
+ ::Aws::SQS::Client.prepend(Ext)
222
+ end
223
+ end
224
+
225
+ register(
226
+ 'Aws::SQS::Client',
227
+ 'aws-sdk-sqs',
228
+ SQSSpy.new
229
+ )
230
+ end
231
+ end
@@ -25,30 +25,28 @@ module Atatus
25
25
  TYPE = 'sucker_punch'
26
26
 
27
27
  def install
28
- if defined?(::SuckerPunch) && defined?(::SuckerPunch::Job) && defined?(::SuckerPunch::Job::ClassMethods)
28
+ ::SuckerPunch::Job::ClassMethods.class_eval do
29
+ alias :__run_perform_without_atatus :__run_perform
29
30
 
30
- ::SuckerPunch::Job::ClassMethods.class_eval do
31
- alias :__run_perform_without_atatus :__run_perform
32
-
33
- def __run_perform(*args)
34
- # This method is reached via JobClass#async_perform
35
- # or JobClass#perform_in.
36
- name = to_s
37
- transaction = Atatus.start_transaction(name, TYPE)
38
- __run_perform_without_atatus(*args)
39
- transaction.done 'success'
40
- rescue ::Exception => e
41
- # Note that SuckerPunch by default doesn't raise the errors from
42
- # the user-defined JobClass#perform method as it uses an error
43
- # handler, accessed via `SuckerPunch.exception_handler`.
44
- Atatus.report(e, handled: false)
45
- transaction.done 'error'
46
- raise
47
- ensure
48
- Atatus.end_transaction
49
- end
31
+ def __run_perform(*args)
32
+ # This method is reached via JobClass#async_perform
33
+ # or JobClass#perform_in.
34
+ name = to_s
35
+ transaction = Atatus.start_transaction(name, TYPE)
36
+ __run_perform_without_atatus(*args)
37
+ transaction.done 'success'
38
+ transaction&.outcome = Transaction::Outcome::SUCCESS
39
+ rescue ::Exception => e
40
+ # Note that SuckerPunch by default doesn't raise the errors from
41
+ # the user-defined JobClass#perform method as it uses an error
42
+ # handler, accessed via `SuckerPunch.exception_handler`.
43
+ Atatus.report(e, handled: false)
44
+ transaction.done 'error'
45
+ transaction&.outcome = Transaction::Outcome::FAILURE
46
+ raise
47
+ ensure
48
+ Atatus.end_transaction
50
49
  end
51
-
52
50
  end
53
51
  end
54
52
  end
@@ -24,23 +24,20 @@ module Atatus
24
24
  class TiltSpy
25
25
  TYPE = 'template.tilt'
26
26
 
27
- def install
28
- if defined?(::Tilt) && defined?(::Tilt::Template)
29
-
30
- ::Tilt::Template.class_eval do
31
- alias render_without_apm render
27
+ # @api private
28
+ module Ext
29
+ def render(*args, &block)
30
+ name = options[:__atatus_template_name] || 'Unknown template'
32
31
 
33
- def render(*args, &block)
34
- name = options[:__atatus_template_name] || 'Unknown template'
35
-
36
- Atatus.with_span name, TYPE do
37
- render_without_apm(*args, &block)
38
- end
39
- end
32
+ Atatus.with_span name, TYPE do
33
+ super(*args, &block)
40
34
  end
41
-
42
35
  end
43
36
  end
37
+
38
+ def install
39
+ ::Tilt::Template.prepend(Ext)
40
+ end
44
41
  end
45
42
 
46
43
  register 'Tilt::Template', 'tilt/template', TiltSpy.new
data/lib/atatus/spies.rb CHANGED
@@ -56,6 +56,26 @@ module Atatus
56
56
  end
57
57
  end
58
58
 
59
+ def self.without_faraday
60
+ return yield unless defined?(FaradaySpy)
61
+
62
+ # rubocop:disable Style/ExplicitBlockArgument
63
+ Atatus::Spies::FaradaySpy.disable_in do
64
+ yield
65
+ end
66
+ # rubocop:enable Style/ExplicitBlockArgument
67
+ end
68
+
69
+ def self.without_net_http
70
+ return yield unless defined?(NetHTTPSpy)
71
+
72
+ # rubocop:disable Style/ExplicitBlockArgument
73
+ Atatus::Spies::NetHTTPSpy.disable_in do
74
+ yield
75
+ end
76
+ # rubocop:enable Style/ExplicitBlockArgument
77
+ end
78
+
59
79
  def self.register_require_hook(registration)
60
80
  registration.require_paths.each do |path|
61
81
  require_hooks[path] = registration
@@ -36,8 +36,8 @@ module Atatus
36
36
  end
37
37
 
38
38
  def initialize(sql)
39
- @sql = sql
40
- @tokenizer = Tokenizer.new(sql)
39
+ @sql = sql.encode('utf-8', invalid: :replace, undef: :replace)
40
+ @tokenizer = Tokenizer.new(@sql)
41
41
  end
42
42
 
43
43
  def parse
@@ -158,9 +158,11 @@ module Atatus
158
158
  def scan_dotted_identifier
159
159
  table = @tokenizer.text
160
160
 
161
+ # rubocop:disable Style/WhileUntilModifier
161
162
  while scan_token(PERIOD) && scan_token(IDENT)
162
163
  table += ".#{@tokenizer.text}"
163
164
  end
165
+ # rubocop:enable Style/WhileUntilModifier
164
166
 
165
167
  table
166
168
  end