atatus 1.7.0 → 2.0.0

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 +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
@@ -25,15 +25,11 @@ module Atatus
25
25
  # @api private
26
26
  class JSONSpy
27
27
  def install
28
- if defined?(::JSON)
29
-
30
- ::JSON.class_eval do
31
- include SpanHelpers
32
- span_class_method :parse, 'JSON#parse', 'json.parse'
33
- span_class_method :parse!, 'JSON#parse!', 'json.parse'
34
- span_class_method :generate, 'JSON#generate', 'json.generate'
35
- end
36
-
28
+ ::JSON.class_eval do
29
+ include SpanHelpers
30
+ span_class_method :parse, 'JSON#parse', 'json.parse'
31
+ span_class_method :parse!, 'JSON#parse!', 'json.parse'
32
+ span_class_method :generate, 'JSON#generate', 'json.generate'
37
33
  end
38
34
  end
39
35
  end
@@ -23,14 +23,10 @@ module Atatus
23
23
  # @api private
24
24
  class MongoSpy
25
25
  def install
26
- if defined?(::Mongo) && defined?(::Mongo::Monitoring) && defined?(::Mongo::Monitoring::Global)
27
-
28
- ::Mongo::Monitoring::Global.subscribe(
29
- ::Mongo::Monitoring::COMMAND,
30
- Subscriber.new
31
- )
32
-
33
- end
26
+ ::Mongo::Monitoring::Global.subscribe(
27
+ ::Mongo::Monitoring::COMMAND,
28
+ Subscriber.new
29
+ )
34
30
  end
35
31
 
36
32
  # @api private
@@ -39,8 +35,10 @@ module Atatus
39
35
  SUBTYPE = 'mongodb'
40
36
  ACTION = 'query'
41
37
 
42
- def initialize
43
- @events = {}
38
+ EVENT_KEY = :__atatus_instrumenter_mongo_events_key
39
+
40
+ def events
41
+ Thread.current[EVENT_KEY] ||= []
44
42
  end
45
43
 
46
44
  def started(event)
@@ -48,11 +46,19 @@ module Atatus
48
46
  end
49
47
 
50
48
  def failed(event)
51
- pop_event(event)
49
+ if (span = pop_event(event))
50
+ span.outcome = Span::Outcome::FAILURE
51
+ end
52
+
53
+ span
52
54
  end
53
55
 
54
56
  def succeeded(event)
55
- pop_event(event)
57
+ if span = pop_event(event)
58
+ span.outcome = Span::Outcome::SUCCESS
59
+ end
60
+
61
+ span
56
62
  end
57
63
 
58
64
  private
@@ -66,7 +72,7 @@ module Atatus
66
72
  # and the collection name is at the key `collection`
67
73
  collection =
68
74
  if event.command[event.command_name] == 1 ||
69
- event.command[event.command_name].is_a?(BSON::Int64)
75
+ event.command[event.command_name].is_a?(BSON::Int64)
70
76
  event.command[:collection]
71
77
  else
72
78
  event.command[event.command_name]
@@ -85,14 +91,13 @@ module Atatus
85
91
  context: build_context(event)
86
92
  )
87
93
 
88
- @events[event.operation_id] = span
94
+ events << span
89
95
  end
90
96
 
91
97
  def pop_event(event)
92
- span = @events.delete(event.operation_id)
93
98
  return unless (curr = Atatus.current_span)
94
99
 
95
- curr == span && Atatus.end_span
100
+ curr == events[-1] && Atatus.end_span(events.pop)
96
101
  end
97
102
 
98
103
  def build_context(event)
@@ -104,9 +109,11 @@ module Atatus
104
109
  user: nil
105
110
  },
106
111
  destination: {
107
- name: SUBTYPE,
108
- resource: SUBTYPE,
109
- type: TYPE
112
+ service: {
113
+ name: SUBTYPE,
114
+ resource: SUBTYPE,
115
+ type: TYPE
116
+ }
110
117
  }
111
118
  )
112
119
  end
@@ -22,17 +22,17 @@ module Atatus
22
22
  module Spies
23
23
  # @api private
24
24
  class NetHTTPSpy
