atatus 1.3.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (148) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/Gemfile +72 -22
  4. data/LICENSE +1 -1
  5. data/atatus.gemspec +2 -2
  6. data/lib/atatus/agent.rb +78 -29
  7. data/lib/atatus/central_config/cache_control.rb +18 -1
  8. data/lib/atatus/central_config.rb +72 -27
  9. data/lib/atatus/child_durations.rb +64 -0
  10. data/lib/atatus/collector/base.rb +102 -43
  11. data/lib/atatus/collector/builder.rb +134 -4
  12. data/lib/atatus/collector/hist.rb +54 -0
  13. data/lib/atatus/collector/layer.rb +1 -0
  14. data/lib/atatus/collector/transport.rb +41 -11
  15. data/lib/atatus/config/bytes.rb +17 -0
  16. data/lib/atatus/config/duration.rb +17 -0
  17. data/lib/atatus/config/options.rb +29 -9
  18. data/lib/atatus/config/regexp_list.rb +17 -0
  19. data/lib/atatus/config/wildcard_pattern_list.rb +64 -0
  20. data/lib/atatus/config.rb +129 -28
  21. data/lib/atatus/context/request/socket.rb +18 -1
  22. data/lib/atatus/context/request/url.rb +17 -0
  23. data/lib/atatus/context/request.rb +17 -0
  24. data/lib/atatus/context/response.rb +27 -2
  25. data/lib/atatus/context/user.rb +17 -0
  26. data/lib/atatus/context.rb +32 -1
  27. data/lib/atatus/context_builder.rb +19 -4
  28. data/lib/atatus/deprecations.rb +17 -0
  29. data/lib/atatus/error/exception.rb +24 -0
  30. data/lib/atatus/error/log.rb +17 -0
  31. data/lib/atatus/error.rb +27 -0
  32. data/lib/atatus/error_builder.rb +21 -2
  33. data/lib/atatus/grape.rb +62 -0
  34. data/lib/atatus/graphql.rb +91 -0
  35. data/lib/atatus/grpc.rb +99 -0
  36. data/lib/atatus/instrumenter.rb +135 -30
  37. data/lib/atatus/internal_error.rb +17 -0
  38. data/lib/atatus/logging.rb +17 -2
  39. data/lib/atatus/metadata/process_info.rb +17 -0
  40. data/lib/atatus/metadata/service_info.rb +21 -6
  41. data/lib/atatus/metadata/system_info/container_info.rb +49 -10
  42. data/lib/atatus/metadata/system_info/hw_info.rb +1 -1
  43. data/lib/atatus/metadata/system_info.rb +22 -3
  44. data/lib/atatus/metadata.rb +17 -0
  45. data/lib/atatus/metrics/breakdown_set.rb +31 -0
  46. data/lib/atatus/metrics/{cpu_mem.rb → cpu_mem_set.rb} +110 -63
  47. data/lib/atatus/metrics/metric.rb +140 -0
  48. data/lib/atatus/metrics/set.rb +123 -0
  49. data/lib/atatus/metrics/span_scoped_set.rb +56 -0
  50. data/lib/atatus/metrics/transaction_set.rb +26 -0
  51. data/lib/atatus/metrics/vm_set.rb +58 -0
  52. data/lib/atatus/metrics.rb +69 -27
  53. data/lib/atatus/metricset.rb +48 -4
  54. data/lib/atatus/middleware.rb +28 -8
  55. data/lib/atatus/naively_hashable.rb +17 -0
  56. data/lib/atatus/normalizers/grape/endpoint_run.rb +65 -0
  57. data/lib/atatus/normalizers/grape.rb +22 -0
  58. data/lib/atatus/normalizers/rails/action_controller.rb +44 -0
  59. data/lib/atatus/normalizers/rails/action_mailer.rb +43 -0
  60. data/lib/atatus/normalizers/{action_view.rb → rails/action_view.rb} +17 -0
  61. data/lib/atatus/normalizers/rails/active_record.rb +80 -0
  62. data/lib/atatus/normalizers/rails.rb +27 -0
  63. data/lib/atatus/normalizers.rb +23 -9
  64. data/lib/atatus/opentracing.rb +75 -42
  65. data/lib/atatus/rails.rb +29 -13
  66. data/lib/atatus/railtie.rb +19 -6
  67. data/lib/atatus/resque.rb +29 -0
  68. data/lib/atatus/sinatra.rb +53 -0
  69. data/lib/atatus/span/context/db.rb +43 -0
  70. data/lib/atatus/span/context/destination.rb +77 -0
  71. data/lib/atatus/span/context/http.rb +43 -0
  72. data/lib/atatus/span/context.rb +43 -28
  73. data/lib/atatus/span.rb +44 -15
  74. data/lib/atatus/span_helpers.rb +18 -1
  75. data/lib/atatus/spies/action_dispatch.rb +27 -6
  76. data/lib/atatus/spies/delayed_job.rb +26 -5
  77. data/lib/atatus/spies/dynamo_db.rb +62 -0
  78. data/lib/atatus/spies/elasticsearch.rb +53 -7
  79. data/lib/atatus/spies/faraday.rb +54 -20
  80. data/lib/atatus/spies/http.rb +36 -6
  81. data/lib/atatus/spies/json.rb +18 -0
  82. data/lib/atatus/spies/mongo.rb +41 -10
  83. data/lib/atatus/spies/net_http.rb +52 -11
  84. data/lib/atatus/spies/rake.rb +42 -23
  85. data/lib/atatus/spies/redis.rb +17 -0
  86. data/lib/atatus/spies/resque.rb +57 -0
  87. data/lib/atatus/spies/sequel.rb +54 -17
  88. data/lib/atatus/spies/shoryuken.rb +69 -0
  89. data/lib/atatus/spies/sidekiq.rb +46 -25
  90. data/lib/atatus/spies/sinatra.rb +20 -4
  91. data/lib/atatus/spies/sneakers.rb +74 -0
  92. data/lib/atatus/spies/sucker_punch.rb +58 -0
  93. data/lib/atatus/spies/tilt.rb +20 -1
  94. data/lib/atatus/spies.rb +33 -15
  95. data/lib/atatus/sql/signature.rb +169 -0
  96. data/lib/atatus/sql/tokenizer.rb +264 -0
  97. data/lib/atatus/sql/tokens.rb +63 -0
  98. data/lib/atatus/sql.rb +36 -0
  99. data/lib/atatus/sql_summarizer.rb +24 -6
  100. data/lib/atatus/stacktrace/frame.rb +17 -3
  101. data/lib/atatus/stacktrace.rb +17 -0
  102. data/lib/atatus/stacktrace_builder.rb +23 -3
  103. data/lib/atatus/subscriber.rb +23 -4
  104. data/lib/atatus/trace_context/traceparent.rb +111 -0
  105. data/lib/atatus/trace_context/tracestate.rb +148 -0
  106. data/lib/atatus/trace_context.rb +84 -51
  107. data/lib/atatus/transaction.rb +74 -18
  108. data/lib/atatus/transport/base.rb +44 -27
  109. data/lib/atatus/transport/connection/http.rb +58 -35
  110. data/lib/atatus/transport/connection/proxy_pipe.rb +24 -5
  111. data/lib/atatus/transport/connection.rb +28 -72
  112. data/lib/atatus/transport/filters/hash_sanitizer.rb +77 -0
  113. data/lib/atatus/transport/filters/secrets_filter.rb +30 -55
  114. data/lib/atatus/transport/filters.rb +18 -1
  115. data/lib/atatus/transport/headers.rb +83 -0
  116. data/lib/atatus/transport/serializers/context_serializer.rb +30 -3
  117. data/lib/atatus/transport/serializers/error_serializer.rb +17 -2
  118. data/lib/atatus/transport/serializers/metadata_serializer.rb +44 -22
  119. data/lib/atatus/transport/serializers/metricset_serializer.rb +34 -6
  120. data/lib/atatus/transport/serializers/span_serializer.rb +47 -12
  121. data/lib/atatus/transport/serializers/transaction_serializer.rb +18 -2
  122. data/lib/atatus/transport/serializers.rb +17 -5
  123. data/lib/atatus/transport/user_agent.rb +48 -0
  124. data/lib/atatus/transport/worker.rb +31 -7
  125. data/lib/atatus/util/inflector.rb +17 -0
  126. data/lib/atatus/util/lru_cache.rb +17 -0
  127. data/lib/atatus/util/throttle.rb +17 -0
  128. data/lib/atatus/util.rb +18 -1
  129. data/lib/atatus/version.rb +19 -1
  130. data/lib/atatus.rb +84 -16
  131. metadata +46 -26
  132. data/Rakefile +0 -19
  133. data/bench/.gitignore +0 -2
  134. data/bench/app.rb +0 -53
  135. data/bench/benchmark.rb +0 -36
  136. data/bench/report.rb +0 -55
  137. data/bench/rubyprof.rb +0 -39
  138. data/bench/stackprof.rb +0 -23
  139. data/bin/build_docs +0 -5
  140. data/bin/console +0 -15
  141. data/bin/setup +0 -8
  142. data/bin/with_framework +0 -7
  143. data/lib/atatus/metrics/vm.rb +0 -60
  144. data/lib/atatus/normalizers/action_controller.rb +0 -27
  145. data/lib/atatus/normalizers/action_mailer.rb +0 -26
  146. data/lib/atatus/normalizers/active_record.rb +0 -45
  147. data/lib/atatus/util/prefixed_logger.rb +0 -18
  148. data/vendor/.gitkeep +0 -0
@@ -0,0 +1,148 @@
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
+ class TraceContext
22
+ # @api private
23
+ class Tracestate
24
+ # @api private
25
+ class Entry
26
+ def initialize(key, value)
27
+ @key = key
28
+ @value = value
29
+ end
30
+
31
+ attr_reader :key, :value
32
+
33
+ def to_s
34
+ "#{key}=#{value}"
35
+ end
36
+ end
37
+
38
+ class EsEntry
39
+ ASSIGN = ':'
40
+ SPLIT = ';'
41
+
42
+ SHORT_TO_LONG = { 's' => 'sample_rate' }
43
+ LONG_TO_SHORT = { 'sample_rate' => 's' }
44
+
45
+ def initialize(values = nil)
46
+ parse(values)
47
+ end
48
+
49
+ attr_reader :sample_rate
50
+
51
+ def key
52
+ 'es'
53
+ end
54
+
55
+ def value
56
+ LONG_TO_SHORT.map do |l, s|
57
+ "#{s}#{ASSIGN}#{send(l)}"
58
+ end.join(SPLIT)
59
+ end
60
+
61
+ def empty?
62
+ !sample_rate
63
+ end
64
+
65
+ def sample_rate=(val)
66
+ float = Float(val).round(3)
67
+
68
+ return nil unless (0.0..1.0).include?(float)
69
+
70
+ @sample_rate = float
71
+ rescue ArgumentError => e
72
+ nil
73
+ end
74
+
75
+ def to_s
76
+ return nil if empty?
77
+
78
+ "es=#{value}"
79
+ end
80
+
81
+ private
82
+
83
+ def parse(values)
84
+ return unless values
85
+
86
+ values.split(SPLIT).map do |kv|
87
+ k, v = kv.split(ASSIGN)
88
+ next unless SHORT_TO_LONG.keys.include?(k)
89
+ send("#{SHORT_TO_LONG[k]}=", v)
90
+ end
91
+ end
92
+ end
93
+
94
+ extend Forwardable
95
+
96
+ def initialize(entries: {}, sample_rate: nil)
97
+ @entries = entries
98
+
99
+ self.sample_rate = sample_rate if sample_rate
100
+ end
101
+
102
+ attr_accessor :entries
103
+
104
+ def_delegators :es_entry, :sample_rate, :sample_rate=
105
+
106
+ def self.parse(header)
107
+ entries =
108
+ split_by_nl_and_comma(header)
109
+ .each_with_object({}) do |entry, hsh|
110
+ k, v = entry.split('=')
111
+
112
+ hsh[k] =
113
+ case k
114
+ when 'es' then EsEntry.new(v)
115
+ else Entry.new(k, v)
116
+ end
117
+ end
118
+
119
+ new(entries: entries)
120
+ end
121
+
122
+ def to_header
123
+ return "" unless entries.any?
124
+
125
+ entries.values.map(&:to_s).join(',')
126
+ end
127
+
128
+ private
129
+
130
+ def es_entry
131
+ # lazy generate this so we only add it if necessary
132
+ entries['es'] ||= EsEntry.new
133
+ end
134
+
135
+ class << self
136
+ private
137
+
138
+ def split_by_nl_and_comma(str)
139
+ # HTTP allows multiple headers with the same name, eg. multiple
140
+ # Set-Cookie headers per response.
141
+ # Rack handles this by joining the headers under the same key, separated
142
+ # by newlines, see https://www.rubydoc.info/github/rack/rack/file/SPEC
143
+ String(str).split("\n").map { |s| s.split(',') }.flatten
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -1,85 +1,118 @@
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
+
1
18
  # frozen_string_literal: true
