atatus 1.7.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -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 +92 -71
  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