25
- KEY = :__atatus_net_http_disabled
26
- TYPE = 'ext'
27
- SUBTYPE = 'net_http'
25
+ DISABLE_KEY = :__atatus_net_http_disabled
26
+ TYPE = 'external'
27
+ SUBTYPE = 'http'
28
28
 
29
29
  class << self
30
30
  def disabled=(disabled)
31
- Thread.current[KEY] = disabled
31
+ Thread.current[DISABLE_KEY] = disabled
32
32
  end
33
33
 
34
34
  def disabled?
35
- Thread.current[KEY] ||= false
35
+ Thread.current[DISABLE_KEY] ||= false
36
36
  end
37
37
 
38
38
  def disable_in
@@ -46,66 +46,68 @@ module Atatus
46
46
  end
47
47
  end
48
48
 
49
- # rubocop:disable Metrics/CyclomaticComplexity
50
- def install
51
- if defined?(::Net) && defined?(::Net::HTTP)
49
+ # @api private
50
+ module Ext
51
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
52
+ def request(req, body = nil, &block)
53
+ unless (transaction = Atatus.current_transaction)
54
+ return super(req, body, &block)
55
+ end
52
56
 
53
- Net::HTTP.class_eval do
54
- alias request_without_apm request
57
+ if Atatus::Spies::NetHTTPSpy.disabled?
58
+ return super(req, body, &block)
59
+ end
55
60
 
56
- def request(req, body = nil, &block)
57
- unless (transaction = Atatus.current_transaction)
58
- return request_without_apm(req, body, &block)
59
- end
61
+ host = req['host']&.split(':')&.first || address || 'localhost'
62
+ method = req.method.to_s.upcase
60
63
 
61
- if Atatus::Spies::NetHTTPSpy.disabled?
62
- return request_without_apm(req, body, &block)
63
- end
64
+ uri_or_path = URI(req.path)
64
65
 
65
- host = req['host']&.split(':')&.first || address
66
- method = req.method.to_s.upcase
66
+ # Support the case where a whole url is passed as a path to a nil host
67
+ uri =
68
+ if uri_or_path.host
69
+ uri_or_path
70
+ else
67
71
  path, query = req.path.split('?')
68
-
69
72
  url = use_ssl? ? +'https://' : +'http://'
70
73
  url << host
71
74
  url << ":#{port}" if port
72
75
  url << path
73
76
  url << "?#{query}" if query
74
- uri = URI(url)
75
-
76
- destination =
77
- Atatus::Span::Context::Destination.from_uri(uri)
78
-
79
- context =
80
- Atatus::Span::Context.new(
81
- http: { url: uri, method: method },
82
- destination: destination
83
- )
84
-
85
- Atatus.with_span(
86
- "#{method} #{host}",
87
- TYPE,
88
- subtype: SUBTYPE,
89
- action: method,
90
- context: context
91
- ) do |span|
92
- trace_context = span&.trace_context || transaction.trace_context
93
- trace_context.apply_headers { |key, value| req[key] = value }
94
-
95
- result = request_without_apm(req, body, &block)
96
-
97
- if (http = span&.context&.http)
98
- http.status_code = result.code
99
- end
100
-
101
- result
102
- end
77
+ URI(url)
103
78
  end
104
- end
105
79
 
80
+ context =
81
+ Atatus::Span::Context.new(
82
+ http: { url: uri, method: method },
83
+ destination: Atatus::Span::Context::Destination.from_uri(uri, type: SUBTYPE)
84
+ )
85
+
86
+ Atatus.with_span(
87
+ "#{method} #{host}",
88
+ TYPE,
89
+ subtype: SUBTYPE,
90
+ context: context
91
+ ) do |span|
92
+ trace_context = span&.trace_context || transaction.trace_context
93
+ trace_context.apply_headers { |key, value| req[key] = value }
94
+
95
+ result = super(req, body, &block)
96
+
97
+ if (http = span&.context&.http)
98
+ http.status_code = result.code
99
+ end
100
+
101
+ span&.outcome = Span::Outcome.from_http_status(result.code)
102
+ result
103
+ end
106
104
  end
105
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
106
+ end
107
+
108
+ def install
109
+ Net::HTTP.prepend(Ext)
107
110
  end
108
- # rubocop:enable Metrics/CyclomaticComplexity
109
111
  end
110
112
 
111
113
  register 'Net::HTTP', 'net/http', NetHTTPSpy.new
