atlas_rb 1.27.1 → 1.27.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 +4 -4
- data/.version +1 -1
- data/CHANGELOG.md +13 -0
- data/Gemfile.lock +1 -1
- data/README.md +24 -0
- data/lib/atlas_rb/metrics.rb +68 -0
- data/lib/atlas_rb.rb +1 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3bf07fbfa75e57be6651cc352fc2216f8c5e4029a68393018fa14b8e6a34e6aa
|
|
4
|
+
data.tar.gz: 63d66617e658bc0693c7a07afdf0b38cac2067f464b3ba1e0466b3a8d7d1860e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2071b3face694f62a03db93362462bf77381cfdcee77c138ff5a2baabe47f000d94ede673ca1d28f160d0348506a844346f920b71457669bae326769aa9286e3
|
|
7
|
+
data.tar.gz: 823ca671c648afad8c4a82111d658a691c6bf757e02cb942594c0a1c6afec2a1b6fda628c954ca909497c7168a6384f845fcf4ed229a1f470d5fabb1bac212c8
|
data/.version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.27.
|
|
1
|
+
1.27.2
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.27.2
|
|
4
|
+
|
|
5
|
+
Requires an Atlas that serves `GET /metrics/latency`.
|
|
6
|
+
|
|
7
|
+
### Added — `AtlasRb::Metrics.latency`
|
|
8
|
+
|
|
9
|
+
Reads Atlas's own request latency for a window of up to 120 minutes: calls,
|
|
10
|
+
5xx count, mean and approximate p50/p95/p99, and the slowest actions. Sent
|
|
11
|
+
with the acting NUID's signed assertion, which must name an admin. A
|
|
12
|
+
5-second deadline, no retry and a fresh socket per call. Raises
|
|
13
|
+
`BackendUnavailableError` when Atlas's Redis is down and `ResourceError` on
|
|
14
|
+
any other non-200.
|
|
15
|
+
|
|
3
16
|
## 1.27.1
|
|
4
17
|
|
|
5
18
|
Requires an Atlas that serves `GET /health` and the `backend_unavailable`
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -857,6 +857,30 @@ It is not a `ResourceError`, which hosts treat as a refusal of the request.
|
|
|
857
857
|
A streaming download (`Blob.content`, `Blob.version_content`) cannot raise
|
|
858
858
|
this: its body has already gone to your block. Check the returned `status`.
|
|
859
859
|
|
|
860
|
+
### Atlas's own latency
|
|
861
|
+
|
|
862
|
+
`AtlasRb::Metrics.latency` reports how long Atlas took to serve its own
|
|
863
|
+
requests over a recent window. Atlas gates it to admins and `:system`, so
|
|
864
|
+
`nuid` must name an admin:
|
|
865
|
+
|
|
866
|
+
```ruby
|
|
867
|
+
latency = AtlasRb::Metrics.latency(minutes: 60, nuid: current_user.nuid)
|
|
868
|
+
latency["calls"] # => 18402
|
|
869
|
+
latency["server_errors"] # => 3
|
|
870
|
+
latency["p95_ms"] # => 98
|
|
871
|
+
latency["slowest_actions"].first # => { "action" => "works#mods", "calls" => 912, "p95_ms" => 188 }
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
Atlas times each request from when Rails dispatches it until it returns, so
|
|
875
|
+
the figures leave out the network and your own waiting. If you also time your
|
|
876
|
+
Atlas calls, the difference is time spent on your side. The percentiles are
|
|
877
|
+
interpolated from histogram buckets, so they are approximate.
|
|
878
|
+
|
|
879
|
+
Like `Health.read`, it has a 5-second deadline and no retry. It raises
|
|
880
|
+
`BackendUnavailableError` (with `dependency == "cache"`) when Atlas's Redis is
|
|
881
|
+
down, `ResourceError` on any other non-200 such as a `403`, and `Faraday`
|
|
882
|
+
errors when nothing answers.
|
|
883
|
+
|
|
860
884
|
## End-to-end example
|
|
861
885
|
|
|
862
886
|
JSON responses come back as `AtlasRb::Mash` (a `Hashie::Mash` subclass), so
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module AtlasRb
|
|
4
|
+
# Atlas's own operational figures. Admin- or `:system`-gated in Atlas.
|
|
5
|
+
class Metrics
|
|
6
|
+
extend AtlasRb::FaradayHelper
|
|
7
|
+
|
|
8
|
+
# Seconds to wait for a socket to open.
|
|
9
|
+
OPEN_TIMEOUT = 2
|
|
10
|
+
|
|
11
|
+
# Seconds to wait for the report. It reads at most 120 small Redis hashes,
|
|
12
|
+
# so a slower answer means Atlas is struggling, and an admin page should
|
|
13
|
+
# not wait on it.
|
|
14
|
+
READ_TIMEOUT = 5
|
|
15
|
+
|
|
16
|
+
# How long Atlas took to serve its own requests (`GET /metrics/latency`).
|
|
17
|
+
#
|
|
18
|
+
# Measured inside Atlas, from when Rails dispatches the action until it
|
|
19
|
+
# returns, so it leaves out the network and the caller's own waiting. A
|
|
20
|
+
# caller that also times its Atlas calls can subtract to see how much of
|
|
21
|
+
# its wait was its own. The percentiles are interpolated from histogram
|
|
22
|
+
# buckets, so they are approximate.
|
|
23
|
+
#
|
|
24
|
+
# No retry, and a fresh socket per call: like {AtlasRb::Health.read}, it is
|
|
25
|
+
# polled rarely and should fail fast rather than hide a struggling Atlas.
|
|
26
|
+
#
|
|
27
|
+
# @param minutes [Integer] the window, 1 to 120. Atlas clamps it.
|
|
28
|
+
# @param nuid [String, nil] the acting NUID, signed into the assertion
|
|
29
|
+
# `sub`. It must name an admin; falls through to
|
|
30
|
+
# {AtlasRb.config#default_nuid}.
|
|
31
|
+
# @param on_behalf_of [String, nil] optional NUID carried as a signed `obo`
|
|
32
|
+
# claim.
|
|
33
|
+
# @return [AtlasRb::Mash] `window_minutes`, `calls`, `server_errors`,
|
|
34
|
+
# `mean_ms`, `p50_ms`, `p95_ms`, `p99_ms` (Integer, or nil with no calls),
|
|
35
|
+
# and `slowest_actions`, an Array of `action` / `calls` / `p95_ms`.
|
|
36
|
+
# @raise [AtlasRb::BackendUnavailableError] when Atlas answers that Redis,
|
|
37
|
+
# which holds the figures, is down (`dependency == "cache"`).
|
|
38
|
+
# @raise [AtlasRb::ResourceError] on any other non-200, notably a `403`
|
|
39
|
+
# for a caller who is not an admin.
|
|
40
|
+
# @raise [Faraday::ConnectionFailed, Faraday::TimeoutError] when Atlas does
|
|
41
|
+
# not answer at all.
|
|
42
|
+
#
|
|
43
|
+
# @example
|
|
44
|
+
# latency = AtlasRb::Metrics.latency(minutes: 15, nuid: current_user.nuid)
|
|
45
|
+
# latency.p95_ms # => 98
|
|
46
|
+
def self.latency(minutes: 60, nuid: nil, on_behalf_of: nil)
|
|
47
|
+
resp = metrics_connection(nuid, on_behalf_of).get("/metrics/latency", minutes: minutes)
|
|
48
|
+
return AtlasRb::Mash.new(JSON.parse(resp.body)) if resp.status == 200
|
|
49
|
+
|
|
50
|
+
raise AtlasRb::ResourceError.new("#{request_target(resp)} → #{resp.status}: #{resp.body}", response: resp)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
class << self
|
|
54
|
+
private
|
|
55
|
+
|
|
56
|
+
def metrics_connection(nuid, on_behalf_of)
|
|
57
|
+
headers = auth_headers(nuid, on_behalf_of).merge("Content-Type" => "application/json")
|
|
58
|
+
Faraday.new(url: ENV.fetch("ATLAS_URL", nil), headers: headers) do |f|
|
|
59
|
+
f.options.open_timeout = OPEN_TIMEOUT
|
|
60
|
+
f.options.timeout = READ_TIMEOUT
|
|
61
|
+
instrument(f)
|
|
62
|
+
f.use AtlasRb::Middleware::RaiseOnBackendUnavailable
|
|
63
|
+
f.adapter :net_http
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
data/lib/atlas_rb.rb
CHANGED
|
@@ -48,6 +48,7 @@ require_relative "atlas_rb/system/work"
|
|
|
48
48
|
require_relative "atlas_rb/audit_event"
|
|
49
49
|
require_relative "atlas_rb/maintenance"
|
|
50
50
|
require_relative "atlas_rb/health"
|
|
51
|
+
require_relative "atlas_rb/metrics"
|
|
51
52
|
|
|
52
53
|
# Ruby client for the Atlas API — Northeastern University's institutional
|
|
53
54
|
# digital repository.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: atlas_rb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.27.
|
|
4
|
+
version: 1.27.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cliff
|
|
@@ -173,6 +173,7 @@ files:
|
|
|
173
173
|
- lib/atlas_rb/health.rb
|
|
174
174
|
- lib/atlas_rb/maintenance.rb
|
|
175
175
|
- lib/atlas_rb/mash.rb
|
|
176
|
+
- lib/atlas_rb/metrics.rb
|
|
176
177
|
- lib/atlas_rb/middleware/raise_on_backend_unavailable.rb
|
|
177
178
|
- lib/atlas_rb/middleware/raise_on_read_error.rb
|
|
178
179
|
- lib/atlas_rb/middleware/raise_on_read_only_mode.rb
|