deployangel 0.1.1 → 0.1.3
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
- data/CHANGELOG.md +15 -0
- data/README.md +9 -2
- data/lib/deployangel/agent.rb +11 -5
- data/lib/deployangel/core/transport.rb +19 -9
- data/lib/deployangel/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5169af9bd2d83ec8ec1446d4ddf641a8908428bc8d50be14fc124a76cfdca936
|
|
4
|
+
data.tar.gz: 466bff7d697f32e27362394130e2e1e0fc0f4e7c62a098740b3c38598443b0fe
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5be25747e622d3556d6f2b6d04351f1d3402f910045ad36e15b1e181b393955acee510906c37abafde57f7cfdde4b41d4742bcf6bcf6e90c549914a033f1205d
|
|
7
|
+
data.tar.gz: ed4075d93e23c0a96b813bb385384de53cd05ca878e3e77140af6cae1eeb827e52c5fef5bb8fcfd40e162cac62ead212ea74a019c93bae629ad55fc1dbbd0365
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.3 (2026-10-02)
|
|
4
|
+
|
|
5
|
+
- Each process sends its minute of telemetry 1 to 50 seconds after the
|
|
6
|
+
minute ends, chosen once per process, instead of within the first 10
|
|
7
|
+
seconds. Apps' batches reach DeployAngel spread across the minute rather
|
|
8
|
+
than all at once.
|
|
9
|
+
|
|
10
|
+
## 0.1.2 (2026-10-02)
|
|
11
|
+
|
|
12
|
+
- Unsent minutes wait in the buffer as gzipped JSON rather than Ruby objects.
|
|
13
|
+
With every list at its cap, 10 minutes queued while DeployAngel was
|
|
14
|
+
unreachable took about 20 MB; they now take well under 1 MB.
|
|
15
|
+
- `rake bench` measures the agent's overhead: time and allocations per
|
|
16
|
+
request, memory with every list at its cap, and the file digest pass.
|
|
17
|
+
|
|
3
18
|
## 0.1.1 (2026-10-02)
|
|
4
19
|
|
|
5
20
|
- Declared Solid Queue schedules carry the time zone Solid Queue reads them
|
data/README.md
CHANGED
|
@@ -78,11 +78,18 @@ user data.
|
|
|
78
78
|
in-memory counters.
|
|
79
79
|
- Payloads are sent from a background thread, once a minute, with short
|
|
80
80
|
timeouts.
|
|
81
|
-
- When DeployAngel is unreachable, the buffer is bounded (10 payloads
|
|
82
|
-
oldest are dropped. Your app is never blocked or failed.
|
|
81
|
+
- When DeployAngel is unreachable, the buffer is bounded (10 payloads, kept as
|
|
82
|
+
gzipped JSON) and the oldest are dropped. Your app is never blocked or failed.
|
|
83
83
|
- Safe across forks (Puma cluster mode and similar), and the minute in progress
|
|
84
84
|
is flushed at shutdown.
|
|
85
85
|
|
|
86
|
+
`bundle exec rake bench` measures this: the time and allocations each request
|
|
87
|
+
adds, memory with every list at its cap, and the one-time file digest pass
|
|
88
|
+
(`APP_ROOT=path/to/app` to digest your own app). On an Apple M-series laptop
|
|
89
|
+
with Ruby 3.4, recording a request adds about 1.6 µs and 6 objects, and with
|
|
90
|
+
every route, job, checkpoint, and exception list at its cap the agent holds
|
|
91
|
+
about 3 MB, including 10 unsent minutes.
|
|
92
|
+
|
|
86
93
|
## Configuration
|
|
87
94
|
|
|
88
95
|
Environment variables are enough for most apps. To override in code:
|
data/lib/deployangel/agent.rb
CHANGED
|
@@ -9,6 +9,12 @@ module DeployAngel
|
|
|
9
9
|
METADATA_PATH = "/api/v1/application_metadata"
|
|
10
10
|
SHUTDOWN_TIMEOUT = 2
|
|
11
11
|
DEFAULT_PAUSE = 60
|
|
12
|
+
# Seconds past each minute a process waits before sending, chosen once
|
|
13
|
+
# per process so the cloud gets a steady stream instead of a burst at
|
|
14
|
+
# the top of the minute. The cloud reads a minute 2 minutes after it
|
|
15
|
+
# ends, so a send that times out (5 seconds) and goes again a minute
|
|
16
|
+
# later still lands in time.
|
|
17
|
+
FLUSH_JITTER = 1.0..50.0
|
|
12
18
|
|
|
13
19
|
attr_reader :config, :release, :instance
|
|
14
20
|
attr_writer :metadata
|
|
@@ -97,13 +103,14 @@ module DeployAngel
|
|
|
97
103
|
DeployAngel.capabilities
|
|
98
104
|
end
|
|
99
105
|
|
|
100
|
-
# Drains completed minutes into the buffer
|
|
106
|
+
# Drains completed minutes into the buffer, encoded so unsent minutes stay
|
|
107
|
+
# small while DeployAngel is unreachable, and sends what it can.
|
|
101
108
|
def flush(include_current: false)
|
|
102
109
|
return 0 unless @active
|
|
103
110
|
|
|
104
111
|
@aggregator.drain(include_current: include_current, max_periods: config.max_queued_payloads).each do |period|
|
|
105
|
-
@buffer.push(Protocol.telemetry(period, instance: @instance, release: @release,
|
|
106
|
-
capabilities: capabilities))
|
|
112
|
+
@buffer.push(Transport.encode(Protocol.telemetry(period, instance: @instance, release: @release,
|
|
113
|
+
runtime: @runtime, capabilities: capabilities)))
|
|
107
114
|
end
|
|
108
115
|
send_buffered
|
|
109
116
|
rescue StandardError => e
|
|
@@ -172,8 +179,7 @@ module DeployAngel
|
|
|
172
179
|
@paused_until = nil
|
|
173
180
|
@metadata_sent = false
|
|
174
181
|
@thread = nil
|
|
175
|
-
|
|
176
|
-
@jitter = rand(1.0..10.0)
|
|
182
|
+
@jitter = rand(FLUSH_JITTER)
|
|
177
183
|
end
|
|
178
184
|
|
|
179
185
|
def run_reporter
|
|
@@ -16,10 +16,28 @@ module DeployAngel
|
|
|
16
16
|
end
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
# A payload already encoded as gzipped JSON. Queued telemetry is kept
|
|
20
|
+
# this way: a full minute is megabytes as Ruby objects but kilobytes
|
|
21
|
+
# compressed.
|
|
22
|
+
Encoded = Struct.new(:bytes)
|
|
23
|
+
|
|
24
|
+
def self.encode(body)
|
|
25
|
+
Encoded.new(gzip(JSON.generate(body)))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.gzip(string)
|
|
29
|
+
io = StringIO.new
|
|
30
|
+
writer = Zlib::GzipWriter.new(io)
|
|
31
|
+
writer.write(string)
|
|
32
|
+
writer.close
|
|
33
|
+
io.string
|
|
34
|
+
end
|
|
35
|
+
|
|
19
36
|
def initialize(config)
|
|
20
37
|
@config = config
|
|
21
38
|
end
|
|
22
39
|
|
|
40
|
+
# body is a Hash, or an Encoded payload sent as is.
|
|
23
41
|
# :ok (2xx), :retry (network error or 5xx), or :drop (any other status,
|
|
24
42
|
# including 429 rate limiting, which the agent honors by pausing).
|
|
25
43
|
def post(path, body)
|
|
@@ -29,7 +47,7 @@ module DeployAngel
|
|
|
29
47
|
request["Content-Type"] = "application/json"
|
|
30
48
|
request["Content-Encoding"] = "gzip"
|
|
31
49
|
request["User-Agent"] = "deployangel-ruby/#{DeployAngel::VERSION} ruby/#{RUBY_VERSION}"
|
|
32
|
-
request.body =
|
|
50
|
+
request.body = (body.is_a?(Encoded) ? body : self.class.encode(body)).bytes
|
|
33
51
|
|
|
34
52
|
response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https",
|
|
35
53
|
open_timeout: @config.open_timeout, read_timeout: @config.read_timeout,
|
|
@@ -54,13 +72,5 @@ module DeployAngel
|
|
|
54
72
|
rescue JSON::ParserError
|
|
55
73
|
{}
|
|
56
74
|
end
|
|
57
|
-
|
|
58
|
-
def gzip(string)
|
|
59
|
-
io = StringIO.new
|
|
60
|
-
writer = Zlib::GzipWriter.new(io)
|
|
61
|
-
writer.write(string)
|
|
62
|
-
writer.close
|
|
63
|
-
io.string
|
|
64
|
-
end
|
|
65
75
|
end
|
|
66
76
|
end
|
data/lib/deployangel/version.rb
CHANGED