elastic-apm 1.1.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.

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
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ElasticAPM
4
- # @api private
5
- class ServiceInfo
6
- def initialize(config)
7
- @config = config
8
- end
9
-
10
- # rubocop:disable Metrics/MethodLength
11
- def build
12
- base = {
13
- name: @config.service_name,
14
- environment: @config.environment,
15
- agent: {
16
- name: 'ruby',
17
- version: VERSION
18
- },
19
- framework: nil,
20
- language: {
21
- name: 'ruby',
22
- version: RUBY_VERSION
23
- },
24
- runtime: runtime,
25
- version: @config.service_version || Util.git_sha
26
- }
27
-
28
- if @config.framework_name
29
- base[:framework] = {
30
- name: @config.framework_name,
31
- version: @config.framework_version
32
- }
33
- end
34
-
35
- base
36
- end
37
- # rubocop:enable Metrics/MethodLength
38
-
39
- def self.build(config)
40
- new(config).build
41
- end
42
-
43
- private
44
-
45
- def runtime
46
- case RUBY_ENGINE
47
- when 'ruby'
48
- { name: RUBY_ENGINE, version: RUBY_VERSION || RUBY_ENGINE_VERSION }
49
- when 'jruby'
50
- { name: RUBY_ENGINE, version: JRUBY_VERSION || RUBY_ENGINE_VERSION }
51
- end
52
- end
53
- end
54
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ElasticAPM
4
- # @api private
5
- class SystemInfo
6
- def initialize(config)
7
- @config = config
8
- end
9
-
10
- def build
11
- {
12
- hostname: @config.hostname || `hostname`.chomp,
13
- architecture: platform.cpu,
14
- platform: platform.os
15
- }
16
- end
17
-
18
- def self.build(config)
19
- new(config).build
20
- end
21
-
22
- private
23
-
24
- def platform
25
- @platform ||= Gem::Platform.local
26
- end
27
- end
28
- end
@@ -1,31 +0,0 @@
1
- # Backport Enumerable#dig to Ruby < 2.3
2
- #
3
- # Implementation from
4
- # https://github.com/Invoca/ruby_dig/blob/master/lib/ruby_dig.rb
5
-
6
- # @api private
7
- module RubyDig
8
- def dig(key, *rest)
9
- value = self[key]
10
-
11
- if value.nil? || rest.empty?
12
- value
13
- elsif value.respond_to?(:dig)
14
- value.dig(*rest)
15
- else
16
- raise TypeError, "#{value.class} does not respond to `#dig'"
17
- end
18
- end
19
- end
20
-
21
- if RUBY_VERSION < '2.3'
22
- # @api private
23
- class Array
24
- include RubyDig
25
- end
26
-
27
- # @api private
28
- class Hash
29
- include RubyDig
30
- end
31
- end
@@ -1,61 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ElasticAPM
4
- module Util
5
- # @api private
6
- class Inspector
7
- def initialize(width = 80)
8
- @width = width
9
- end
10
-
11
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
12
- def transaction(transaction)
13
- unless transaction.done?
14
- raise ArgumentError, 'Transaction still running'
15
- end
16
-
17
- width_factor = @width.to_f / ms(transaction.duration)
18
-
19
- lines = ['=' * @width]
20
- lines << "[T] #{transaction.name} " \
21
- "- #{transaction.type} (#{ms transaction.duration} ms)"
22
- lines << "+#{'-' * (@width - 2)}+"
23
-
24
- transaction.spans.each do |span|
25
- indent = (ms(span.relative_start) * width_factor).to_i
26
-
27
- if span.duration
28
- span_width = ms(span.duration) * width_factor
29
- duration_desc = ms(span.duration)
30
- else
31
- span_width = @width - indent
32
- duration_desc = 'RUNNING'
33
- end
34
-
35
- description = "[#{span.id}] " \
36
- "#{span.name} - #{span.type} (#{duration_desc} ms)"
37
- description_indent = [
38
- 0,
39
- [indent, @width - description.length].min
40
- ].max
41
-
42
- lines << "#{' ' * description_indent}#{description}"
43
- lines << "#{' ' * indent}+#{'-' * [(span_width - 2), 0].max}+"
44
- end
45
-
46
- lines.map { |s| s[0..@width] }.join("\n")
47
- rescue StandardError => e
48
- puts e
49
- puts e.backtrace.join("\n")
50
- nil
51
- end
52
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
53
-
54
- private
55
-
56
- def ms(micros)
57
- micros.to_f / 1_000
58
- end
59
- end
60
- end
61
- end
@@ -1,106 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'concurrent/timer_task'
4
-
5
- module ElasticAPM
6
- # @api private
7
- class Worker
8
- include Log
9
-
10
- # @api private
11
- class StopMsg; end
12
-
13
- # @api private
14
- class FlushMsg; end
15
-
16
- # @api private
17
- class ErrorMsg
18
- def initialize(error)
19
- @error = error
20
- end
21
-
22
- attr_reader :error
23
- end
24
-
25
- def initialize(config, messages, pending_transactions, adapter)
26
- @config = config
27
- @messages = messages
28
- @pending_transactions = pending_transactions
29
- @adapter = adapter
30
-
31
- @serializers = Struct.new(:transactions, :errors).new(
32
- Serializers::Transactions.new(config),
33
- Serializers::Errors.new(config)
34
- )
35
- end
36
-
37
- attr_reader :config, :messages, :pending_transactions
38
-
39
- # rubocop:disable Metrics/MethodLength
40
- def run_forever
41
- @timer_task = build_timer_task.execute
42
-
43
- while (msg = messages.pop)
44
- case msg
45
- when ErrorMsg
46
- post_error msg
47
- when FlushMsg
48
- collect_and_send_transactions
49
- when StopMsg
50
- # empty collected transactions before exiting
51
- collect_and_send_transactions
52
- stop!
53
- end
54
- end
55
- end
56
- # rubocop:enable Metrics/MethodLength
57
-
58
- private
59
-
60
- def stop!
61
- @timer_task && @timer_task.shutdown
62
- Thread.exit
63
- end
64
-
65
- def build_timer_task
66
- Concurrent::TimerTask.new(execution_interval: config.flush_interval) do
67
- messages.push(FlushMsg.new)
68
- end
69
- end
70
-
71
- def post_error(msg)
72
- payload = @serializers.errors.build_all([msg.error])
73
- @adapter.post('/v1/errors', payload)
74
- end
75
-
76
- def collect_and_send_transactions
77
- return if pending_transactions.empty?
78
-
79
- transactions = collect_batched_transactions
80
-
81
- payload = @serializers.transactions.build_all(transactions)
82
-
83
- begin
84
- @adapter.post('/v1/transactions', payload)
85
- rescue ::Exception => e
86
- fatal 'Failed posting: %s', e.inspect
87
- debug e.backtrace.join("\n")
88
- nil
89
- end
90
- end
91
-
92
- def collect_batched_transactions
93
- batch = []
94
-
95
- begin
96
- while (transaction = pending_transactions.pop(true)) &&
97
- batch.length <= config.max_queue_size
98
- batch << transaction
99
- end
100
- rescue ThreadError # queue empty
101
- end
102
-
103
- batch
104
- end
105
- end
106
- end