2
19
 
20
+ require 'atatus/trace_context/tracestate'
21
+ require 'atatus/trace_context/traceparent'
22
+
3
23
  module Atatus
4
24
  # @api private
5
25
  class TraceContext
6
- class InvalidTraceparentHeader < StandardError; end
26
+ extend Forwardable
7
27
 
8
- VERSION = '00'
9
- HEX_REGEX = /[^[:xdigit:]]/.freeze
10
-
11
- TRACE_ID_LENGTH = 16
12
- ID_LENGTH = 8
28
+ class InvalidTraceparentHeader < StandardError; end
13
29
 
14
30
  def initialize(
15
- version: VERSION,
16
- trace_id: nil,
17
- span_id: nil,
18
- id: nil,
19
- recorded: true
31
+ traceparent: nil,
32
+ tracestate: nil,
33
+ **legacy_traceparent_attrs
20
34
  )
21
- @version = version
22
- @trace_id = trace_id || hex(TRACE_ID_LENGTH)
23
- # TODO: rename to parent_id with next major version bump
24
- @parent_id = span_id
25
- @id = id || hex(ID_LENGTH)
26
- @recorded = recorded
35
+ @traceparent = traceparent || Traceparent.new(**legacy_traceparent_attrs)
36
+ @tracestate = tracestate || Tracestate.new
27
37
  end
28
38
 
29
- attr_accessor :version, :id, :trace_id, :parent_id, :recorded
39
+ attr_accessor :traceparent, :tracestate
40
+
41
+ def_delegators :traceparent,
42
+ :version, :trace_id, :id, :parent_id, :ensure_parent_id, :recorded?
43
+
44
+ class << self
45
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
46
+ def parse(legacy_header = nil, env: nil, metadata: nil)
47
+ unless legacy_header || env || metadata
48
+ raise ArgumentError, 'TraceContext expects env:, metadata: ' \
49
+ 'or single argument header string'
50
+ end
51
+
52
+ if legacy_header
53
+ legacy_parse_from_header(legacy_header)
54
+ elsif env
55
+ trace_context_from_env(env)
56
+ elsif metadata
57
+ trace_context_from_metadata(metadata)
58
+ end
59
+ end
60
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
61
+
62
+ private
30
63
 
31
- alias :recorded? :recorded
64
+ def trace_context_from_env(env)
65
+ return unless (
66
+ header =
67
+ env['HTTP_ATATUS_TRACEPARENT'] || env['HTTP_TRACEPARENT']
68
+ )
32
69
 
33
- # rubocop:disable Metrics/AbcSize
34
- def self.parse(header)
35
- raise InvalidTraceparentHeader unless header.length == 55
36
- raise InvalidTraceparentHeader unless header[0..1] == VERSION
70
+ parent = TraceContext::Traceparent.parse(header)
37
71
 
