elastic-apm 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of elastic-apm might be problematic. Click here for more details.

Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +7 -1
  5. data/CHANGELOG.md +45 -0
  6. data/Gemfile +17 -12
  7. data/bench/app.rb +1 -2
  8. data/bench/benchmark.rb +1 -1
  9. data/bench/stackprof.rb +1 -1
  10. data/docs/api.asciidoc +115 -76
  11. data/docs/configuration.asciidoc +232 -167
  12. data/docs/context.asciidoc +7 -3
  13. data/docs/custom-instrumentation.asciidoc +17 -28
  14. data/docs/index.asciidoc +13 -7
  15. data/docs/supported-technologies.asciidoc +65 -0
  16. data/elastic-apm.gemspec +3 -2
  17. data/lib/elastic_apm.rb +272 -121
  18. data/lib/elastic_apm/agent.rb +56 -107
  19. data/lib/elastic_apm/config.rb +130 -106
  20. data/lib/elastic_apm/config/duration.rb +25 -0
  21. data/lib/elastic_apm/config/size.rb +28 -0
  22. data/lib/elastic_apm/context_builder.rb +1 -0
  23. data/lib/elastic_apm/deprecations.rb +19 -0
  24. data/lib/elastic_apm/error.rb +5 -2
  25. data/lib/elastic_apm/error/exception.rb +1 -1
  26. data/lib/elastic_apm/error_builder.rb +5 -0
  27. data/lib/elastic_apm/instrumenter.rb +121 -53
  28. data/lib/elastic_apm/internal_error.rb +1 -0
  29. data/lib/elastic_apm/{log.rb → logging.rb} +16 -11
  30. data/lib/elastic_apm/metadata.rb +20 -0
  31. data/lib/elastic_apm/metadata/process_info.rb +26 -0
  32. data/lib/elastic_apm/metadata/service_info.rb +56 -0
  33. data/lib/elastic_apm/metadata/system_info.rb +30 -0
  34. data/lib/elastic_apm/middleware.rb +31 -15
  35. data/lib/elastic_apm/normalizers/action_controller.rb +1 -1
  36. data/lib/elastic_apm/normalizers/action_mailer.rb +1 -1
  37. data/lib/elastic_apm/normalizers/action_view.rb +3 -3
  38. data/lib/elastic_apm/normalizers/active_record.rb +2 -1
  39. data/lib/elastic_apm/railtie.rb +1 -1
  40. data/lib/elastic_apm/span.rb +59 -29
  41. data/lib/elastic_apm/span/context.rb +30 -4
  42. data/lib/elastic_apm/span_helpers.rb +1 -1
  43. data/lib/elastic_apm/spies/delayed_job.rb +7 -7
  44. data/lib/elastic_apm/spies/elasticsearch.rb +4 -4
  45. data/lib/elastic_apm/spies/http.rb +38 -0
  46. data/lib/elastic_apm/spies/mongo.rb +22 -11
  47. data/lib/elastic_apm/spies/net_http.rb +7 -4
  48. data/lib/elastic_apm/spies/rake.rb +5 -6
  49. data/lib/elastic_apm/spies/redis.rb +1 -1
  50. data/lib/elastic_apm/spies/sequel.rb +9 -7
  51. data/lib/elastic_apm/spies/sidekiq.rb +5 -5
  52. data/lib/elastic_apm/spies/tilt.rb +2 -2
  53. data/lib/elastic_apm/sql_summarizer.rb +3 -3
  54. data/lib/elastic_apm/stacktrace_builder.rb +6 -6
  55. data/lib/elastic_apm/subscriber.rb +3 -3
  56. data/lib/elastic_apm/traceparent.rb +62 -0
  57. data/lib/elastic_apm/transaction.rb +62 -93
  58. data/lib/elastic_apm/transport/base.rb +98 -0
  59. data/lib/elastic_apm/transport/connection.rb +175 -0
  60. data/lib/elastic_apm/transport/filters.rb +45 -0
  61. data/lib/elastic_apm/transport/filters/request_body_filter.rb +31 -0
  62. data/lib/elastic_apm/transport/filters/secrets_filter.rb +59 -0
  63. data/lib/elastic_apm/transport/serializers.rb +58 -0
  64. data/lib/elastic_apm/transport/serializers/error_serializer.rb +59 -0
  65. data/lib/elastic_apm/transport/serializers/span_serializer.rb +30 -0
  66. data/lib/elastic_apm/transport/serializers/transaction_serializer.rb +33 -0
  67. data/lib/elastic_apm/transport/worker.rb +73 -0
  68. data/lib/elastic_apm/util.rb +11 -8
  69. data/lib/elastic_apm/version.rb +1 -1
  70. metadata +40 -21
  71. data/.travis.yml +0 -5
  72. data/docs/troubleshooting.asciidoc +0 -28
  73. data/lib/elastic_apm/filters.rb +0 -46
  74. data/lib/elastic_apm/filters/request_body_filter.rb +0 -33
  75. data/lib/elastic_apm/filters/secrets_filter.rb +0 -59
  76. data/lib/elastic_apm/http.rb +0 -139
  77. data/lib/elastic_apm/process_info.rb +0 -24
  78. data/lib/elastic_apm/serializers.rb +0 -28
  79. data/lib/elastic_apm/serializers/errors.rb +0 -61
  80. data/lib/elastic_apm/serializers/transactions.rb +0 -51
  81. data/lib/elastic_apm/service_info.rb +0 -54
  82. data/lib/elastic_apm/system_info.rb +0 -28
  83. data/lib/elastic_apm/util/dig.rb +0 -31
  84. data/lib/elastic_apm/util/inspector.rb +0 -61
  85. data/lib/elastic_apm/worker.rb +0 -106
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'elastic_apm/transport/filters/request_body_filter'
4
+ require 'elastic_apm/transport/filters/secrets_filter'
5
+
6
+ module ElasticAPM
7
+ module Transport
8
+ # @api private
9
+ module Filters
10
+ def self.new(config)
11
+ Container.new(config)
12
+ end
13
+
14
+ # @api private
15
+ class Container
16
+ def initialize(config)
17
+ @filters = {
18
+ request_body: RequestBodyFilter.new(config),
19
+ secrets: SecretsFilter.new(config)
20
+ }
21
+ end
22
+
23
+ def add(key, filter)
24
+ @filters[key] = filter
25
+ end
26
+
27
+ def remove(key)
28
+ @filters.delete(key)
29
+ end
30
+
31
+ def apply!(payload)
32
+ @filters.reduce(payload) do |result, (_key, filter)|
33
+ result = filter.call(result)
34
+ break if result.nil?
35
+ result
36
+ end
37
+ end
38
+
39
+ def length
40
+ @filters.length
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ module Filters
6
+ # @api private
7
+ class RequestBodyFilter
8
+ FILTERED = '[FILTERED]'
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ end
13
+
14
+ def call(payload)
15
+ strip_body_from payload[:transaction]
16
+ strip_body_from payload[:error]
17
+
18
+ payload
19
+ end
20
+
21
+ private
22
+
23
+ def strip_body_from(payload)
24
+ return unless payload
25
+ return unless (request = payload.dig(:context, :request))
26
+ request[:body] = FILTERED
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ module Filters
6
+ # @api private
7
+ class SecretsFilter
8
+ FILTERED = '[FILTERED]'
9
+
10
+ KEY_FILTERS = [
11
+ /passw(or)?d/i,
12
+ /^pw$/,
13
+ /secret/i,
14
+ /token/i,
15
+ /api[-._]?key/i,
16
+ /session[-._]?id/i
17
+ ].freeze
18
+
19
+ VALUE_FILTERS = [
20
+ # (probably) credit card number
21
+ /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/
22
+ ].freeze
23
+
24
+ def initialize(config)
25
+ @config = config
26
+ @key_filters = KEY_FILTERS + config.custom_key_filters
27
+ end
28
+
29
+ def call(payload)
30
+ strip_from payload[:transaction], :context, :request, :headers
31
+ strip_from payload[:transaction], :context, :response, :headers
32
+ strip_from payload[:error], :context, :request, :headers
33
+ strip_from payload[:error], :context, :response, :headers
34
+
35
+ payload
36
+ end
37
+
38
+ def strip_from(event, *path)
39
+ return unless event
40
+ return unless (headers = event.dig(*path))
41
+
42
+ headers.each do |k, v|
43
+ if filter_key?(k) || filter_value?(v)
44
+ headers[k] = FILTERED
45
+ end
46
+ end
47
+ end
48
+
49
+ def filter_key?(key)
50
+ @key_filters.any? { |regex| key.match regex }
51
+ end
52
+
53
+ def filter_value?(value)
54
+ VALUE_FILTERS.any? { |regex| value.match regex }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ module ElasticAPM
6
+ module Transport
7
+ # @api private
8
+ module Serializers
9
+ # @api private
10
+ class UnrecognizedResource < InternalError; end
11
+
12
+ # @api private
13
+ class Serializer
14
+ def initialize(config)
15
+ @config = config
16
+ end
17
+
18
+ private
19
+
20
+ def ms(micros)
21
+ micros.to_f / 1_000
22
+ end
23
+ end
24
+
25
+ # @api private
26
+ class Container
27
+ def initialize(config)
28
+ @transaction = Serializers::TransactionSerializer.new(config)
29
+ @span = Serializers::SpanSerializer.new(config)
30
+ @error = Serializers::ErrorSerializer.new(config)
31
+ end
32
+
33
+ attr_reader :transaction, :span, :error
34
+
35
+ def serialize(resource)
36
+ case resource
37
+ when Transaction
38
+ transaction.build(resource)
39
+ when Span
40
+ span.build(resource)
41
+ when Error
42
+ error.build(resource)
43
+ else
44
+ raise UnrecognizedResource, resource.inspect
45
+ end
46
+ end
47
+ end
48
+
49
+ def self.new(config)
50
+ Container.new(config)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ require 'elastic_apm/transport/serializers/transaction_serializer'
57
+ require 'elastic_apm/transport/serializers/span_serializer'
58
+ require 'elastic_apm/transport/serializers/error_serializer'
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ module Serializers
6
+ # @api private
7
+ class ErrorSerializer < Serializer
8
+ # rubocop:disable Metrics/MethodLength
9
+ def build(error)
10
+ base = {
11
+ id: error.id,
12
+ transaction_id: error.transaction_id,
13
+ trace_id: error.trace_id,
14
+ parent_id: error.parent_id,
15
+
16
+ culprit: error.culprit,
17
+ timestamp: error.timestamp,
18
+ context: error.context.to_h
19
+ }
20
+
21
+ if (exception = error.exception)
22
+ base[:exception] = build_exception exception
23
+ end
24
+
25
+ if (log = error.log)
26
+ base[:log] = build_log log
27
+ end
28
+
29
+ { error: base }
30
+ end
31
+ # rubocop:enable Metrics/MethodLength
32
+
33
+ private
34
+
35
+ def build_exception(exception)
36
+ {
37
+ message: exception.message,
38
+ type: exception.type,
39
+ module: exception.module,
40
+ code: exception.code,
41
+ attributes: exception.attributes,
42
+ stacktrace: exception.stacktrace.to_a,
43
+ handled: exception.handled
44
+ }
45
+ end
46
+
47
+ def build_log(log)
48
+ {
49
+ message: log.message,
50
+ level: log.level,
51
+ logger_name: log.logger_name,
52
+ param_message: log.param_message,
53
+ stacktrace: log.stacktrace.to_a
54
+ }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ module Serializers
6
+ # @api private
7
+ class SpanSerializer < Serializer
8
+ # rubocop:disable Metrics/MethodLength
9
+ def build(span)
10
+ {
11
+ span: {
12
+ id: span.id,
13
+ transaction_id: span.transaction_id,
14
+ parent_id: span.parent_id,
15
+ name: span.name,
16
+ type: span.type,
17
+ start: ms(span.relative_start),
18
+ duration: ms(span.duration),
19
+ context: span.context&.to_h,
20
+ stacktrace: span.stacktrace.to_a,
21
+ timestamp: span.timestamp,
22
+ trace_id: span.trace_id
23
+ }
24
+ }
25
+ end
26
+ # rubocop:enable Metrics/MethodLength
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ module Serializers
6
+ # @api private
7
+ class TransactionSerializer < Serializer
8
+ # rubocop:disable Metrics/MethodLength
9
+ def build(transaction)
10
+ {
11
+ transaction: {
12
+ id: transaction.id,
13
+ trace_id: transaction.trace_id,
14
+ parent_id: transaction.parent_id,
15
+ name: transaction.name,
16
+ type: transaction.type,
17
+ result: transaction.result.to_s,
18
+ duration: ms(transaction.duration),
19
+ timestamp: transaction.timestamp,
20
+ sampled: transaction.sampled?,
21
+ context: transaction.context.to_h,
22
+ span_count: {
23
+ started: transaction.started_spans,
24
+ dropped: transaction.dropped_spans
25
+ }
26
+ }
27
+ }
28
+ end
29
+ # rubocop:enable Metrics/MethodLength
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ElasticAPM
4
+ module Transport
5
+ # @api private
6
+ class Worker
7
+ include Logging
8
+
9
+ # @api private
10
+ class StopMessage; end
11
+
12
+ # @api private
13
+ class FlushMessage; end
14
+
15
+ def initialize(
16
+ config,
17
+ queue,
18
+ serializers:,
19
+ filters:,
20
+ conn_adapter: Connection
21
+ )
22
+ @config = config
23
+ @queue = queue
24
+
25
+ @stopping = false
26
+
27
+ @connection = conn_adapter.new(config)
28
+ @serializers = serializers
29
+ @filters = filters
30
+ end
31
+
32
+ attr_reader :queue, :filters, :name, :connection, :serializers
33
+
34
+ def stop
35
+ @stopping = true
36
+ end
37
+
38
+ def stopping?
39
+ @stopping
40
+ end
41
+
42
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
43
+ def work_forever
44
+ while (msg = queue.pop)
45
+ case msg
46
+ when StopMessage
47
+ stop
48
+ else
49
+ process msg
50
+ end
51
+
52
+ next unless stopping?
53
+
54
+ debug 'Stopping worker -- %s', self
55
+ @connection.flush
56
+ break
57
+ end
58
+ rescue Exception => e
59
+ warn 'Worker died with exception: %s', e.inspect
60
+ debug e.backtrace.join("\n")
61
+ end
62
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
63
+
64
+ private
65
+
66
+ def process(resource)
67
+ serialized = serializers.serialize(resource)
68
+ @filters.apply!(serialized)
69
+ @connection.write(serialized.to_json)
70
+ end
71
+ end
72
+ end
73
+ end
@@ -7,19 +7,22 @@ module ElasticAPM
7
7
  target - target.to_i % 60