@@ -0,0 +1,77 @@
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
+ begin
19
+ require 'active_support/notifications'
20
+ require 'active_support/subscriber'
21
+
22
+ # frozen_string_literal: true
23
+ module Atatus
24
+ # @api private
25
+ module Spies
26
+ # @api private
27
+ class RacecarSpy
28
+ TYPE = 'kafka'
29
+ SUBTYPE = 'racecar'
30
+
31
+ # @api private
32
+ class ConsumerSubscriber < ActiveSupport::Subscriber
33
+ def start_process_message(event)
34
+ start_process_transaction(event: event, kind: 'process_message')
35
+ end
36
+ def process_message(_event)
37
+ Atatus.end_transaction
38
+ end
39
+
40
+ def start_process_batch(event)
41
+ start_process_transaction(event: event, kind: 'process_batch')
42
+ end
43
+ def process_batch(_event)
44
+ Atatus.end_transaction
45
+ end
46
+
47
+ private # only public methods will be subscribed
48
+
49
+ def start_process_transaction(event:, kind:)
50
+ Atatus.start_transaction(kind, TYPE)
51
+ Atatus.current_transaction.context.set_service(framework_name: 'racecar', framework_version: Racecar::VERSION)
52
+ end
53
+ end
54
+
55
+ class ProducerSubscriber < ActiveSupport::Subscriber
56
+ def start_deliver_message(event)
57
+ Atatus.start_transaction('deliver_message',TYPE)
58
+ Atatus.current_transaction.context.set_service(framework_name: 'racecar', framework_version: Racecar::VERSION)
59
+ end
60
+
61
+ def deliver_message(_event)
62
+ Atatus.end_transaction
63
+ end
64
+ end
65
+
66
+ def install
67
+ ConsumerSubscriber.attach_to(:racecar)
68
+ ProducerSubscriber.attach_to(:racecar)
69
+ end
70
+ end
71
+ register 'Racecar', 'racecar', RacecarSpy.new
72
+ end
73
+ end
74
+
75
+ rescue LoadError
76
+ # no active support available
77
+ end
@@ -22,43 +22,43 @@ module Atatus
22
22
  module Spies
23
23
  # @api private
24
24
  class RakeSpy
25
- def install
26
- if defined?(::Rake) && defined?(::Rake::Task)
27
-
28
- ::Rake::Task.class_eval do
29
- alias execute_without_apm execute
30
-
31
- def execute(*args)
32
- agent = Atatus.start
25
+ # @api private
26
+ module Ext
27
+ def execute(*args)
28
+ agent = Atatus.start
33
29
 
34
- unless agent && agent.config.instrumented_rake_tasks.include?(name)
35
- return execute_without_apm(*args)
36
- end
37
-
38
- transaction =
39
- Atatus.start_transaction("Rake::Task[#{name}]", 'Rake')
30
+ unless agent && agent.config.instrumented_rake_tasks.include?(name)
31
+ return super(*args)
32
+ end
40
33
 
41
- begin
42
- result = execute_without_apm(*args)
34
+ transaction =
35
+ Atatus.start_transaction("Rake::Task[#{name}]", 'Rake')
43
36
 
44
- transaction.result = 'success' if transaction
45
- rescue StandardError => e
46
- transaction.result = 'error' if transaction
47
- Atatus.report(e)
37
+ begin
38
+ result = super(*args)
48
39
 
49
- raise
50
- ensure
51
- Atatus.end_transaction
52
- Atatus.stop
53
- end
40
+ transaction&.result = 'success'
41
+ transaction&.outcome = Transaction::Outcome::SUCCESS
42
+ rescue StandardError => e
43
+ transaction&.result = 'error'
44
+ transaction&.outcome = Transaction::Outcome::FAILURE
45
+ Atatus.report(e)
54
46
 
55
- result
56
- end
47
+ raise
48
+ ensure
49
+ Atatus.end_transaction
50
+ Atatus.stop
57
51
  end
58
52
 
53
+ result
59
54
  end
60
55
  end
56
+
57
+ def install
58
+ ::Rake::Task.prepend(Ext)
59
+ end
61
60
  end
61
+
62
62
  register 'Rake::Task', 'rake', RakeSpy.new
63
63
  end
64
64
  end
@@ -22,23 +22,22 @@ module Atatus
22
22
  module Spies
