async-service-supervisor 0.16.0 → 0.18.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: 5d6f60f666c3e162c85ca9a275a74dd74dc2219230950d18a0ecf08cffa5761a
4
- data.tar.gz: 2c78c20413ca658e6f2341999bfe42fc1600028978ab134ea10f0b0bed5ac44c
3
+ metadata.gz: 6a0086a1c1f5816a02f4d611debc76dbb5ca57d61add0ae50c95a5c94169b268
4
+ data.tar.gz: '07742320659e85f1931e75929de111362d503ec3e1f32cda7c4971d0459a95d0'
5
5
  SHA512:
6
- metadata.gz: c4f862fdaeef651d0b736381340277720b987ac70a3f2e32481a636c638a251f30f5340da9f9789938eb4c7e25b9188b1e3f83c86ae0846f2620d23c9e69365f
7
- data.tar.gz: 59291a5fe82bd9dbd2b42ef041b2cde87648666c787c99c90725b88576c0484e759c11fdd6a23ce8d58ce4666f6d21e9258065a2af870f040ab74cbccf15d50a
6
+ metadata.gz: d67c02d1a93dbda316a5656f832a14337e528d9532bffe28fe78bddd6fadde1181bd7dce9c164c5c602654dd29d3826c370edfd54fe4c4a54179813cb6d35af5
7
+ data.tar.gz: ad9a517628238cd27c72f5bbf3fcd044eda810b39745faa7c455cfa8cc4f2af24807ad5ecb86d597cd96b0d10b92061f33c8357851b2dd608ea7facaf792f057
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1,3 @@
1
- �2뷢��
2
- �-��ˆ���� ��A , �����W}�)NS��8
1
+ �v]���s,�[��*�qC�jL�a+��G� �p��0�Kk��>%Up ���ig8,�o���
2
+ )�p\��hVk�n�b���7�V�U�!^�X�
3
+ ��**�|H��԰]�ZR/�(�u}؁� 8?G��������Qh
@@ -56,12 +56,15 @@ module Async
56
56
  end
57
57
 
58
58
  # The supervised worker for the current process.
59
+ # @parameter state [Hash | Nil] Additional state to register with the supervisor.
59
60
  # @returns [Worker] The worker client.
60
- def supervisor_worker
61
+ def supervisor_worker(state: nil)
62
+ state = self.supervisor_worker_state.merge(state || {})
63
+
61
64
  Worker.new(
62
65
  process_id: Process.pid,
63
66
  endpoint: supervisor_endpoint,
64
- state: self.supervisor_worker_state,
67
+ state: state,
65
68
  utilization_schema: self.utilization_schema,
66
69
  utilization_registry: self.utilization_registry,
67
70
  )
@@ -70,11 +73,12 @@ module Async
70
73
  # Create a supervised worker for the given instance.
71
74
  #
72
75
  # @parameter instance [Async::Container::Instance] The container instance.
76
+ # @parameter state [Hash | Nil] Additional state to register with the supervisor.
73
77
  # @returns [Worker] The worker client.
74
- def prepare!(instance)
78
+ def prepare!(instance, state: nil)
75
79
  super(instance)
76
80
 
77
- supervisor_worker.run
81
+ supervisor_worker(state: state).run
78
82
  end
79
83
  end
80
84
  end
@@ -277,10 +277,10 @@ module Async
277
277
  :utilization_monitor
278
278
  end
279
279
 
280
- # Serialize utilization data for JSON.
280
+ # Sample aggregated utilization data.
281
281
  #
282
282
  # @returns [Hash] Hash mapping service names to aggregated utilization metrics.
283
- def as_json
283
+ def sample
284
284
  @guard.synchronize do
285
285
  aggregated = {}
286
286
 
@@ -313,6 +313,13 @@ module Async
313
313
  end
314
314
  end
315
315
 
316
+ # Serialize utilization data for JSON.
317
+ #
318
+ # @returns [Hash] Hash mapping service names to aggregated utilization metrics.
319
+ def as_json
320
+ self.sample
321
+ end
322
+
316
323
  # Emit the utilization metrics.
317
324
  #
318
325
  # @parameter status [Hash] The utilization metrics.
@@ -9,7 +9,7 @@ module Async
9
9
  module Service
10
10
  # @namespace
11
11
  module Supervisor
12
- VERSION = "0.16.0"
12
+ VERSION = "0.18.0"
13
13
  end
14
14
  end
15
15
  end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "metrics/provider"