38
- new.tap do |t|
39
- t.version, t.trace_id, t.parent_id, t.flags =
40
- header.split('-').tap do |values|
41
- values[-1] = Util.hex_to_bits(values[-1])
72
+ state =
73
+ if (header = env['HTTP_TRACESTATE'])
74
+ TraceContext::Tracestate.parse(header)
42
75
  end
43
76
 
44
- raise InvalidTraceparentHeader if HEX_REGEX =~ t.trace_id
45
- raise InvalidTraceparentHeader if HEX_REGEX =~ t.parent_id
77
+ new(traceparent: parent, tracestate: state)
46
78
  end
47
- end
48
- # rubocop:enable Metrics/AbcSize
49
79
 
50
- def flags=(flags)
51
- @flags = flags
80
+ def trace_context_from_metadata(metadata)
81
+ return unless (header = metadata['atatus-traceparent'] ||
82
+ metadata['traceparent'])
52
83
 
53
- self.recorded = flags[7] == '1'
54
- end
84
+ parent = TraceContext::Traceparent.parse(header)
55
85
 
56
- def flags
57
- format('0000000%d', recorded? ? 1 : 0)
58
- end
86
+ state =
87
+ if (header = metadata['tracestate'])
88
+ TraceContext::Tracestate.parse(header)
89
+ end
59
90
 
60
- def hex_flags
61
- format('%02x', flags.to_i(2))
62
- end
91
+ new(traceparent: parent, tracestate: state)
92
+ end
63
93
 
64
- def ensure_parent_id
65
- @parent_id ||= hex(ID_LENGTH)
94
+ def legacy_parse_from_header(header)
95
+ parent = Traceparent.parse(header)
96
+ new(traceparent: parent)
97
+ end
66
98
  end
67
99
 
68
100
  def child
69
101
  dup.tap do |tc|
70
- tc.parent_id = tc.id
71
- tc.id = hex(ID_LENGTH)
102
+ tc.traceparent = tc.traceparent.child
72
103
  end
73
104
  end
74
105
 
75
- def to_header
76
- format('%s-%s-%s-%s', version, trace_id, id, hex_flags)
77
- end
106
+ def apply_headers
107
+ yield 'Traceparent', traceparent.to_header
108
+
109
+ if tracestate
110
+ yield 'Tracestate', tracestate.to_header
111
+ end
78
112
 
79
- private
113
+ return unless Atatus.agent.config.use_atatus_traceparent_header
80
114
 
81
- def hex(len)
82
- SecureRandom.hex(len)
115
+ yield 'Atatus-Traceparent', traceparent.to_header
83
116
  end
84
117
  end
85
118
  end
@@ -1,36 +1,71 @@
1
- # frozen_string_literal: true
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.
2
17
 
3
- require 'securerandom'
4
- require 'forwardable'
18
+ # frozen_string_literal: true
5
19
 
6
20
  module Atatus
7
21
  # @api private
8
22
  class Transaction
9
23
  extend Forwardable
24
+ include ChildDurations::Methods
10
25
 
11
26
  def_delegators :@trace_context,
12
27
  :trace_id, :parent_id, :id, :ensure_parent_id
13
28
 
14
29
  DEFAULT_TYPE = 'custom'
30
+ MUTEX = Mutex.new
15
31
 
16
32
  # rubocop:disable Metrics/ParameterLists
17
33
  def initialize(
18
34
  name = nil,
19
35
  type = nil,
20
36
  sampled: true,
37
+ sample_rate: 1,
21
38
  context: nil,
22
- labels: nil,
39
+ config:,
23
40
  trace_context: nil
24
41
  )
25
42
  @name = name
26
43
  @type = type || DEFAULT_TYPE
44
+ @config = config
45
+
46
+ # Cache these values in case they are changed during the
47
+ # transaction's lifetime via the remote config
48
+ @span_frames_min_duration = config.span_frames_min_duration
49
+ @collect_metrics = config.collect_metrics?
50
+ @breakdown_metrics = config.breakdown_metrics?
51
+ @framework_name = config.framework_name
52
+ @transaction_max_spans = config.transaction_max_spans
53
+ @default_labels = config.default_labels
27
54
 
28
55
  @sampled = sampled
