atatus 1.6.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/Gemfile +49 -13
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +3 -3
  6. data/lib/atatus/agent.rb +18 -7
  7. data/lib/atatus/central_config.rb +19 -8
  8. data/lib/atatus/collector/base.rb +113 -1
  9. data/lib/atatus/collector/builder.rb +8 -0
  10. data/lib/atatus/collector/layer.rb +1 -1
  11. data/lib/atatus/collector/transport.rb +23 -2
  12. data/lib/atatus/{sql_summarizer.rb → config/log_level_map.rb} +22 -28
  13. data/lib/atatus/config/options.rb +2 -1
  14. data/lib/atatus/config/regexp_list.rb +1 -1
  15. data/lib/atatus/config/round_float.rb +31 -0
  16. data/lib/atatus/config/server_info.rb +50 -0
  17. data/lib/atatus/config/wildcard_pattern_list.rb +3 -1
  18. data/lib/atatus/config.rb +94 -70
  19. data/lib/atatus/context/company.rb +38 -0
  20. data/lib/atatus/context/request/socket.rb +1 -2
  21. data/lib/atatus/context/response.rb +1 -3
  22. data/lib/atatus/context.rb +4 -8
  23. data/lib/atatus/context_builder.rb +3 -3
  24. data/lib/atatus/error.rb +2 -1
  25. data/lib/atatus/error_builder.rb +1 -1
  26. data/lib/atatus/fields.rb +98 -0
  27. data/lib/atatus/graphql.rb +2 -0
  28. data/lib/atatus/grpc.rb +5 -7
  29. data/lib/atatus/instrumenter.rb +38 -24
  30. data/lib/atatus/metadata/cloud_info.rb +156 -0
  31. data/lib/atatus/metadata/service_info.rb +3 -3
  32. data/lib/atatus/metadata/system_info/container_info.rb +20 -8
  33. data/lib/atatus/metadata/system_info.rb +20 -5
  34. data/lib/atatus/metadata.rb +3 -1
  35. data/lib/atatus/metrics/cpu_mem_set.rb +10 -38
  36. data/lib/atatus/metrics/jvm_set.rb +88 -0
  37. data/lib/atatus/metrics/metric.rb +2 -0
  38. data/lib/atatus/metrics.rb +32 -16
  39. data/lib/atatus/middleware.rb +8 -3
  40. data/lib/atatus/naively_hashable.rb +1 -0
  41. data/lib/atatus/normalizers/rails/active_record.rb +25 -7
  42. data/lib/atatus/normalizers.rb +2 -2
  43. data/lib/atatus/opentracing.rb +5 -3
  44. data/lib/atatus/rails.rb +1 -1
  45. data/lib/atatus/span/context/db.rb +1 -1
  46. data/lib/atatus/span/context/destination.rb +58 -32
  47. data/lib/atatus/span/context/http.rb +2 -0
  48. data/lib/atatus/span/context/links.rb +32 -0
  49. data/lib/atatus/{sql.rb → span/context/message.rb} +16 -12
  50. data/lib/atatus/span/context/service.rb +55 -0
  51. data/lib/atatus/span/context.rb +28 -3
  52. data/lib/atatus/span.rb +35 -5
  53. data/lib/atatus/span_helpers.rb +12 -23
  54. data/lib/atatus/spies/action_dispatch.rb +10 -13
  55. data/lib/atatus/spies/azure_storage_table.rb +148 -0
  56. data/lib/atatus/spies/delayed_job.rb +19 -13
  57. data/lib/atatus/spies/dynamo_db.rb +56 -15
  58. data/lib/atatus/spies/elasticsearch.rb +54 -39
  59. data/lib/atatus/spies/faraday.rb +92 -58
  60. data/lib/atatus/spies/http.rb +33 -37
  61. data/lib/atatus/spies/json.rb +5 -9
  62. data/lib/atatus/spies/mongo.rb +26 -19
  63. data/lib/atatus/spies/net_http.rb +53 -51
  64. data/lib/atatus/spies/racecar.rb +77 -0
  65. data/lib/atatus/spies/rake.rb +27 -27
  66. data/lib/atatus/spies/redis.rb +11 -12
  67. data/lib/atatus/spies/resque.rb +18 -23
  68. data/lib/atatus/spies/s3.rb +132 -0
  69. data/lib/atatus/spies/sequel.rb +50 -40
  70. data/lib/atatus/spies/shoryuken.rb +4 -6
  71. data/lib/atatus/spies/sidekiq.rb +23 -31
  72. data/lib/atatus/spies/sinatra.rb +20 -28
  73. data/lib/atatus/spies/sneakers.rb +2 -0
  74. data/lib/atatus/spies/sns.rb +126 -0
  75. data/lib/atatus/spies/sqs.rb +231 -0
  76. data/lib/atatus/spies/sucker_punch.rb +20 -22
  77. data/lib/atatus/spies/tilt.rb +10 -13
  78. data/lib/atatus/spies.rb +20 -0
  79. data/lib/atatus/sql/signature.rb +4 -2
  80. data/lib/atatus/sql/tokenizer.rb +23 -7
  81. data/lib/atatus/stacktrace/frame.rb +1 -0
  82. data/lib/atatus/stacktrace_builder.rb +12 -16
  83. data/lib/atatus/subscriber.rb +1 -0
  84. data/lib/atatus/trace_context/traceparent.rb +5 -8
  85. data/lib/atatus/trace_context/tracestate.rb +16 -14
  86. data/lib/atatus/trace_context.rb +6 -16
  87. data/lib/atatus/transaction.rb +25 -4
  88. data/lib/atatus/transport/base.rb +1 -3
  89. data/lib/atatus/transport/connection/http.rb +11 -3
  90. data/lib/atatus/transport/connection/proxy_pipe.rb +1 -2
  91. data/lib/atatus/transport/connection.rb +3 -2
  92. data/lib/atatus/transport/filters/hash_sanitizer.rb +16 -34
  93. data/lib/atatus/transport/filters/secrets_filter.rb +35 -12
  94. data/lib/atatus/transport/serializers/context_serializer.rb +1 -2
  95. data/lib/atatus/transport/serializers/metadata_serializer.rb +54 -8
  96. data/lib/atatus/transport/serializers/metricset_serializer.rb +2 -2
  97. data/lib/atatus/transport/serializers/span_serializer.rb +55 -9
  98. data/lib/atatus/transport/serializers/transaction_serializer.rb +1 -0
  99. data/lib/atatus/transport/serializers.rb +9 -6
  100. data/lib/atatus/transport/user_agent.rb +16 -9
  101. data/lib/atatus/transport/worker.rb +2 -1
  102. data/lib/atatus/util/deep_dup.rb +65 -0
  103. data/lib/atatus/util/precision_validator.rb +46 -0
  104. data/lib/atatus/util.rb +2 -0
  105. data/lib/atatus/version.rb +1 -1
  106. data/lib/atatus.rb +48 -5
  107. metadata +41 -11