8
8
  end
9
9
 
10
- def self.micros(target = Time.now.utc)
11
- target.to_i * 1_000_000 + target.usec
12
- end
13
-
14
- def self.inspect_transaction(transaction)
15
- Inspector.new.transaction transaction
10
+ def self.micros(target = Time.now)
11
+ utc = target.utc
12
+ utc.to_i * 1_000_000 + utc.usec
16
13
  end
17
14
 
18
15
  def self.git_sha
19
16
  sha = `git rev-parse --verify HEAD 2>&1`.chomp
20
17
  $? && $?.success? ? sha : nil # rubocop:disable Style/SpecialGlobalVars
21
18
  end
19
+
20
+ def self.hex_to_bits(str)
21
+ str.hex.to_s(2).rjust(str.size * 4, '0')
22
+ end
23
+
24
+ def self.reverse_merge!(first, second)
25
+ first.merge!(second) { |_, old, _| old }
26
+ end
22
27
  end
23
28
  end
24
-
25
- require 'elastic_apm/util/inspector'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ElasticAPM
4
- VERSION = '1.1.0'.freeze
4
+ VERSION = '2.0.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic-apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikkel Malmberg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-07 00:00:00.000000000 Z
11
+ date: 2018-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -16,14 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 1.0.0
19
+ version: '1.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 1.0.0
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: http
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
27
41
  description:
