plain_apm 0.7.0 → 0.8.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2b4d2bddabd031b2b17d2edcf27e32f323c217b2331c469072e95d0afeb58ec7
4
- data.tar.gz: a892bbd62da4a10b074046c39326576355d591bf02982f9d336a97d887f99bc6
3
+ metadata.gz: 3acddaa717f06d06714c34402f068f3f196cfa3f0408b5567a3e488f77305793
4
+ data.tar.gz: cac965341db100f19bc3199d629ddfd3bff4fd7e9f5695a9c4c11baf69ba7c50
5
5
  SHA512:
6
- metadata.gz: b523dbaea426bbb9f2e4c2808efb4937ebf5c842361d07c9a0ae6a23bef03fe8bef0a71815710b4c55a7f8a1eeaea01e8b0fbe01bb3ed9af58743a31aa09c0aa
7
- data.tar.gz: 93c110b5e728cd6e934cbb25e56bd5345e3cc45dc1776922ca39a5de902e19a996fcc2aa7de0c749b231e8faf137b16be49f1d9389bec1735986223f18bc6798
6
+ metadata.gz: 0e2919a1a3f001220ad564e982c9097b016b791296f71e2f8cadc3dda8f1abdd5a9a85aae650e239c3dbea638f6b385ef33943fd7c4e56419b340f8bb756046f
7
+ data.tar.gz: a7f2f65d4cf5ff3a673d54e3f196fbe79c60268104c9b531127fc87aad56de262d06a3c1858f19e0a27fff6b3fc66bd2117614081ad64c1cce030faf1d7fd97d
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "singleton"
4
4
  require "json"
5
- require "socket"
6
5
 
7
6
  module PlainApm
8
7
  class Agent
@@ -1,6 +1,9 @@
1
+ require "time"
2
+ require "socket"
3
+
1
4
  module PlainApm
2
5
  module EventAttributes
3
- SOURCES_WITH_HOST_ATTRIBUTES = %w[
6
+ SOURCES_WITH_EXTRA_ATTRIBUTES = %w[
4
7
  action_controller
5
8
  action_mailer
6
9
  active_job
@@ -23,8 +26,7 @@ module PlainApm
23
26
  "name" => tool
24
27
  }
25
28
 
26
- attrs.merge!(agent_attributes)
27
- attrs.merge!(host_attributes) if add_host_attributes?(source)
29
+ attrs.merge!(trace_attributes(source))
28
30
 
29
31
  [tool, attrs]
30
32
  end
@@ -41,7 +43,7 @@ module PlainApm
41
43
  }
42
44
 
43
45
  if context[:env]
44
- attrs["params"] = env["action_dispatch.request.parameters"]
46
+ attrs["params"] = context[:env]["action_dispatch.request.parameters"]
45
47
  end
46
48
 
47
49
  if context[:job]&.is_a?(ActiveJob::Base)
@@ -57,8 +59,7 @@ module PlainApm
57
59
  })
58
60
  end
59
61
 
60
- attrs.merge!(context_attributes, agent_attributes)
61
- attrs.merge!(host_attributes) if add_host_attributes?(source)
62
+ attrs.merge!(trace_attributes(source))
62
63
 
63
64
  [source, attrs]
64
65
  end
@@ -71,50 +72,52 @@ module PlainApm
71
72
  "source" => source,
72
73
  "name" => name,
73
74
  "allocations" => event.allocations,
74
- "thread_allocations" => event.thread_allocations,
75
- "started_at" => event.time,
76
- "finished_at" => event.end
75
+ "event_time" => event.time,
76
+ "duration" => event.duration
77
77
  }
78
78
 
79
+ attrs["thread_allocations"] = event.thread_allocations if event.respond_to?(:thread_allocations)
79
80
  attrs["source_location"] = loc if !loc.nil?
80
- attrs.merge!(context_attributes, agent_attributes)
81
- attrs.merge!(host_attributes) if add_host_attributes?(source)
81
+
82
+ attrs.merge!(trace_attributes(source))
82
83
 
83
84
  [name, attrs]
84
85
  end
85
86
 
86
87
  private
87
88
 