@@ -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
@@ -28,56 +28,66 @@ module Atatus
28
28
  ACTION = 'query'
29
29
 
30
30
  def self.summarizer
31
- @summarizer ||= Sql.summarizer
31
+ @summarizer ||= Sql::Signature::Summarizer.new
32
32
  end
33
33
 
34
- def install
35
- require 'sequel/database/logging'
36
-
37
- if defined?(::Sequel) && defined?(::Sequel::Database)
38
-
39
- ::Sequel::Database.class_eval do
40
- alias log_connection_yield_without_apm log_connection_yield
34
+ # @api private
35
+ module Ext
36
+ # rubocop:disable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
37
+ def log_connection_yield(sql, connection, args = nil, &block)
38
+ unless Atatus.current_transaction
39
+ return super(sql, connection, args, &block)
40
+ end
41
41
 
42
- def log_connection_yield(sql, connection, args = nil, &block)
43
- unless Atatus.current_transaction
44
- return log_connection_yield_without_apm(
45
- sql, connection, args, &block
46
- )
47
- end
42
+ subtype = database_type.to_s
48
43
 
49
- subtype = database_type.to_s
44
+ name =
45
+ Atatus::Spies::SequelSpy.summarizer.summarize sql
50
46
 
51
- name =
52
- Atatus::Spies::SequelSpy.summarizer.summarize sql
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 == ''
53
54
 
54
- context = Atatus::Span::Context.new(
55
- db: { statement: sql, type: 'sql', user: opts[:user] },
56
- destination: { name: subtype, resource: subtype, type: TYPE }
57
- )
55
+ context = Atatus::Span::Context.new(
56
+ db: { statement: sql, type: 'sql', user: opts[:user] },
57
+ service: {target: {type: subtype, name: db_name }},
58
+ destination: { service: { resource: subtype } }
59
+ )
58
60
 
59
- span = Atatus.start_span(
60
- name,
61
- TYPE,
62
- subtype: subtype,
63
- action: ACTION,
64
- context: context
65
- )
66
- yield.tap do |result|
67
- if name =~ /^(UPDATE|DELETE)/
68
- if connection.respond_to?(:changes)
69
- span.context.db.rows_affected = connection.changes
70
- elsif result.is_a?(Integer)
71
- span.context.db.rows_affected = result
72
- end
73
- end
61
+ span = Atatus.start_span(
62
+ name,
63
+ TYPE,
64
+ subtype: subtype,
65
+ action: ACTION,
66
+ context: context
67
+ )
68
+ super(sql, connection, args, &block).tap do |result|
69
+ if /^(UPDATE|DELETE)/.match?(name)
70
+ if connection.respond_to?(:changes)
71
+ span.context.db.rows_affected = connection.changes
72
+ elsif result.is_a?(Integer)
73
+ span.context.db.rows_affected = result
74
74
  end
75
- ensure
76
- Atatus.end_span
77
75
  end
78
76
  end
79
-
77
+ rescue
78
+ span&.outcome = Span::Outcome::FAILURE
79
+ raise
80
+ ensure
81
+ span&.outcome ||= Span::Outcome::SUCCESS
82
+ Atatus.end_span
80
83
  end
84
+ # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
85
+ end
86
+
87
+ def install
88
+ require 'sequel/database/logging'
89
+
90
+ ::Sequel::Database.prepend(Ext)
81
91
  end
82
92
  end
83
93
 
@@ -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
@@ -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