async-utilization 0.3.2 → 0.4.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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/async/utilization/metric.rb +8 -5
- data/lib/async/utilization/namespace.rb +51 -0
- data/lib/async/utilization/registry.rb +15 -50
- data/lib/async/utilization/version.rb +1 -1
- data/lib/async/utilization.rb +1 -0
- data/readme.md +21 -0
- data/releases.md +5 -0
- data/test/async/utilization/namespace.rb +53 -0
- data/test/async/utilization/registry.rb +24 -15
- data.tar.gz.sig +0 -0
- metadata +4 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 522f4b5822343c23f14422555147e2159e2bac50afbd230a06e985e2cfe1cee4
|
|
4
|
+
data.tar.gz: caa61db8daf6f65a77e319a210ee0079f9a647deed614e7cc5333507967964fa
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ebaabb2e0959e3664e4e2a18812d71efa75d967a2fb01a89f8d63af02eb9e36bc564edfc50c7315b4efbbe8ee5f60e865250cb660daa274fa185e6a538994f6c
|
|
7
|
+
data.tar.gz: 7760f55b1383998120a3f7bf0b65b578c8da04bf648c0407f6b3e57040edec2b1487b82356f6d11eaf3bdb02cab9ddc8797eb3c8ee67c930a03d35fec08a5e60
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
|
@@ -38,11 +38,14 @@ module Async
|
|
|
38
38
|
# @attribute [Symbol] The field name for this metric.
|
|
39
39
|
attr :name
|
|
40
40
|
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
# Get the current in-memory metric value.
|
|
42
|
+
#
|
|
43
|
+
# @returns [Numeric] The last value written to this metric.
|
|
44
|
+
def value
|
|
45
|
+
@guard.synchronize do
|
|
46
|
+
@value
|
|
47
|
+
end
|
|
48
|
+
end
|
|
46
49
|
|
|
47
50
|
# Set the observer and rebuild cache.
|
|
48
51
|
#
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
module Async
|
|
7
|
+
module Utilization
|
|
8
|
+
# A registry-like view that prefixes metric names.
|
|
9
|
+
#
|
|
10
|
+
# Namespaces let components use generic metric names while applications decide
|
|
11
|
+
# how those names are composed in the shared registry.
|
|
12
|
+
class Namespace
|
|
13
|
+
# Initialize a new namespace.
|
|
14
|
+
#
|
|
15
|
+
# @parameter registry [Registry] The underlying registry.
|
|
16
|
+
# @parameter name [Symbol] The namespace name.
|
|
17
|
+
def initialize(registry, name)
|
|
18
|
+
@registry = registry
|
|
19
|
+
@name = name.to_sym
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# @attribute [Registry] The underlying registry.
|
|
23
|
+
attr :registry
|
|
24
|
+
|
|
25
|
+
# @attribute [Symbol] The namespace name.
|
|
26
|
+
attr :name
|
|
27
|
+
|
|
28
|
+
# Get a metric in this namespace.
|
|
29
|
+
#
|
|
30
|
+
# @parameter name [Symbol] The metric name.
|
|
31
|
+
# @returns [Metric] A metric instance for the namespaced field.
|
|
32
|
+
def metric(name)
|
|
33
|
+
@registry.metric(metric_name(name))
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Get a nested namespace.
|
|
37
|
+
#
|
|
38
|
+
# @parameter name [Symbol] The nested namespace name.
|
|
39
|
+
# @returns [Namespace] A namespace view with the composed name.
|
|
40
|
+
def namespace(name)
|
|
41
|
+
self.class.new(@registry, metric_name(name))
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def metric_name(name)
|
|
47
|
+
:"#{@name}_#{name}"
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
# Copyright, 2026, by Samuel Williams.
|
|
5
5
|
|
|
6
6
|
require "console"
|
|
7
|
+
require_relative "namespace"
|
|
7
8
|
|
|
8
9
|
module Async
|
|
9
10
|
module Utilization
|
|
@@ -22,9 +23,11 @@ module Async
|
|
|
22
23
|
# @example Create a registry and emit metrics:
|
|
23
24
|
# registry = Async::Utilization::Registry.new
|
|
24
25
|
#
|
|
25
|
-
#
|
|
26
|
-
#
|
|
27
|
-
#
|
|
26
|
+
# total_requests = registry.metric(:total_requests)
|
|
27
|
+
# total_requests.increment
|
|
28
|
+
#
|
|
29
|
+
# active_requests = registry.metric(:active_requests)
|
|
30
|
+
# active_requests.track do
|
|
28
31
|
# # Handle request - auto-decrements when block completes
|
|
29
32
|
# end
|
|
30
33
|
#
|
|
@@ -37,7 +40,6 @@ module Async
|
|
|
37
40
|
# observer = Async::Utilization::Observer.open(schema, "/path/to/shm", 4096, 0)
|
|
38
41
|
# registry.observer = observer
|
|
39
42
|
class Registry
|
|
40
|
-
|
|
41
43
|
# Initialize a new registry.
|
|
42
44
|
def initialize
|
|
43
45
|
@observer = nil
|
|
@@ -49,15 +51,12 @@ module Async
|
|
|
49
51
|
# @attribute [Object | Nil] The registered observer.
|
|
50
52
|
attr :observer
|
|
51
53
|
|
|
52
|
-
# @attribute [Mutex] The mutex for thread safety.
|
|
53
|
-
attr :guard
|
|
54
|
-
|
|
55
54
|
# Get the current values for all metrics.
|
|
56
55
|
#
|
|
57
56
|
# @returns [Hash] Hash mapping field names to their current values.
|
|
58
57
|
def values
|
|
59
58
|
@metrics.transform_values do |metric|
|
|
60
|
-
metric.
|
|
59
|
+
metric.value
|
|
61
60
|
end
|
|
62
61
|
end
|
|
63
62
|
|
|
@@ -79,48 +78,6 @@ module Async
|
|
|
79
78
|
|
|
80
79
|
# Console.info(self, "Observer assigned", observer: observer, metric_count: @metrics.size)
|
|
81
80
|
end
|
|
82
|
-
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
# Set a field value.
|
|
86
|
-
#
|
|
87
|
-
# Delegates to the metric instance for the given field.
|
|
88
|
-
#
|
|
89
|
-
# @parameter field [Symbol] The field name to set.
|
|
90
|
-
# @parameter value [Numeric] The value to set.
|
|
91
|
-
def set(field, value)
|
|
92
|
-
metric(field).set(value)
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
# Increment a field value.
|
|
96
|
-
#
|
|
97
|
-
# Delegates to the metric instance for the given field.
|
|
98
|
-
#
|
|
99
|
-
# @parameter field [Symbol] The field name to increment.
|
|
100
|
-
# @returns [Integer] The new value of the field.
|
|
101
|
-
def increment(field)
|
|
102
|
-
metric(field).increment
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# Track an operation: increment before the block, decrement after it completes.
|
|
106
|
-
#
|
|
107
|
-
# Delegates to the metric instance for the given field.
|
|
108
|
-
#
|
|
109
|
-
# @parameter field [Symbol] The field name to track.
|
|
110
|
-
# @yield The operation to track.
|
|
111
|
-
# @returns [Object] The block's return value.
|
|
112
|
-
def track(field, &block)
|
|
113
|
-
metric(field).track(&block)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
# Decrement a field value.
|
|
117
|
-
#
|
|
118
|
-
# Delegates to the metric instance for the given field.
|
|
119
|
-
#
|
|
120
|
-
# @parameter field [Symbol] The field name to decrement.
|
|
121
|
-
# @returns [Integer] The new value of the field.
|
|
122
|
-
def decrement(field)
|
|
123
|
-
metric(field).decrement
|
|
124
81
|
end
|
|
125
82
|
|
|
126
83
|
# Get a cached metric reference for a field.
|
|
@@ -137,6 +94,14 @@ module Async
|
|
|
137
94
|
@metrics[field] ||= Metric.for(field, @observer)
|
|
138
95
|
end
|
|
139
96
|
end
|
|
97
|
+
|
|
98
|
+
# Get a namespace view of this registry.
|
|
99
|
+
#
|
|
100
|
+
# @parameter name [Symbol] The namespace name.
|
|
101
|
+
# @returns [Namespace] A registry-like namespace view.
|
|
102
|
+
def namespace(name)
|
|
103
|
+
Namespace.new(self, name)
|
|
104
|
+
end
|
|
140
105
|
end
|
|
141
106
|
end
|
|
142
107
|
end
|
data/lib/async/utilization.rb
CHANGED
data/readme.md
CHANGED
|
@@ -14,6 +14,11 @@ Please see the [project documentation](https://socketry.github.io/async-utilizat
|
|
|
14
14
|
|
|
15
15
|
Please see the [project releases](https://socketry.github.io/async-utilization/releases/index) for all releases.
|
|
16
16
|
|
|
17
|
+
### v0.4.0
|
|
18
|
+
|
|
19
|
+
- Add `Async::Utilization::Namespace` for composing registry metric names.
|
|
20
|
+
- `Async::Utilization::Metric` is the primary interface, remove `#set`, `#increment`, `#decrement` and `#track` from `Registry`.
|
|
21
|
+
|
|
17
22
|
### v0.3.2
|
|
18
23
|
|
|
19
24
|
- Better observer state handling.
|
|
@@ -40,6 +45,22 @@ We welcome contributions to this project.
|
|
|
40
45
|
4. Push to the branch (`git push origin my-new-feature`).
|
|
41
46
|
5. Create new Pull Request.
|
|
42
47
|
|
|
48
|
+
### Running Tests
|
|
49
|
+
|
|
50
|
+
To run the test suite:
|
|
51
|
+
|
|
52
|
+
``` shell
|
|
53
|
+
bundle exec sus
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Making Releases
|
|
57
|
+
|
|
58
|
+
To make a new release:
|
|
59
|
+
|
|
60
|
+
``` shell
|
|
61
|
+
bundle exec bake gem:release:patch # or minor or major
|
|
62
|
+
```
|
|
63
|
+
|
|
43
64
|
### Developer Certificate of Origin
|
|
44
65
|
|
|
45
66
|
In order to protect users of this project, we require all contributors to comply with the [Developer Certificate of Origin](https://developercertificate.org/). This ensures that all contributions are properly licensed and attributed.
|
data/releases.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Releases
|
|
2
2
|
|
|
3
|
+
## v0.4.0
|
|
4
|
+
|
|
5
|
+
- Add `Async::Utilization::Namespace` for composing registry metric names.
|
|
6
|
+
- `Async::Utilization::Metric` is the primary interface, remove `#set`, `#increment`, `#decrement` and `#track` from `Registry`.
|
|
7
|
+
|
|
3
8
|
## v0.3.2
|
|
4
9
|
|
|
5
10
|
- Better observer state handling.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Released under the MIT License.
|
|
4
|
+
# Copyright, 2026, by Samuel Williams.
|
|
5
|
+
|
|
6
|
+
require "sus"
|
|
7
|
+
require "async/utilization"
|
|
8
|
+
|
|
9
|
+
describe Async::Utilization::Namespace do
|
|
10
|
+
let(:registry) {Async::Utilization::Registry.new}
|
|
11
|
+
let(:namespace) {registry.namespace(:socket_accept)}
|
|
12
|
+
|
|
13
|
+
it "uses namespaced metric names" do
|
|
14
|
+
metric = namespace.metric(:acquired_count)
|
|
15
|
+
|
|
16
|
+
expect(metric).to be_a(Async::Utilization::Metric)
|
|
17
|
+
expect(metric.name).to be == :socket_accept_acquired_count
|
|
18
|
+
|
|
19
|
+
metric.set(2)
|
|
20
|
+
expect(registry.values).to have_keys(socket_accept_acquired_count: be == 2)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "returns the same metric instance for the same namespaced field" do
|
|
24
|
+
metric1 = namespace.metric(:waiting_count)
|
|
25
|
+
metric2 = namespace.metric(:waiting_count)
|
|
26
|
+
|
|
27
|
+
expect(metric1).to be == metric2
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "supports nested namespaces" do
|
|
31
|
+
metric = namespace.namespace(:long_task).metric(:waiting_count)
|
|
32
|
+
|
|
33
|
+
expect(metric.name).to be == :socket_accept_long_task_waiting_count
|
|
34
|
+
|
|
35
|
+
metric.increment
|
|
36
|
+
expect(registry.values).to have_keys(socket_accept_long_task_waiting_count: be == 1)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "writes namespaced metrics to an observer" do
|
|
40
|
+
schema = Async::Utilization::Schema.build(socket_accept_acquired_count: :u64)
|
|
41
|
+
buffer = IO::Buffer.new(8)
|
|
42
|
+
|
|
43
|
+
observer = Object.new
|
|
44
|
+
observer.define_singleton_method(:schema){schema}
|
|
45
|
+
observer.define_singleton_method(:buffer){buffer}
|
|
46
|
+
|
|
47
|
+
registry.observer = observer
|
|
48
|
+
|
|
49
|
+
namespace.metric(:acquired_count).set(5)
|
|
50
|
+
|
|
51
|
+
expect(buffer.get_value(:u64, 0)).to be == 5
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -8,37 +8,38 @@ require "async/utilization"
|
|
|
8
8
|
|
|
9
9
|
describe Async::Utilization::Registry do
|
|
10
10
|
let(:registry) {Async::Utilization::Registry.new}
|
|
11
|
+
let(:test_field_metric) {registry.metric(:test_field)}
|
|
11
12
|
|
|
12
13
|
it "can increment a value" do
|
|
13
|
-
value =
|
|
14
|
+
value = test_field_metric.increment
|
|
14
15
|
expect(value).to be == 1
|
|
15
16
|
expect(registry.values[:test_field]).to be == 1
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
it "can increment multiple times" do
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
test_field_metric.increment
|
|
21
|
+
test_field_metric.increment
|
|
22
|
+
test_field_metric.increment
|
|
22
23
|
|
|
23
24
|
expect(registry.values[:test_field]).to be == 3
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
it "can decrement a value" do
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
test_field_metric.increment
|
|
29
|
+
test_field_metric.increment
|
|
29
30
|
|
|
30
|
-
value =
|
|
31
|
+
value = test_field_metric.decrement
|
|
31
32
|
expect(value).to be == 1
|
|
32
33
|
expect(registry.values[:test_field]).to be == 1
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
it "can set a value directly" do
|
|
36
|
-
|
|
37
|
+
test_field_metric.set(42)
|
|
37
38
|
expect(registry.values[:test_field]).to be == 42
|
|
38
39
|
end
|
|
39
40
|
|
|
40
41
|
it "can track an operation with auto-decrement" do
|
|
41
|
-
|
|
42
|
+
test_field_metric.track do
|
|
42
43
|
expect(registry.values[:test_field]).to be == 1
|
|
43
44
|
end
|
|
44
45
|
|
|
@@ -47,7 +48,7 @@ describe Async::Utilization::Registry do
|
|
|
47
48
|
|
|
48
49
|
it "decrements even if track block raises an error" do
|
|
49
50
|
begin
|
|
50
|
-
|
|
51
|
+
test_field_metric.track do
|
|
51
52
|
raise "Error!"
|
|
52
53
|
end
|
|
53
54
|
rescue
|
|
@@ -64,13 +65,13 @@ describe Async::Utilization::Registry do
|
|
|
64
65
|
observer.define_singleton_method(:schema){schema}
|
|
65
66
|
observer.define_singleton_method(:buffer){buffer}
|
|
66
67
|
|
|
67
|
-
|
|
68
|
+
test_field_metric.set(5)
|
|
68
69
|
registry.observer = observer
|
|
69
70
|
|
|
70
71
|
# Buffer should be synced with the existing value on observer assignment
|
|
71
72
|
expect(buffer.get_value(:u64, 0)).to be == 5
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
test_field_metric.increment
|
|
74
75
|
|
|
75
76
|
# Buffer should reflect the incremented value
|
|
76
77
|
expect(buffer.get_value(:u64, 0)).to be == 6
|
|
@@ -83,6 +84,14 @@ describe Async::Utilization::Registry do
|
|
|
83
84
|
expect(registry.values).to have_keys(module_test: be == 2)
|
|
84
85
|
end
|
|
85
86
|
|
|
87
|
+
it "can create a namespace" do
|
|
88
|
+
namespace = registry.namespace(:socket_accept)
|
|
89
|
+
|
|
90
|
+
expect(namespace).to be_a(Async::Utilization::Namespace)
|
|
91
|
+
expect(namespace.registry).to be == registry
|
|
92
|
+
expect(namespace.name).to be == :socket_accept
|
|
93
|
+
end
|
|
94
|
+
|
|
86
95
|
it "can use metric for decrement" do
|
|
87
96
|
registry.metric(:module_decrement_test).increment
|
|
88
97
|
registry.metric(:module_decrement_test).increment
|
|
@@ -104,7 +113,7 @@ describe Async::Utilization::Registry do
|
|
|
104
113
|
observer.define_singleton_method(:schema){schema}
|
|
105
114
|
observer.define_singleton_method(:buffer){buffer}
|
|
106
115
|
|
|
107
|
-
|
|
116
|
+
test_field_metric.set(7)
|
|
108
117
|
registry.observer = observer
|
|
109
118
|
|
|
110
119
|
expect(buffer.get_value(:u64, 0)).to be == 7
|
|
@@ -118,11 +127,11 @@ describe Async::Utilization::Registry do
|
|
|
118
127
|
observer.define_singleton_method(:buffer){buffer}
|
|
119
128
|
|
|
120
129
|
registry.observer = observer
|
|
121
|
-
|
|
130
|
+
test_field_metric.set(5)
|
|
122
131
|
expect(buffer.get_value(:u64, 0)).to be == 5
|
|
123
132
|
|
|
124
133
|
registry.observer = nil
|
|
125
|
-
|
|
134
|
+
test_field_metric.set(99)
|
|
126
135
|
|
|
127
136
|
# Buffer unchanged, in-memory value updated
|
|
128
137
|
expect(buffer.get_value(:u64, 0)).to be == 5
|
data.tar.gz.sig
CHANGED
|
Binary file
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: async-utilization
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Samuel Williams
|
|
@@ -58,6 +58,7 @@ extra_rdoc_files: []
|
|
|
58
58
|
files:
|
|
59
59
|
- lib/async/utilization.rb
|
|
60
60
|
- lib/async/utilization/metric.rb
|
|
61
|
+
- lib/async/utilization/namespace.rb
|
|
61
62
|
- lib/async/utilization/observer.rb
|
|
62
63
|
- lib/async/utilization/registry.rb
|
|
63
64
|
- lib/async/utilization/schema.rb
|
|
@@ -67,6 +68,7 @@ files:
|
|
|
67
68
|
- releases.md
|
|
68
69
|
- test/async/utilization.rb
|
|
69
70
|
- test/async/utilization/metric.rb
|
|
71
|
+
- test/async/utilization/namespace.rb
|
|
70
72
|
- test/async/utilization/observer.rb
|
|
71
73
|
- test/async/utilization/registry.rb
|
|
72
74
|
- test/async/utilization/schema.rb
|
|
@@ -90,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
90
92
|
- !ruby/object:Gem::Version
|
|
91
93
|
version: '0'
|
|
92
94
|
requirements: []
|
|
93
|
-
rubygems_version: 4.0.
|
|
95
|
+
rubygems_version: 4.0.6
|
|
94
96
|
specification_version: 4
|
|
95
97
|
summary: High-performance utilization metrics for Async services using shared memory.
|
|
96
98
|
test_files: []
|
metadata.gz.sig
CHANGED
|
Binary file
|