23
23
  # @api private
24
24
  class RedisSpy
25
- def install
26
- if defined?(::Redis) && defined?(::Redis::Client)
27
- ::Redis::Client.class_eval do
28
- alias call_without_apm call
29
-
30
- def call(command, &block)
31
- name = command[0].upcase
25
+ # @api private
26
+ module Ext
27
+ def call(command, &block)
28
+ name = command[0].to_s.upcase
32
29
 
33
- return call_without_apm(command, &block) if command[0] == :auth
30
+ return super(command, &block) if command[0] == :auth
34
31
 
35
- Atatus.with_span(name.to_s, 'db.redis') do
36
- call_without_apm(command, &block)
37
- end
38
- end
32
+ Atatus.with_span(name.to_s, 'db.redis') do
33
+ super(command, &block)
39
34
  end
40
35
  end
41
36
  end
37
+
38
+ def install
39
+ ::Redis::Client.prepend(Ext)
40
+ end
42
41
  end
43
42
 
44
43
  register 'Redis', 'redis', RedisSpy.new
@@ -24,31 +24,26 @@ module Atatus
24
24
  class ResqueSpy
25
25
  TYPE = 'Resque'
26
26
 
27
- def install
28
- install_perform_spy
27
+ # @api private
28
+ module Ext
29
+ def perform
30
+ name = @payload && @payload['class']&.to_s
31
+ transaction = Atatus.start_transaction(name, TYPE)
32
+ super
33
+ transaction&.done 'success'
34
+ transaction&.outcome = Transaction::Outcome::SUCCESS
35
+ rescue ::Exception => e
36
+ Atatus.report(e, handled: false)
37
+ transaction&.done 'error'
38
+ transaction&.outcome = Transaction::Outcome::FAILURE
39
+ raise
40
+ ensure
41
+ Atatus.end_transaction
42
+ end
29
43
  end
30
44
 
31
- def install_perform_spy
32
- if defined?(::Resque) && defined?(::Resque::Job)
33
-
34
- ::Resque::Job.class_eval do
35
- alias :perform_without_atatus :perform
36
-
37
- def perform
38
- name = @payload && @payload['class']&.to_s
39
- transaction = Atatus.start_transaction(name, TYPE)
40
- perform_without_atatus
41
- transaction.done 'success'
42
- rescue ::Exception => e
43
- Atatus.report(e, handled: false)
44
- transaction.done 'error' if transaction
45
- raise
46
- ensure
47
- Atatus.end_transaction
48
- end
49
- end
50
-
51
- end
45
+ def install
46
+ ::Resque::Job.prepend(Ext)
52
47
  end
53
48
  end
54
49
 
