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
@@ -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