28
42
  email:
29
43
  - mikkel@elastic.co
@@ -35,7 +49,6 @@ files:
35
49
  - ".hound.yml"
36
50
  - ".rspec"
37
51
  - ".rubocop.yml"
38
- - ".travis.yml"
39
52
  - CHANGELOG.md
40
53
  - CODE_OF_CONDUCT.md
41
54
  - Gemfile
@@ -60,12 +73,14 @@ files:
60
73
  - docs/getting-started-rack.asciidoc
61
74
  - docs/getting-started-rails.asciidoc
62
75
  - docs/index.asciidoc
63
- - docs/troubleshooting.asciidoc
76
+ - docs/supported-technologies.asciidoc
64
77
  - elastic-apm.gemspec
65
78
  - lib/elastic-apm.rb
66
79
  - lib/elastic_apm.rb
67
80
  - lib/elastic_apm/agent.rb
68
81
  - lib/elastic_apm/config.rb
82
+ - lib/elastic_apm/config/duration.rb
83
+ - lib/elastic_apm/config/size.rb
69
84
  - lib/elastic_apm/context.rb
70
85
  - lib/elastic_apm/context/request.rb
71
86
  - lib/elastic_apm/context/request/socket.rb
@@ -73,17 +88,18 @@ files:
73
88
  - lib/elastic_apm/context/response.rb
74
89
  - lib/elastic_apm/context/user.rb
75
90
  - lib/elastic_apm/context_builder.rb
91
+ - lib/elastic_apm/deprecations.rb
76
92
  - lib/elastic_apm/error.rb
77
93
  - lib/elastic_apm/error/exception.rb
78
94
  - lib/elastic_apm/error/log.rb
79
95
  - lib/elastic_apm/error_builder.rb
80
- - lib/elastic_apm/filters.rb
81
- - lib/elastic_apm/filters/request_body_filter.rb
82
- - lib/elastic_apm/filters/secrets_filter.rb
83
- - lib/elastic_apm/http.rb
84
96
  - lib/elastic_apm/instrumenter.rb
85
97
  - lib/elastic_apm/internal_error.rb
86
- - lib/elastic_apm/log.rb
98
+ - lib/elastic_apm/logging.rb
99
+ - lib/elastic_apm/metadata.rb
100
+ - lib/elastic_apm/metadata/process_info.rb
101
+ - lib/elastic_apm/metadata/service_info.rb
102
+ - lib/elastic_apm/metadata/system_info.rb
87
103
  - lib/elastic_apm/middleware.rb
88
104
  - lib/elastic_apm/naively_hashable.rb
89
105
  - lib/elastic_apm/normalizers.rb