@@ -0,0 +1,132 @@
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 S3Spy
25
+ TYPE = 'storage'
26
+ SUBTYPE = 's3'
27
+ AP_REGION_REGEX = /^(?:[^:]+:){3}([^:]+).*/
28
+ AP_REGEX = /:accesspoint.*/
29
+ MUTEX = Mutex.new
30
+
31
+ @@formatted_op_names = {}
32
+
33
+ def self.without_net_http
34
+ return yield unless defined?(NetHTTPSpy)
35
+
36
+ # rubocop:disable Style/ExplicitBlockArgument
37
+ Atatus::Spies::NetHTTPSpy.disable_in do
38
+ yield
39
+ end
40
+ # rubocop:enable Style/ExplicitBlockArgument
41
+ end
42
+
43
+ def self.bucket_name(params)
44
+ return unless (bucket = params[:bucket]&.to_s)
45
+ return bucket unless (index = bucket.rindex(AP_REGEX))
46
+
47
+ bucket[index+1..-1]
48
+ end
49
+
50
+ def self.accesspoint_region(params)
51
+ if params[:bucket] && (match = AP_REGION_REGEX.match(params[:bucket]))
52
+ match[1]
53
+ end
54
+ end
55
+
56
+ def self.span_name(operation_name, bucket_name)
57
+ bucket_name ? "S3 #{formatted_op_name(operation_name)} #{bucket_name}" :
58
+ "S3 #{formatted_op_name(operation_name)}"
59
+ end
60
+
61
+ def self.formatted_op_name(operation_name)
62
+ if @@formatted_op_names[operation_name]
63
+ return @@formatted_op_names[operation_name]
64
+ end
65
+
66
+ MUTEX.synchronize do
67
+ if @@formatted_op_names[operation_name]
68
+ return @@formatted_op_names[operation_name]
69
+ end
70
+
71
+ @@formatted_op_names[operation_name] =
72
+ operation_name.to_s.split('_').collect(&:capitalize).join
73
+ end
74
+
75
+ @@formatted_op_names[operation_name]
76
+ end
77
+
78
+
79
+ # @api private
80
+ module Ext
81
+ def self.prepended(mod)
82
+ # Alias all available operations
83
+ mod.api.operation_names.each do |operation_name|
84
+ define_method(operation_name) do |params = {}, options = {}, &block|
85
+ bucket_name = Atatus::Spies::S3Spy.bucket_name(params)
86
+ region = Atatus::Spies::S3Spy.accesspoint_region(params) || config.region
87
+
88
+ resource = "#{SUBTYPE}/#{bucket_name || 'unknown-bucket'}"
89
+ context = Atatus::Span::Context.new(
90
+ db: {
91
+ instance: config.region,
92
+ type: SUBTYPE
93
+ },
94
+ destination: {
95
+ address: config.endpoint.host,
96
+ port: config.endpoint.port,
97
+ service: {
98
+ name: SUBTYPE,
99
+ type: TYPE,
100
+ resource: resource },
101
+ cloud: { region: region }
102
+ }
103
+ )
104
+
105
+ Atatus.with_span(
106
+ Atatus::Spies::S3Spy.span_name(operation_name, bucket_name),
107
+ TYPE,
108
+ subtype: SUBTYPE,
109
+ action: Atatus::Spies::S3Spy.formatted_op_name(operation_name),
110
+ context: context
111
+ ) do
112
+ Atatus::Spies::S3Spy.without_net_http do
113
+ super(params, options, &block)
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ def install
122
+ ::Aws::S3::Client.prepend(Ext)
123
+ end
124
+ end
125
+
126
+ register(
127
+ 'Aws::S3::Client',
128
+ 'aws-sdk-s3',
129
+ S3Spy.new
130
+ )
131
+ end
132
+ end
@@ -17,7 +17,7 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
- require 'atatus/sql'
20
+ require 'atatus/sql/signature'
21
21
 
22
22
  module Atatus
23
23
  # @api private
@@ -44,8 +44,17 @@ module Atatus
44
44
  name =
45
45
  Atatus::Spies::SequelSpy.summarizer.summarize sql
46
46
 
47
+ db_name = ''
48
+ # postgresql shows current database
49
+ db_name = connection&.db.to_s if connection.respond_to?(:db)
50
+ # sqlite may expose a filename
51
+ db_name = connection&.filename.to_s if db_name == '' && connection.respond_to?(:filename)
52
+ # fall back to adapter class name
53
+ db_name = connection.class.to_s if db_name == ''
54
+
47
55
  context = Atatus::Span::Context.new(
48
56
  db: { statement: sql, type: 'sql', user: opts[:user] },
57
+ service: {target: {type: subtype, name: db_name }},
49
58
  destination: { service: { resource: subtype } }
50
59
  )
51
60
 
@@ -84,4 +93,4 @@ module Atatus
84
93
 
85
94
  register 'Sequel', 'sequel', SequelSpy.new
86
95
  end
87
- end
96
+ end
@@ -37,9 +37,11 @@ module Atatus
37
37
  yield
38
38
 
39
39
  transaction&.done :success
40
+ transaction&.outcome = Transaction::Outcome::SUCCESS
40
41
  rescue ::Exception => e
41
42
  Atatus.report(e, handled: false)
42
43
  transaction&.done :error
44
+ transaction&.outcome = Transaction::Outcome::FAILURE
43
45
  raise
44
46
  ensure
45
47
  Atatus.end_transaction
@@ -54,12 +56,8 @@ module Atatus
54
56
  end
55
57
 
56
58
  def install
57
- if defined?(::Shoryuken)
58
-
59
- ::Shoryuken.server_middleware do |chain|
60
- chain.add Middleware
61
- end
62
-
59
+ ::Shoryuken.server_middleware do |chain|
60
+ chain.add Middleware
63
61
  end
64
62
  end
65
63
  end