rails-profiler 0.36.1 → 0.36.2

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: '0807af8c2469a24ab547cc295678acea816cb51f02a8975fd420d2fd2dfa8311'
4
- data.tar.gz: 6eec3e7dc0245496d254dd72ae1b65247d44cbf6ab107cf79671acbba25cfbf3
3
+ metadata.gz: 425d3e2d7c0c01fc34672541d20f519bf260bd32e19c7ea9100fa5c5d6e43a81
4
+ data.tar.gz: a56c7fb60987d17569b6dfaad5d37068c516e39ed8f73fe260f4ad651c0dcb36
5
5
  SHA512:
6
- metadata.gz: b92743541a4ecd0d12177a813e07a8d0c8ca455f2a9edf468e46f35807d3ebf968053bd0c82a1e565d724bcd8db91f13941abbe13d86d0b42883b305d16eaea1
7
- data.tar.gz: 32c9fbea2e9555b061adb5d27be1816056d974431e69960aa1537f28ab87c2db3cd68b5edfa373943b28dbddec43edfe85497ee729d4bac5d0cdf8739bf7ed2e
6
+ metadata.gz: 1102b3922c690c15f2247343fb6afd9b1ef2d5e5fbe7d79b88affad0b01ae288586f0df29f9049ee8b65385ccf12138365963ca5dbbe1032158dd259f3538d14
7
+ data.tar.gz: 06e26f6bd030fc17d8da158d5e6205d0cbaf426b0545b26ea2bd4cddcf3d4e1e685ab2bd668149cddc63aa4e052bcf25bbde7a120168ba8599f1bd22e7e18cbd
data/CHANGELOG.md CHANGED
@@ -19,6 +19,14 @@ every commit of every tag interval is accounted for one way or the other.
19
19
 
20
20
  ## [Unreleased]
21
21
 
22
+ ## [0.36.2] - 2026-10-18
23
+
24
+ <!-- stamped -->
25
+
26
+ ### Fixed
27
+
28
+ - **Cluster:** the heartbeat thread of a worker no longer keeps the collectors of the request that was running when it was started (a worker forked or restarted mid-request), and no longer records its own HTTP calls into them.
29
+
22
30
  ## [0.36.1] - 2026-10-17
23
31
 
24
32
  <!-- stamped -->
@@ -4,6 +4,7 @@ require "net/http"
4
4
  require "json"
5
5
  require "uri"
6
6
  require_relative "security"
7
+ require_relative "../instrumentation/request_context"
7
8
 
8
9
  module Profiler
9
10
  module Cluster
@@ -105,21 +106,25 @@ module Profiler
105
106
  def start_heartbeat_thread
106
107
  return if @thread&.alive?
107
108
 
108
- @thread = Thread.new do
109
- interval = Profiler.configuration.cluster_heartbeat_interval
110
- loop do
111
- sleep interval
112
- unless @registered
113
- register!
114
- @registered = true
115
- log_info("Re-registered with master after previous failure")
116
- else
117
- heartbeat!
118
- end
119
- rescue => e
120
- @registered = false
121
- log_warn("communication with the master failed, will retry", e)
109
+ # Started from a request thread (a worker forked mid-request, a restart), it must not
110
+ # inherit that request's collectors for the life of the process.
111
+ @thread = Profiler::Instrumentation::RequestContext.detached { Thread.new { heartbeat_loop } }
112
+ end
113
+
114
+ def heartbeat_loop
115
+ interval = Profiler.configuration.cluster_heartbeat_interval
116
+ loop do
117
+ sleep interval
118
+ unless @registered
119
+ register!
120
+ @registered = true
121
+ log_info("Re-registered with master after previous failure")
122
+ else
123
+ heartbeat!
122
124
  end
125
+ rescue => e
126
+ @registered = false
127
+ log_warn("communication with the master failed, will retry", e)
123
128
  end
124
129
  end
125
130
 
@@ -18,6 +18,8 @@ module Profiler
18
18
  profiler_flamegraph_collector
19
19
  ].freeze
20
20
 
21
+ DETACHED_KEY = :profiler_detached_thread
22
+
21
23
  # The files whose code calls Thread.new to create the threads of a pool: concurrent-ruby's
22
24
  # executors (a worker of RubyThreadPoolExecutor, the thread of SimpleExecutorService) and
23
25
  # Puma's thread pool.
@@ -63,6 +65,21 @@ module Profiler
63
65
  wrapper
64
66
  end
65
67
 
68
+ # Runs the block, in which a Thread.new starts a thread of the gem's own that outlives any
69
+ # request (the cluster heartbeat): it gets no context and drops the scope its Fiber storage
70
+ # inherits, so it cannot keep a request's collectors alive for as long as it runs.
71
+ def detached
72
+ previous = Thread.current[DETACHED_KEY]
73
+ Thread.current[DETACHED_KEY] = true
74
+ yield
75
+ ensure
76
+ Thread.current[DETACHED_KEY] = previous
77
+ end
78
+
79
+ def detached?
80
+ Thread.current[DETACHED_KEY] == true
81
+ end
82
+
66
83
  # Whether the thread being created is one of a pool's: then it must not inherit. Only the
67
84
  # code that calls Thread.new counts; a thread the application starts from a task, or from a
68
85
  # request a pool thread serves, is the request's.
@@ -16,6 +16,8 @@ module Profiler
16
16
  # without this the error would never come while a profile is being collected.
17
17
  return super if block.nil?
18
18
 
19
+ return super(*args, &RequestContext.without_inherited(block)) if RequestContext.detached?
20
+
19
21
  context = RequestContext.capture
20
22
  return super if context.nil?
21
23
  return super(*args, &RequestContext.without_inherited(block)) if RequestContext.creating_pool_thread?
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Profiler
4
- VERSION = "0.36.1"
4
+ VERSION = "0.36.2"
5
5
 
6
6
  GEM_ROOT = File.expand_path("../..", __dir__)
7
7
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-profiler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.36.1
4
+ version: 0.36.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sébastien Duplessy
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-10-17 00:00:00.000000000 Z
11
+ date: 2026-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails