async-service-supervisor 0.16.0 → 0.17.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: df5a5c251964d3435c184c712d4ccc2aa8c74a255d78f3632669a1a527ce78af
4
+ data.tar.gz: ea832f3d1e9136ccca58f5c5025fe180de773389a739d9b0ad99aae453df2ee2
5
5
  SHA512:
6
- metadata.gz: c4f862fdaeef651d0b736381340277720b987ac70a3f2e32481a636c638a251f30f5340da9f9789938eb4c7e25b9188b1e3f83c86ae0846f2620d23c9e69365f
7
- data.tar.gz: 59291a5fe82bd9dbd2b42ef041b2cde87648666c787c99c90725b88576c0484e759c11fdd6a23ce8d58ce4666f6d21e9258065a2af870f040ab74cbccf15d50a
6
+ metadata.gz: f54af527ecda8c37129a39f6061095cbaf66b47eec102fd21c1aecb9e5791f487c3d48f567f0a0898a7168ba33bc3a60eef18f7fc1beb656640ce53e3b5f02ed
7
+ data.tar.gz: a9e0b9c6e8a489665d72ed11b0af0eeca18fa7256bfbcdf9d7bef364554fcd219a15c1dbae49d073d8631a92ca023c689f91936444630198b596fcf2eae110dc
checksums.yaml.gz.sig CHANGED
Binary file
@@ -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.17.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,10 @@ 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.17.0
32
+
33
+ - Add opt-in `metrics` and `traces` providers for supervisor process metrics, utilization metrics, and worker lifecycle tracing.
34
+
31
35
  ### v0.16.0
32
36
 
33
37
  - Add `ProcessMonitor#emit(metrics)` as an override point for subclasses to consume captured process metrics (e.g. emitting StatsD gauges).
@@ -69,13 +73,6 @@ Please see the [project releases](https://socketry.github.io/async-service-super
69
73
 
70
74
  - Close `Call` queue if asynchronous call fails during dispatch - further messages will fail with `ClosedQueueError`.
71
75
 
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,9 @@
1
1
  # Releases
2
2
 
3
+ ## v0.17.0
4
+
5
+ - Add opt-in `metrics` and `traces` providers for supervisor process metrics, utilization metrics, and worker lifecycle tracing.
6
+
3
7
  ## v0.16.0
4
8
 
5
9
  - 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.17.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