7
+
8
+ require_relative "../../../../../async/service/supervisor/process_monitor"
9
+
10
+ class Async::Service::Supervisor::ProcessMonitor
11
+ Metrics::Provider(self) do
12
+ PROCESS_METRICS_GENERAL_PROCESSOR_UTILIZATION = Metrics.metric("process.metrics.general.processor_utilization", :gauge, description: "Processor utilization for a supervised process.")
13
+ PROCESS_METRICS_GENERAL_TOTAL_SIZE = Metrics.metric("process.metrics.general.total_size", :gauge, description: "Total memory size for a supervised process.", unit: "bytes")
14
+ PROCESS_METRICS_GENERAL_VIRTUAL_SIZE = Metrics.metric("process.metrics.general.virtual_size", :gauge, description: "Virtual memory size for a supervised process.", unit: "bytes")
15
+ PROCESS_METRICS_GENERAL_RESIDENT_SIZE = Metrics.metric("process.metrics.general.resident_size", :gauge, description: "Resident memory size for a supervised process.", unit: "bytes")
16
+
17
+ def emit(metrics)
18
+ metrics.each_value do |general|
19
+ if value = general[:processor_utilization]
20
+ PROCESS_METRICS_GENERAL_PROCESSOR_UTILIZATION.emit(value)
21
+ end
22
+
23
+ if value = general[:total_size]
24
+ PROCESS_METRICS_GENERAL_TOTAL_SIZE.emit(value)
25
+ end
26
+
27
+ if value = general[:virtual_size]
28
+ PROCESS_METRICS_GENERAL_VIRTUAL_SIZE.emit(value)
29
+ end
30
+
31
+ if value = general[:resident_size]
32
+ PROCESS_METRICS_GENERAL_RESIDENT_SIZE.emit(value)
33
+ end
34
+ end
35
+
36
+ super
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "metrics/provider"
7
+ require "metrics/tags"
8
+
9
+ require_relative "../../../../../async/service/supervisor/utilization_monitor"
10
+
11
+ class Async::Service::Supervisor::UtilizationMonitor
12
+ Metrics::Provider(self) do
13
+ UTILIZATION = Metrics.metric("async.utilization", :gauge, description: "Active requests per worker.")
14
+ UTILIZATION_CONNECTIONS_ACTIVE = Metrics.metric("async.utilization.connections.active", :gauge, description: "The number of active connections.")
15
+ UTILIZATION_CONNECTIONS_TOTAL = Metrics.metric("async.utilization.connections.total", :gauge, description: "The total number of connections.")
16
+ UTILIZATION_REQUESTS_ACTIVE = Metrics.metric("async.utilization.requests.active", :gauge, description: "The number of active requests.")
17
+ UTILIZATION_REQUESTS_TOTAL = Metrics.metric("async.utilization.requests.total", :gauge, description: "The total number of requests.")
18
+ UTILIZATION_WORKERS = Metrics.metric("async.utilization.workers", :gauge, description: "The number of workers contributing utilization metrics.")
19
+
20
+ def emit(metrics)
21
+ metrics.each do |service_name, fields|
22
+ tags = Metrics::Tags.normalize(service: service_name)
23
+
24
+ if connections_active = fields[:connections_active]
25
+ UTILIZATION_CONNECTIONS_ACTIVE.emit(connections_active, tags: tags)
26
+ end
27
+
28
+ if connections_total = fields[:connections_total]
29
+ UTILIZATION_CONNECTIONS_TOTAL.emit(connections_total, tags: tags)
30
+ end
31
+
32
+ if requests_active = fields[:requests_active]
33
+ UTILIZATION_REQUESTS_ACTIVE.emit(requests_active, tags: tags)
34
+ end
35
+
36
+ if requests_total = fields[:requests_total]
37
+ UTILIZATION_REQUESTS_TOTAL.emit(requests_total, tags: tags)
38
+ end
39
+
40
+ if worker_count = fields[:worker_count]
41
+ UTILIZATION_WORKERS.emit(worker_count, tags: tags)
42
+
43
+ if worker_count > 0 and requests_active = fields[:requests_active]
44
+ UTILIZATION.emit(requests_active.to_f / worker_count, tags: tags)
45
+ end
46
+ end
47
+ end
48
+
49
+ super
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require_relative "supervisor/process_monitor"
7
+ require_relative "supervisor/utilization_monitor"
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "traces/provider"
7
+
8
+ require_relative "../../../../../async/service/supervisor/server"
9
+
10
+ Traces::Provider(Async::Service::Supervisor::Server) do
11
+ def remove(controller)
12
+ return super unless controller.id
13
+
14
+ attributes = {
15
+ "worker.id" => controller.id,
16
+ "worker.process_id" => controller.process_id,
17
+ "service.name" => controller.state[:name],
18
+ "monitor.count" => @monitors.size,
19
+ }
20
+
21
+ Traces.trace("async.service.supervisor.worker.remove", attributes: attributes) do
22
+ super
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require "traces/provider"
7
+
8
+ require_relative "../../../../../async/service/supervisor/supervisor_controller"
9
+
10
+ Traces::Provider(Async::Service::Supervisor::SupervisorController) do
11
+ def register(worker, process_id:, state: {})
12
+ attributes = {
13
+ "worker.process_id" => process_id,
14
+ "service.name" => state[:name],
15
+ "monitor.count" => @server.monitors.size,
16
+ }
17
+
18
+ Traces.trace("async.service.supervisor.worker.register", attributes: attributes) do |span|
19
+ super.tap do |id|
20
+ span["worker.id"] = id
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require_relative "supervisor/server"
7
+ require_relative "supervisor/supervisor_controller"
data/readme.md CHANGED
@@ -28,6 +28,14 @@ Please see the [project documentation](https://socketry.github.io/async-service-
28
28
 
29
29
  Please see the [project releases](https://socketry.github.io/async-service-supervisor/releases/index) for all releases.
30
30
 
31
+ ### v0.18.0
32
+
33
+ - Allow supervised services to merge additional worker state during preparation and worker construction.
34
+
35
+ ### v0.17.0
36
+
37
+ - Add opt-in `metrics` and `traces` providers for supervisor process metrics, utilization metrics, and worker lifecycle tracing.
38
+
31
39
  ### v0.16.0
32
40
 
33
41
  - Add `ProcessMonitor#emit(metrics)` as an override point for subclasses to consume captured process metrics (e.g. emitting StatsD gauges).
@@ -65,17 +73,6 @@ Please see the [project releases](https://socketry.github.io/async-service-super
65
73
  - Add support for `Memory::Leak::Cluster` `free_size_minimum:` option.
66
74
  - Remove extraneous "Memory leak detected\!" logs.
67
75
 
68
- ### v0.9.1
69
-
70
- - Close `Call` queue if asynchronous call fails during dispatch - further messages will fail with `ClosedQueueError`.
71
-
72
- ### v0.9.0
73
-
74
- - Better handling of write failures in `Connection::Call.dispatch`, ensuring we don't leak calls.
75
- - Robust monitor loop handling - restart on failure, and align loop iterations.
76
- - Disable memory sampler by default and use text output format.
77
- - Introduce support for redirecting dump output to logs.
78
-
79
76
  ## Contributing
80
77
 
81
78
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Releases
2
2
 
3
+ ## v0.18.0
4
+
5
+ - Allow supervised services to merge additional worker state during preparation and worker construction.
6
+
7
+ ## v0.17.0
8
+
9
+ - Add opt-in `metrics` and `traces` providers for supervisor process metrics, utilization metrics, and worker lifecycle tracing.
10
+
3
11
  ## v0.16.0
4
12
 
5
13
  - Add `ProcessMonitor#emit(metrics)` as an override point for subclasses to consume captured process metrics (e.g. emitting StatsD gauges).
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-service-supervisor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -176,6 +176,12 @@ files:
176
176
  - lib/async/service/supervisor/version.rb
177
177
  - lib/async/service/supervisor/worker.rb
178
178
  - lib/async/service/supervisor/worker_controller.rb
179
+ - lib/metrics/provider/async/service/supervisor.rb
180
+ - lib/metrics/provider/async/service/supervisor/process_monitor.rb
181
+ - lib/metrics/provider/async/service/supervisor/utilization_monitor.rb
182
+ - lib/traces/provider/async/service/supervisor.rb
183
+ - lib/traces/provider/async/service/supervisor/server.rb
184
+ - lib/traces/provider/async/service/supervisor/supervisor_controller.rb
179
185
  - license.md
180
186
  - readme.md
181
187
  - releases.md
@@ -199,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
199
205
  - !ruby/object:Gem::Version
200
206
  version: '0'
201
207
  requirements: []
202
- rubygems_version: 4.0.6
208
+ rubygems_version: 4.0.10
203
209
  specification_version: 4
204
210
  summary: A supervisor for managing multiple container processes.
205
211
  test_files: []
metadata.gz.sig CHANGED
Binary file