88
- def context_attributes
89
- ##
90
- # Context contains the trace ID (which comes from either
91
- # HTTP_X_REQUEST_ID header, the deserialized job,
92
- # or is generated by the trace_id middleware).
93
- # It can also carry user inserted app data.
94
- if defined?(PlainApm::Extensions::Context)
95
- PlainApm::Extensions::Context.current
96
- else
97
- {}
98
- end
89
+ def trace_attributes(source)
90
+ process_attributes.merge(context_attributes)
99
91
  end
100
92
 
101
- def agent_attributes
93
+ def process_attributes
102
94
  {
95
+ "thread_id" => Thread.current.object_id,
96
+ "collected_at" => Time.now.iso8601(9),
103
97
  "version" => PlainApm::VERSION
104
- }
98
+ }.merge(
99
+ host_attributes
100
+ )
105
101
  end
106
102
 
107
103
  def host_attributes
108
- {
109
- "collected_at" => Time.now.iso8601(9),
104
+ @host_attributes ||= {
110
105
  "hostname" => Socket.gethostname,
111
- "pid" => Process.pid,
112
- "thread_id" => Thread.current.object_id
106
+ "pid" => Process.pid
113
107
  }
114
108
  end
115
109
 
116
- def add_host_attributes?(source)
117
- SOURCES_WITH_HOST_ATTRIBUTES.include?(source)
110
+ def context_attributes
111
+ ##
112
+ # Context contains the trace ID (which comes from either
113
+ # HTTP_X_REQUEST_ID header, the deserialized job,
114
+ # or is generated by the trace_id middleware).
115
+ # It can also carry user inserted app data.
116
+ if defined?(PlainApm::Extensions::Context)
117
+ PlainApm::Extensions::Context.current
118
+ else
119
+ {}
120
+ end
118
121
  end
119
122
 
120
123
  def source_location
@@ -24,12 +24,6 @@ module PlainApm
24
24
  super(job)
25
25
  end
26
26
  end
27
-
28
- ##
29
- # Allow tracing request ID through jobs
30
- ActiveSupport.on_load(:active_job) do |klass|
31
- klass.prepend(ActiveJob)
32
- end
33
27
  end
34
28
  end
35
29
  end
@@ -11,7 +11,7 @@ require "securerandom"
11
11
  module PlainApm
12
12
  module Extensions
13
13
  module Context
14
- class Middleware
14
+ class Rack
15
15
  def initialize(app)
16
16
  @app = app
17
17
  end
@@ -21,8 +21,12 @@ module PlainApm
21
21
 
22
22
  status, headers, body = @app.call(env)
23
23
 
24
- body = Rack::BodyProxy.new(body) do
25
- Context.clear!
24
+ body = if defined?(Rack::BodyProxy)
25
+ Rack::BodyProxy.new(body) do
26
+ Context.clear!
27
+ end
28
+ else
29
+ body
26
30
  end
27
31
 
28
32
  processed = true
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "securerandom"
4
+
5
+ ##
6
+ # This code is inspired by request_store gem by Steve Klabnik:
7
+ #
8
+ # https://github.com/steveklabnik/request_store/
9
+ #
10
+ # See LICENSE.txt in the current directory for the license.
11
+ module PlainApm
12
+ module Extensions
13
+ module Context
14
+ class Rack
15
+ def initialize(app)
16
+ @app = app
17
+ end
18
+
19
+ def call(env)
20
+ Context.trace_id = trace_id(env)
21
+
22
+ status, headers, body = @app.call(env)
23
+
24
+ body = Rack::BodyProxy.new(body) do
25
+ Context.clear!
26
+ end
27
+
28
+ processed = true
29
+
30
+ [status, headers, body]
31
+ ensure
32
+ Context.clear! if !processed
33
+ end
34
+
35
+ private
36
+
37
+ def trace_id(env)
38
+ request_id(env) || SecureRandom.uuid
39
+ end
40
+
41
+ def request_id(env)
42
+ env["action_dispatch.request_id"] || env["HTTP_X_REQUEST_ID"]
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -9,12 +9,18 @@
9
9
  module PlainApm
10
10
  module Extensions
11
11
  module Context
12
- class Railtie < Rails::Railtie
13
- initializer "plain_apm.insert_context_middleware" do |app|
14
- if defined?(ActionDispatch::RequestId)
15
- app.config.middleware.insert_after ActionDispatch::RequestId, PlainApm::Extensions::Context::Middleware
16
- else
17
- app.config.middleware.insert_after Rack::MethodOverride, PlainApm::Extensions::Context::Middleware
12
+ if defined?(Rails::Railtie)
13
+ class Railtie < Rails::Railtie
14
+ initializer "plain_apm.initialize_context" do |app|
15
+ ActiveSupport.on_load(:active_job) do |klass|
16
+ klass.prepend(PlainApm::Extensions::Context::ActiveJob)
17
+ end
18
+
19
+ if defined?(ActionDispatch::RequestId)
20
+ app.config.middleware.insert_after ActionDispatch::RequestId, PlainApm::Extensions::Context::Rack
21
+ else
22
+ app.config.middleware.insert_after Rack::MethodOverride, PlainApm::Extensions::Context::Rack
23
+ end
18
24
  end
19
25
  end
20
26
  end
@@ -32,7 +32,7 @@ module PlainApm
32
32
  event["source"] = source
33
33
  event["name"] = "rack_middleware"
34
34
 
35
- PlainApm::Agent.collect(event)
35
+ PlainApm.agent.collect(event)
36
36
  end
37
37
  end
38
38
  end
@@ -3,9 +3,11 @@
3
3
  module PlainApm
4
4
  module Extensions
5
5
  module Exceptions
6
- class Railtie < Rails::Railtie
7
- initializer "plain_apm.insert_exceptions_middleware" do |app|
8
- app.config.middleware.insert(0, PlainApm::Extensions::Exceptions::Rack)
6
+ if defined?(Rails::Railtie)
7
+ class Railtie < Rails::Railtie
8
+ initializer "plain_apm.insert_exceptions_middleware" do |app|
9
+ app.config.middleware.insert(0, PlainApm::Extensions::Exceptions::Rack)
10
+ end
9
11
  end
10
12
  end
11
13
  end
@@ -0,0 +1,31 @@
1
+ module PlainApm
2
+ module Extensions
3
+ module ThreadAllocations
4
+ module ActiveSupportEvent
5
+ def start!
6
+ super
7
+ @thread_allocation_count_start = now_thread_allocations
8
+ end
9
+
10
+ def finish!
11
+ super
12
+ @thread_allocation_count_finish = now_thread_allocations
13
+ end
14
+
15
+ def thread_allocations
16
+ @thread_allocation_count_finish - @thread_allocation_count_start
17
+ end
18
+
19
+ if defined?(PlainApm::ObjectTracing)
20
+ def now_thread_allocations
21
+ PlainApm::ObjectTracing.total_thread_allocated_objects
22
+ end
23
+ else
24
+ def now_thread_allocations
25
+ 0
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,15 @@
1
+ module PlainApm
2
+ module Extensions
3
+ module ThreadAllocations
4
+ if defined?(Rails::Railtie)
5
+ class Railtie < Rails::Railtie
6
+ initializer "plain_apm.thread_allocations_in_active_support_events" do
7
+ ActiveSupport::Notifications::Event.prepend(
8
+ PlainApm::Extensions::ThreadAllocations::ActiveSupportEvent
9
+ )
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -6,6 +6,7 @@ module PlainApm
6
6
 
7
7
  def plain_apm_instrument(name, context = {}, &block)
8
8
  sanitized_name = name.gsub(/\W/, "_").gsub(/(?!^)([A-Z])/) { |m| "_#{m}" }.squeeze("_").downcase
9
+ return unless defined?(ActiveSupport::Notifications)
9
10
  ActiveSupport::Notifications.instrument("#{sanitized_name}.manual_plain_apm", **context, &block)
10
11
  end
11
12
  end
@@ -43,7 +43,7 @@ module PlainApm
43
43
 
44
44
  # strip rails root
45
45
  def identifier(id)
46
- return id unless defined?(Rails) && Rails.root
46
+ return id unless defined?(Rails) && Rails.respond_to?(:root)
47
47
 
48
48
  root = Rails.root.to_s
49
49
 
@@ -23,6 +23,8 @@ module PlainApm
23
23
  case name
24
24
  when "sql"
25
25
  base.merge({"sql" => payload[:sql]})
26
+ when "instantiation"
27
+ base.merge({"class_name" => payload[:class_name], "record_count" => payload[:record_count]})
26
28
  end
27
29
  end
28
30
  end
@@ -6,29 +6,36 @@ module PlainApm
6
6
  include EventAttributes
7
7
 
8
8
  def install
9
- begin
10
- require "active_support/notifications"
11
- rescue LoadError
12
- return
13
- end
9
+ return unless defined?(::ActiveSupport::Notifications)
14
10
 
15
11
  asn = ::ActiveSupport::Notifications
16
12
 
17
- # Rails >= 6.1
18
- if asn.respond_to?(:monotonic_subscribe)
19
- asn.monotonic_subscribe(notification_pattern, method(:collect))
13
+ # Rails 6.0 has a slightly different arity check in the subscriber
14
+ # constructor, so we need to use a proc, method(:collect) won't work.
15
+ # https://github.com/rails/rails/blob/28bb76d3efc39b2ef663dfe2346f7c2621343cd6/activesupport/lib/active_support/notifications/fanout.rb#L93-L100
16
+ # vs
17
+ # https://github.com/rails/rails/blob/7c70791470fc517deb7c640bead9f1b47efb5539/activesupport/lib/active_support/notifications/fanout.rb#L132-L139
18
+ subscriber = proc { |event| collect(event) }
19
+
20
+ # #monotonic_subscribe got added in Rails >= 6.1
21
+ @subscription = if asn.respond_to?(:monotonic_subscribe)
22
+ asn.monotonic_subscribe(notification_pattern, subscriber)
20
23
  else
21
- asn.subscribe(notification_pattern, method(:collect))
24
+ asn.subscribe(notification_pattern, subscriber)
22
25
  end
23
26
  end
24
27
 
28
+ def uninstall
29
+ ::ActiveSupport::Notifications.unsubscribe(@subscription) if @subscription
30
+ end
31
+
25
32
  def collect(event)
26
33
  # id / transaction_id is by instrumenter and thread
27
34
  payload = payload(event)
28
35
 
29
36
  return if payload.nil?
30
37
 
31
- Agent.collect(payload)
38
+ ::PlainApm.agent.collect(payload)
32
39
  end
33
40
 
34
41
  private
@@ -14,12 +14,16 @@ module PlainApm
14
14
  collect
15
15
  end
16
16
 
17
+ def uninstall
18
+ # NOOP
19
+ end
20
+
17
21
  def collect
18
22
  result = git_revision || hg_revision || return
19
23
 
20
24
  _, attrs = attributes_from_deploy(*result)
21
25
 
22
- Agent.collect(attrs)
26
+ ::PlainApm.agent.collect(attrs)
23
27
  end
24
28
 
25
29
  private
@@ -5,12 +5,7 @@ module PlainApm
5
5
  include EventAttributes
6
6
 
7
7
  def install
8
- begin
9
- require "active_support/error_reporter"
10
- require "active_support/lazy_load_hooks"
11
- rescue LoadError
12
- return
13
- end
8
+ return unless defined?(Rails) && Rails.respond_to?(:error)
14
9
 
15
10
  # Install the hook when the app is up. This might miss errors that
16
11
  # happen before that, but that's OK.
@@ -19,6 +14,14 @@ module PlainApm
19
14
  end
20
15
  end
21
16
 
17
+ def uninstall
18
+ return unless defined?(Rails) && Rails.respond_to?(:error)
19
+
20
+ # There's no unsubscribe
21
+ subscribers = Rails.error.instance_variable_get(:@subscribers)
22
+ subscribers&.delete(self)
23
+ end
24
+
22
25
  def collect(e, handled:, severity:, context: {})
23
26
  source, event = attributes_from_exception(e, context)
24
27
 
@@ -27,7 +30,7 @@ module PlainApm
27
30
  event["source"] = source
28
31
  event["name"] = "error_reporter"
29
32
 
30
- PlainApm::Agent.collect(event)
33
+ ::PlainApm.agent.collect(event)
31
34
  end
32
35
 
33
36
  alias_method :report, :collect
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PlainApm
4
- VERSION = "0.7.0"
4
+ VERSION = "0.8.0"
5
5
  end
data/lib/plain_apm.rb CHANGED
@@ -8,27 +8,11 @@ require_relative "plain_apm/event_attributes"
8
8
 
9
9
  require "object_tracing"
10
10
 
11
+ # Deployment reporting.
11
12
  require_relative "plain_apm/hooks/deploy"
12
13
 
13
- # Rails extensions
14
- begin
15
- require "rack/body_proxy"
16
-
17
- require_relative "plain_apm/extensions/context"
18
- require_relative "plain_apm/extensions/context/middleware"
19
- require_relative "plain_apm/extensions/context/active_job" if defined?(ActiveSupport)
20
- require_relative "plain_apm/extensions/context/railtie" if defined?(Rails::Railtie)
21
- require_relative "plain_apm/extensions/thread_allocations"
22
- require_relative "plain_apm/helpers"
23
- rescue LoadError
24
- nil
25
- end
26
-
27
- # Rack exceptions
28
- require_relative "plain_apm/extensions/exceptions/rack"
29
- require_relative "plain_apm/extensions/exceptions/railtie" if defined?(Rails::Railtie)
30
-
31
- # Rails instrumentation
14
+ # Rails instrumentation. The hooks won't install unless
15
+ # ActiveSupport::Notifications is loaded.
32
16
  require_relative "plain_apm/hooks/active_support_subscriber"
33
17
  require_relative "plain_apm/hooks/action_mailer"
34
18
  require_relative "plain_apm/hooks/action_pack"
@@ -39,12 +23,40 @@ require_relative "plain_apm/hooks/active_support"
39
23
  require_relative "plain_apm/hooks/manual"
40
24
  require_relative "plain_apm/hooks/error_reporter"
41
25
 
26
+ # Per thread context for request IDs / job IDs.
27
+ require_relative "plain_apm/extensions/context"
28
+ require_relative "plain_apm/extensions/context/rack"
29
+ require_relative "plain_apm/extensions/context/active_job"
30
+ require_relative "plain_apm/extensions/context/railtie"
31
+
32
+ # Per thread allocations in ASN events
33
+ require_relative "plain_apm/extensions/thread_allocations/active_support_event"
34
+ require_relative "plain_apm/extensions/thread_allocations/railtie"
35
+
36
+ # Helpers du jour.
37
+ require_relative "plain_apm/helpers"
38
+
39
+ # Rack exceptions. Activate the middleware if in Rails.
40
+ require_relative "plain_apm/extensions/exceptions/rack"
41
+ require_relative "plain_apm/extensions/exceptions/railtie"
42
+
42
43
  module PlainApm
43
- if defined?(Rails)
44
+ # Allow swapping out the Agent for a synchronous, in-memory implementation in
45
+ # the tests.
46
+ def self.agent=(agent)
47
+ @@agent = agent
48
+ end
49
+
50
+ def self.agent
51
+ @@agent ||= Agent.instance
52
+ end
53
+
54
+ # after_initialize allows reading settings from ENV on app start.
55
+ if defined?(Rails::Railtie)
44
56
  class Railtie < Rails::Railtie
45
- config.after_initialize { PlainApm::Agent.start }
57
+ config.after_initialize { PlainApm.agent.start }
46
58
  end
47
59
  else
48
- Agent.start
60
+ PlainApm.agent.start
49
61
  end
50
62
  end
metadata CHANGED
@@ -1,71 +1,71 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plain_apm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - PlainAPM Team
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-06 00:00:00.000000000 Z
11
+ date: 2023-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '5.0'
20
20
  type: :development
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: '0'
26
+ version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: standard
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '1.16'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '1.16'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: appraisal
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '2.4'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '2.4'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rake-compiler
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '0'
61
+ version: '1.2'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '0'
68
+ version: '1.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -92,23 +92,23 @@ files:
92
92
  - Gemfile
93
93
  - LICENSE.txt
94
94
  - README.md
95
- - Rakefile
96
95
  - ext/object_tracing/extconf.rb
97
96
  - ext/object_tracing/object_tracing.c
98
97
  - lib/plain_apm.rb
99
98
  - lib/plain_apm/agent.rb
100
- - lib/plain_apm/backoff.rb
101
99
  - lib/plain_apm/config.rb
102
100
  - lib/plain_apm/event_attributes.rb
103
101
  - lib/plain_apm/extensions/context.rb
104
102
  - lib/plain_apm/extensions/context/LICENSE.txt
105
103
  - lib/plain_apm/extensions/context/active_job.rb
106
104
  - lib/plain_apm/extensions/context/middleware.rb
105
+ - lib/plain_apm/extensions/context/rack.rb
107
106
  - lib/plain_apm/extensions/context/railtie.rb
108
107
  - lib/plain_apm/extensions/exceptions/active_job.rb
109
108
  - lib/plain_apm/extensions/exceptions/rack.rb
110
109
  - lib/plain_apm/extensions/exceptions/railtie.rb
111
- - lib/plain_apm/extensions/thread_allocations.rb
110
+ - lib/plain_apm/extensions/thread_allocations/active_support_event.rb
111
+ - lib/plain_apm/extensions/thread_allocations/railtie.rb
112
112
  - lib/plain_apm/helpers.rb
113
113
  - lib/plain_apm/hooks/action_mailer.rb
114
114
  - lib/plain_apm/hooks/action_pack.rb
data/Rakefile DELETED
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "bundler/gem_tasks"
4
- require "appraisal"
5
- require "standard/rake"
6
- require "rake/testtask"
7
- require "rake/extensiontask"
8
-
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << "test"
11
- t.libs << "lib"
12
- t.test_files = FileList["test/**/*_test.rb"]
13
- end
14
-
15
- Rake::ExtensionTask.new("object_tracing")
16
-
17
- namespace :test do
18
- task all: "appraisal:all"
19
- end
20
-
21
- task default: :test
@@ -1,40 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module PlainApm
4
- class Backoff
5
- ##
6
- # Exponential backoff with jitter.
7
-
8
- DEFAULT_BASE_SECONDS = 1.5
9
- DEFAULT_MAX_RETRIES = 10 # sum_0^10 1.5 ** k ~ 170s
10
- DEFAULT_JITTER_MULTIPLIER = 0.2 # % of the current retry interval
11
-
12
- ##
13
- # @param base_seconds [Integer] base of the exponential retry.
14
- # @param max_retries [Integer] maximum retries to perform.
15
- # @param jitter_multiplier [Float] % of the current retry interval to use for jitter.
16
- def initialize(base_seconds: nil, max_retries: nil, jitter_multiplier: nil)
17
- @base_seconds = base_seconds || DEFAULT_BASE_SECONDS
18
- @max_retries = max_retries || DEFAULT_MAX_RETRIES
19
- @jitter_multiplier = jitter_multiplier || DEFAULT_JITTER_MULTIPLIER
20
- end
21
-
22
- ##
23
- # @param retries [Integer] Number of current retry attempts.
24
- #
25
- # @return [Integer|nil] Amount of time slept, or nil if out of retries.
26
- def delay_time(retries:)
27
- return if retries >= max_retries
28
-
29
- base_interval = (base_seconds**retries)
30
- jitter_interval = base_interval * jitter_multiplier
31
-
32
- # The random factor is never -1, but that shouldn't be an issue.
33
- base_interval + jitter_interval * (1.0 - 2.0 * rand)
34
- end
35
-
36
- private
37
-
38
- attr_reader :base_seconds, :max_retries, :jitter_multiplier
39
- end
40
- end
@@ -1,35 +0,0 @@
1
- module PlainApm
2
- module Extensions
3
- module ThreadAllocations
4
- def start!
5
- super
6
- @thread_allocation_count_start = now_thread_allocations
7
- end
8
-
9
- def finish!
10
- super
11
- @thread_allocation_count_finish = now_thread_allocations
12
- end
13
-
14
- def thread_allocations
15
- @thread_allocation_count_finish - @thread_allocation_count_start
16
- end
17
-
18
- private
19
-
20
- if defined?(PlainApm::ObjectTracing)
21
- def now_thread_allocations
22
- PlainApm::ObjectTracing.total_thread_allocated_objects
23
- end
24
- else
25
- def now_thread_allocations
26
- 0
27
- end
28
- end
29
- end
30
-
31
- if defined?(ActiveSupport)
32
- ActiveSupport::Notifications::Event.prepend(PlainApm::Extensions::ThreadAllocations)
33
- end
34
- end
35
- end