@@ -91,12 +107,7 @@ files:
91
107
  - lib/elastic_apm/normalizers/action_mailer.rb
92
108
  - lib/elastic_apm/normalizers/action_view.rb
93
109
  - lib/elastic_apm/normalizers/active_record.rb
94
- - lib/elastic_apm/process_info.rb
95
110
  - lib/elastic_apm/railtie.rb
96
- - lib/elastic_apm/serializers.rb
97
- - lib/elastic_apm/serializers/errors.rb
98
- - lib/elastic_apm/serializers/transactions.rb
99
- - lib/elastic_apm/service_info.rb
100
111
  - lib/elastic_apm/span.rb
101
112
  - lib/elastic_apm/span/context.rb
102
113
  - lib/elastic_apm/span_helpers.rb
@@ -104,6 +115,7 @@ files:
104
115
  - lib/elastic_apm/spies/action_dispatch.rb
105
116
  - lib/elastic_apm/spies/delayed_job.rb
106
117
  - lib/elastic_apm/spies/elasticsearch.rb
118
+ - lib/elastic_apm/spies/http.rb
107
119
  - lib/elastic_apm/spies/json.rb
108
120
  - lib/elastic_apm/spies/mongo.rb
109
121
  - lib/elastic_apm/spies/net_http.rb
@@ -118,15 +130,22 @@ files:
118
130
  - lib/elastic_apm/stacktrace/frame.rb
119
131
  - lib/elastic_apm/stacktrace_builder.rb
120
132
  - lib/elastic_apm/subscriber.rb
121
- - lib/elastic_apm/system_info.rb
133
+ - lib/elastic_apm/traceparent.rb
122
134
  - lib/elastic_apm/transaction.rb
135
+ - lib/elastic_apm/transport/base.rb
136
+ - lib/elastic_apm/transport/connection.rb
137
+ - lib/elastic_apm/transport/filters.rb
138
+ - lib/elastic_apm/transport/filters/request_body_filter.rb
139
+ - lib/elastic_apm/transport/filters/secrets_filter.rb
140
+ - lib/elastic_apm/transport/serializers.rb
141
+ - lib/elastic_apm/transport/serializers/error_serializer.rb
142
+ - lib/elastic_apm/transport/serializers/span_serializer.rb
143
+ - lib/elastic_apm/transport/serializers/transaction_serializer.rb
144
+ - lib/elastic_apm/transport/worker.rb
123
145
  - lib/elastic_apm/util.rb
124
- - lib/elastic_apm/util/dig.rb
125
146
  - lib/elastic_apm/util/inflector.rb
126
- - lib/elastic_apm/util/inspector.rb
127
147
  - lib/elastic_apm/util/lru_cache.rb
128
148
  - lib/elastic_apm/version.rb
129
- - lib/elastic_apm/worker.rb
130
149
  - vendor/.gitkeep
131
150
  homepage: https://github.com/elastic/apm-agent-ruby
132
151
  licenses:
@@ -141,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
141
160
  requirements:
142
161
  - - ">="
143
162
  - !ruby/object:Gem::Version
144
- version: 2.2.0
163
+ version: 2.3.0
145
164
  required_rubygems_version: !ruby/object:Gem::Requirement
146
165
  requirements:
147
166
  - - ">="