56
+ @sample_rate = sample_rate
29
57
 
30
58
  @context = context || Context.new # TODO: Lazy generate this?
31
- Util.reverse_merge!(@context.labels, labels) if labels
59
+ if @default_labels
60
+ Util.reverse_merge!(@context.labels, @default_labels)
61
+ end
32
62
 
33
- @trace_context = trace_context || TraceContext.new(recorded: sampled)
63
+ unless (@trace_context = trace_context)
64
+ @trace_context = TraceContext.new(
65
+ traceparent: TraceContext::Traceparent.new(recorded: sampled),
66
+ tracestate: TraceContext::Tracestate.new(sample_rate: sampled ? sample_rate : 0)
67
+ )
68
+ end
34
69
 
35
70
  @started_spans = 0
36
71
  @dropped_spans = 0
@@ -41,8 +76,24 @@ module Atatus
41
76
 
42
77
  attr_accessor :name, :type, :result, :spans, :ruby_time
43
78
 
44
- attr_reader :context, :duration, :started_spans, :dropped_spans,
45
- :timestamp, :trace_context, :notifications
79
+ attr_reader(
80
+ :breakdown_metrics,
81
+ :collect_metrics,
82
+ :context,
83
+ :dropped_spans,
84
+ :duration,
85
+ :framework_name,
86
+ :notifications,
87
+ :self_time,
88
+ :sample_rate,
89
+ :span_frames_min_duration,
90
+ :started_spans,
91
+ :timestamp,
92
+ :trace_context,
93
+ :transaction_max_spans
94
+ )
95
+
96
+ alias :collect_metrics? :collect_metrics
46
97
 
47
98
  def sampled?
48
99
  @sampled
@@ -63,6 +114,8 @@ module Atatus
63
114
  def stop(clock_end = Util.monotonic_micros)
64
115
  raise 'Transaction not yet start' unless timestamp
65
116
  @duration = clock_end - @clock_start
117
+ @self_time = @duration - child_durations.duration
118
+
66
119
  self
67
120
  end
68
121
 
@@ -75,21 +128,24 @@ module Atatus
75
128
  # spans
76
129
 
77
130
  def inc_started_spans!
78
- @started_spans += 1
131
+ MUTEX.synchronize do
132
+ @started_spans += 1
133
+ if @started_spans > transaction_max_spans
134
+ @dropped_spans += 1
135
+ return false
136
+ end
137
+ end
138
+ true
79
139
  end
80
140
 
81
- def inc_dropped_spans!
82
- @dropped_spans += 1
83
- end
141
+ # context
84
142
 
85
- def max_spans_reached?(config)
86
- started_spans > config.transaction_max_spans
143
+ def add_response(status = nil, **args)
144
+ context.response = Context::Response.new(status, **args)
87
145
  end
88
146
 
89
- # context
90
-
91
- def add_response(*args)
92
- context.response = Context::Response.new(*args)
147
+ def set_user(user)
148
+ context.user = Context::User.infer(@config, user)
93
149
  end
94
150
 
95
151
  def inspect
@@ -1,15 +1,35 @@
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
+
1
18
  # frozen_string_literal: true
2
19
 
3
20
  require 'atatus/metadata'
21
+ require 'atatus/transport/user_agent'
22
+ require 'atatus/transport/headers'
4
23
  require 'atatus/transport/connection'
5
24
  require 'atatus/transport/worker'
6
25
  require 'atatus/transport/serializers'
7
26
  require 'atatus/transport/filters'
27
+ require 'atatus/transport/connection/http'
28
+
8
29
  require 'atatus/util/throttle'
9
30
 
10
31
  module Atatus
11
32
  module Transport
12
- # rubocop:disable Metrics/ClassLength
13
33
  # @api private
14
34
  class Base
15
35
  include Logging
@@ -28,7 +48,6 @@ module Atatus
28
48
  @stopped = Concurrent::AtomicBoolean.new
29
49
  @workers = Array.new(config.pool_size)
30
50
 
31
- @watcher_mutex = Mutex.new
32
51
  @worker_mutex = Mutex.new
33
52
  end
34
53
 
@@ -36,9 +55,13 @@ module Atatus
36
55
 
37
56
  def start
38
57
  debug '%s: Starting Transport', pid_str
58
+ # Set @stopped to false first, in case transport is restarted;
59
+ # ensure_worker_count requires @stopped to be false
60
+ # ~estolfo
61
+ @stopped.make_false unless @stopped.false?
39
62
 
40
- ensure_watcher_running
41
63
  ensure_worker_count
64
+ create_watcher
42
65
  end
43
66
 
44
67
  def stop
@@ -50,14 +73,13 @@ module Atatus
50
73
  stop_workers
51
74
  end
52
75
 
53
- # rubocop:disable Metrics/MethodLength
54
76
  def submit(resource)
55
77
  if @stopped.true?
56
78
  warn '%s: Transport stopping, no new events accepted', pid_str
79
+ debug 'Dropping: %s', resource.inspect
57
80
  return false
58
81
  end
59
82
 
60
- ensure_watcher_running
61
83
  queue.push(resource, true)
62
84
 
63
85
  true
@@ -68,31 +90,31 @@ module Atatus
68
90
  error '%s: Failed adding to the transport queue: %p', pid_str, e.inspect
69
91
  nil
70
92
  end
71
- # rubocop:enable Metrics/MethodLength
72
93
 
73
94
  def add_filter(key, callback)
74
95
  @filters.add(key, callback)
75
96
  end
76
97
 
98
+ def handle_forking!
99
+ # We can't just stop and start again because the StopMessage
100
+ # will then be the first message processed when the transport is
101
+ # restarted.
102
+ stop_watcher
103
+ ensure_worker_count
104
+ create_watcher
105
+ end
106
+
77
107
  private
78
108
 
79
109
  def pid_str
80
110
  format('[PID:%s]', Process.pid)
81
111
  end
82
112
 
83
- def ensure_watcher_running
84
- # pid has changed == we've forked
85
- return if @pid == Process.pid
86
-
87
- @watcher_mutex.synchronize do
88
- return if @pid == Process.pid
89
- @pid = Process.pid
90
-
91
- @watcher = Concurrent::TimerTask.execute(
92
- execution_interval: WATCHER_EXECUTION_INTERVAL,
93
- timeout_interval: WATCHER_TIMEOUT_INTERVAL
94
- ) { ensure_worker_count }
95
- end
113
+ def create_watcher
114
+ @watcher = Concurrent::TimerTask.execute(
115
+ execution_interval: WATCHER_EXECUTION_INTERVAL,
116
+ timeout_interval: WATCHER_TIMEOUT_INTERVAL
117
+ ) { ensure_worker_count }
96
118
  end
97
119
 
98
120
  def ensure_worker_count
@@ -124,7 +146,6 @@ module Atatus
124
146
  end
125
147
  end
126
148
 
127
- # rubocop:disable Metrics/MethodLength
128
149
  def stop_workers
129
150
  debug '%s: Stopping workers', pid_str
130
151
 
@@ -142,10 +163,10 @@ module Atatus
142
163
  thread.kill
143
164
  end
144
165
 
145
- @workers.clear
166
+ # Maintain the @worker array size for when transport is restarted
167
+ @workers.fill(nil)
146
168
  end
147
169
  end
148
- # rubocop:enable Metrics/MethodLength
149
170
 
150
171
  def send_stop_messages
151
172
  config.pool_size.times { queue.push(Worker::StopMessage.new, true) }
@@ -154,10 +175,7 @@ module Atatus
154
175
  end
155
176
 
156
177
  def stop_watcher
157
- @watcher_mutex.synchronize do
158
- return if watcher.nil? || @pid != Process.pid
159
- watcher.shutdown
160
- end
178
+ watcher&.shutdown
161
179
  end
162
180
 
163
181
  def throttled_queue_full_warning
@@ -169,6 +187,5 @@ module Atatus
169
187
  end).call
170
188
  end
171
189
  end
172
- # rubocop:enable Metrics/ClassLength
173
190
  end
174
191
  end