end_point_blank 0.2.0 → 0.2.1
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/LICENSE +16 -0
- data/README.md +265 -24
- data/end_point_blank.gemspec +1 -0
- data/lib/end_point_blank/configuration.rb +1 -1
- data/lib/end_point_blank/version.rb +1 -1
- data/lib/end_point_blank/writers/delayed_writer.rb +16 -7
- metadata +6 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b93be9173755a967ce4c1f1d38205b8803bc175ec1d029f860c6620807553bca
|
|
4
|
+
data.tar.gz: 74ff753691ea46be3ac391cea6b178673a8fb4cd7e0b6ea2861b9646d138e710
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4533c807575899944c7626e716585018309a55311d659b0e2b3fa5005b0ab5b825bec2ef89a0b3d9108277ddac28cc985c75c6047ded18542c2d4dceeace66f1
|
|
7
|
+
data.tar.gz: d7a5148cba59e40aaf3190b8147800e4777882ff08c31e9245ede3f289eff1eedb2c43dfe034587bf52cf2b23518b2d6cdbe4435e90235c71418d433c1d9b16c
|
data/LICENSE
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
Copyright (c) 2026 EndPointBlank. All rights reserved.
|
|
2
|
+
|
|
3
|
+
This software and its associated documentation (the "Software") are the
|
|
4
|
+
proprietary and confidential property of EndPointBlank. The Software is licensed,
|
|
5
|
+
not sold, and its use is governed by a separate written agreement between you and
|
|
6
|
+
EndPointBlank. No rights are granted except as expressly set out in that agreement.
|
|
7
|
+
|
|
8
|
+
Without the prior written permission of EndPointBlank, you may not copy, modify,
|
|
9
|
+
merge, publish, distribute, sublicense, or sell copies of the Software, in whole
|
|
10
|
+
or in part, by any means.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
13
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
14
|
+
FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL ENDPOINTBLANK BE
|
|
15
|
+
LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY ARISING FROM THE USE OF THE
|
|
16
|
+
SOFTWARE.
|
data/README.md
CHANGED
|
@@ -1,28 +1,188 @@
|
|
|
1
|
-
#
|
|
1
|
+
# EndPointBlank (Ruby)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Ruby client for [EndPointBlank](https://endpointblank.com): API endpoint tracking, endpoint
|
|
4
|
+
authorization, error/request/response/log reporting, and client-side data masking — with a
|
|
5
|
+
**framework-agnostic core** that runs in plain Ruby or Sinatra, plus a Rails adapter that
|
|
6
|
+
auto-loads (railtie + middleware) when Rails is present.
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
## Capabilities
|
|
9
|
+
|
|
10
|
+
- **Endpoint tracking** — every request/response passing through the Rack middleware is reported.
|
|
11
|
+
- **Authorization** — outbound calls to other EndPointBlank-protected services are signed
|
|
12
|
+
(`Basic` client-credential or cached `Bearer` token), and inbound requests can be authorized
|
|
13
|
+
against the EndPointBlank service before your action runs.
|
|
14
|
+
- **Error, request, response, and log reporting** — background, queued, non-blocking delivery to
|
|
15
|
+
the EndPointBlank intake API.
|
|
16
|
+
- **Client-side data masking** (`EndPointBlank::Masking` / `masking_rules`) — strip or redact
|
|
17
|
+
sensitive fields from payloads *before* they leave your process, as defense in depth on top of
|
|
18
|
+
server-side masking.
|
|
19
|
+
- **Framework-agnostic core** — `EndPointBlank::Middleware::Rack::ReportInteraction` and the
|
|
20
|
+
writers work directly against Rack env/`::Rack::Request`, so the gem behaves correctly under
|
|
21
|
+
plain Ruby, Sinatra, or any Rack app. When `::Rails` is defined, a `Railtie` auto-inserts the
|
|
22
|
+
middleware and wires up `Rails.logger`; nothing extra needs loading.
|
|
6
23
|
|
|
7
24
|
## Installation
|
|
8
25
|
|
|
9
|
-
|
|
26
|
+
This gem is **not yet published on RubyGems.org**. Until it is, install it from git.
|
|
27
|
+
|
|
28
|
+
Add to your `Gemfile`:
|
|
29
|
+
|
|
30
|
+
```ruby
|
|
31
|
+
gem "end_point_blank", github: "EndPointBlank/end_point_blank_rails"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
(Once released to RubyGems, this collapses to `gem "end_point_blank"`.)
|
|
35
|
+
|
|
36
|
+
Then:
|
|
37
|
+
|
|
38
|
+
```sh
|
|
39
|
+
bundle install
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```ruby
|
|
45
|
+
EndPointBlank.configure do |config|
|
|
46
|
+
config.client_id = "your-client-id"
|
|
47
|
+
config.client_secret = "your-client-secret"
|
|
48
|
+
config.app_name = "my-service"
|
|
49
|
+
end
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
That's it for a Rails app — the railtie auto-inserts the reporting middleware, and every request
|
|
53
|
+
processed by your app is tracked. For plain Ruby / Sinatra, see
|
|
54
|
+
[Framework integration](#framework-integration) below to wire up the Rack middleware yourself.
|
|
55
|
+
|
|
56
|
+
To send your first log line:
|
|
57
|
+
|
|
58
|
+
```ruby
|
|
59
|
+
EndPointBlank::Writers::LogWriter.info("service started", { pid: Process.pid })
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Configuration
|
|
10
63
|
|
|
11
|
-
|
|
64
|
+
`EndPointBlank.configure { |c| ... }` yields the `EndPointBlank::Configuration` singleton.
|
|
65
|
+
Every setting listed below can be set explicitly in that block, and most also fall back to an
|
|
66
|
+
`ENDPOINTBLANK_*` environment variable, then to a built-in default.
|
|
12
67
|
|
|
13
|
-
|
|
68
|
+
**Precedence: explicit `configure` value > `ENDPOINTBLANK_*` environment variable > default.**
|
|
14
69
|
|
|
15
|
-
|
|
70
|
+
| `configure` setting | Env var fallback | Default | Notes |
|
|
71
|
+
|---|---|---|---|
|
|
72
|
+
| `client_id` | `ENDPOINTBLANK_CLIENT_ID` | `nil` | Used to build the `Basic` authorization header. |
|
|
73
|
+
| `client_secret` | `ENDPOINTBLANK_CLIENT_SECRET` | `nil` | Paired with `client_id`. |
|
|
74
|
+
| `base_url` | `ENDPOINTBLANK_BASE_URL` | `https://in.endpointblank.com` | Base for access-token, authorize, and endpoint-update APIs. |
|
|
75
|
+
| `log_base_url` | `ENDPOINTBLANK_LOG_BASE_URL` | `https://log.endpointblank.com` | Base for error/request/response/log reporting APIs. |
|
|
76
|
+
| `app_name` | `ENDPOINTBLANK_APP_NAME` | `Rails.application.name.underscore` if Rails is defined, else `nil` | Identifies your app to EndPointBlank. |
|
|
77
|
+
| `env_name` | `ENDPOINTBLANK_ENV` | `RACK_ENV`, then `APP_ENV`, then `Rails.env` if defined, else `"production"` (resolved per-request by `SessionConfiguration.env_name`, not read directly off `Configuration`) | The environment name reported with each request/response payload. |
|
|
78
|
+
| `logger` | — | A `::Logger.new($stdout, level: ::Logger::INFO)`, or `Rails.logger` under Rails (set by the railtie) | Any object with `.debug`/`.info`/`.warn`/`.error`/`.fatal` works. |
|
|
79
|
+
| `worker_count` | — | `4` | Currently unused by the delayed writer (which always spins up 2 threads); reserved. |
|
|
80
|
+
| `token_ttl` | — | `nil` | Optional TTL (seconds) requested when generating a `Bearer` access token. |
|
|
81
|
+
| `cache_ttl` | — | `300` | TTL (seconds) for the authorization decision cache. |
|
|
82
|
+
| `masking_rules` | — | `[]` | Ordered list of masking rule hashes — see [Data masking](#data-masking). |
|
|
83
|
+
| `mask_hook` | — | `nil` | Optional `->(payload, record_type_string) { payload }` run after `masking_rules`. |
|
|
84
|
+
| `version_finder` | — | `nil` | Optional `->(request) { "1" }` overriding `EndPointBlank::Commands::VersionFinder`'s default header/param/path detection. |
|
|
85
|
+
| `application_version` | — | `nil` | Reserved for reporting your app's own version. |
|
|
16
86
|
|
|
17
|
-
|
|
87
|
+
Note: there is also a bare `environment` accessor on `Configuration`, but it is not read by any
|
|
88
|
+
code path in this gem (the real per-request environment name is `env_name`, described above) — do
|
|
89
|
+
not rely on it.
|
|
90
|
+
|
|
91
|
+
### `configure` block example
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
EndPointBlank.configure do |config|
|
|
95
|
+
config.client_id = "abc123"
|
|
96
|
+
config.client_secret = "s3cr3t"
|
|
97
|
+
config.base_url = "https://in.endpointblank.com"
|
|
98
|
+
config.log_base_url = "https://log.endpointblank.com"
|
|
99
|
+
config.app_name = "checkout-service"
|
|
100
|
+
config.env_name = "staging"
|
|
101
|
+
config.logger = Logger.new($stdout)
|
|
102
|
+
end
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 12-factor / env-var example
|
|
106
|
+
|
|
107
|
+
With no `configure` block at all (or a partial one), the same values can come entirely from the
|
|
108
|
+
environment:
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
export ENDPOINTBLANK_CLIENT_ID=abc123
|
|
112
|
+
export ENDPOINTBLANK_CLIENT_SECRET=s3cr3t
|
|
113
|
+
export ENDPOINTBLANK_BASE_URL=https://in.endpointblank.com
|
|
114
|
+
export ENDPOINTBLANK_LOG_BASE_URL=https://log.endpointblank.com
|
|
115
|
+
export ENDPOINTBLANK_APP_NAME=checkout-service
|
|
116
|
+
export ENDPOINTBLANK_ENV=staging
|
|
117
|
+
```
|
|
18
118
|
|
|
19
119
|
## Usage
|
|
20
120
|
|
|
21
|
-
###
|
|
121
|
+
### Authorization
|
|
122
|
+
|
|
123
|
+
`EndPointBlank::Authorization.header(hostname = nil)` builds the outbound `Authorization` header
|
|
124
|
+
used by the gem's own HTTP calls: a cached `Bearer` token for `hostname` when one is available
|
|
125
|
+
(via `EndPointBlank::AccessTokens`), otherwise `Basic` credentials built from `client_id` /
|
|
126
|
+
`client_secret`.
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
EndPointBlank::Authorization.header # => "Basic ..."
|
|
130
|
+
EndPointBlank::Authorization.header("api.example.com") # => "Bearer ..." if a token is cached
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Under Rails, protect an inbound endpoint by including the `Authorized` concern in a controller —
|
|
134
|
+
it calls `EndPointBlank::Commands::EndpointAuthorize.authorize(request)` before the action, and
|
|
135
|
+
raises `EndPointBlank::UnauthorizedError` (which you can rescue with
|
|
136
|
+
`rescue_from EndPointBlank::UnauthorizedError` in `ApplicationController`) on a non-201 response:
|
|
137
|
+
|
|
138
|
+
```ruby
|
|
139
|
+
class OrdersController < ApplicationController
|
|
140
|
+
include EndPointBlank::Rails::Authorized
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
`EndPointBlank::Commands::EndpointAuthorize.authorize` sends the request's path, HTTP method,
|
|
145
|
+
inbound `Authorization` header, app name, resolved endpoint version, and remote IP to
|
|
146
|
+
`#{base_url}/api/authorize`, and caches a positive (201) result for `cache_ttl` seconds via
|
|
147
|
+
`EndPointBlank::Commands::AuthenticationCache`.
|
|
22
148
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
149
|
+
### Error reporting
|
|
150
|
+
|
|
151
|
+
Exceptions raised while `EndPointBlank::Middleware::Rack::ReportInteraction` is on the stack are
|
|
152
|
+
reported automatically (see [Framework integration](#framework-integration)). To report one
|
|
153
|
+
manually:
|
|
154
|
+
|
|
155
|
+
```ruby
|
|
156
|
+
begin
|
|
157
|
+
risky_operation!
|
|
158
|
+
rescue => e
|
|
159
|
+
EndPointBlank::Writers::ExceptionWriter.write(e)
|
|
160
|
+
raise
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Request/response/log reporting
|
|
165
|
+
|
|
166
|
+
Requests and responses are written automatically by the Rack middleware. Application logs are
|
|
167
|
+
sent explicitly:
|
|
168
|
+
|
|
169
|
+
```ruby
|
|
170
|
+
EndPointBlank::Writers::LogWriter.info("cache warmed", { keys: 42 })
|
|
171
|
+
EndPointBlank::Writers::LogWriter.warn("slow query", { duration_ms: 820 })
|
|
172
|
+
EndPointBlank::Writers::LogWriter.error("payment webhook rejected", { code: "sig_mismatch" })
|
|
173
|
+
EndPointBlank::Writers::LogWriter.fatal("out of workers")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
All writers (`RequestWriter`, `ResponseWriter`, `ExceptionWriter`, `LogWriter`) enqueue their
|
|
177
|
+
payload onto a bounded, in-memory queue (`DelayedWriter`, capacity 1000, drop-oldest under
|
|
178
|
+
sustained backpressure) drained by two background threads that POST batches via `excon`. Delivery
|
|
179
|
+
is fire-and-forget and never raises into your request cycle.
|
|
180
|
+
|
|
181
|
+
### Data masking
|
|
182
|
+
|
|
183
|
+
Mask sensitive data **client-side, before it leaves your process**. Configure an ordered list of
|
|
184
|
+
rules; each rule targets one field and masks by a JSONPath, a regex, or both. (Server-side intake
|
|
185
|
+
also masks independently, so this is defense in depth.)
|
|
26
186
|
|
|
27
187
|
```ruby
|
|
28
188
|
EndPointBlank.configure do |config|
|
|
@@ -37,28 +197,109 @@ EndPointBlank.configure do |config|
|
|
|
37
197
|
end
|
|
38
198
|
```
|
|
39
199
|
|
|
40
|
-
Rules are hashes with symbol keys.
|
|
200
|
+
Rules are hashes with symbol (or string) keys.
|
|
41
201
|
|
|
42
202
|
**Rule fields**
|
|
43
203
|
|
|
44
|
-
- `target` — exactly one of `"request_body"`, `"request_headers"`, `"path"`, `"response_body"`,
|
|
204
|
+
- `target` — exactly one of `"request_body"`, `"request_headers"`, `"path"`, `"response_body"`,
|
|
205
|
+
`"error_message"`.
|
|
45
206
|
- `path` — an optional JSONPath (supported subset: `$`, `.name`, `['name']`, `[n]`, `.*` / `[*]`,
|
|
46
207
|
and `..name` for recursive descent). Keys are case-sensitive.
|
|
47
|
-
- `regex` — an optional regular expression.
|
|
208
|
+
- `regex` — an optional regular expression source string.
|
|
48
209
|
- `replacement_value` — the replacement string (default `"..."`).
|
|
49
210
|
|
|
50
|
-
**Semantics — path scopes, regex matches within.** With only a `path`, the selected node is
|
|
51
|
-
entirely. With only a `regex`, every matching string is replaced. With both, the
|
|
52
|
-
only within the path-selected node(s). When a `regex` is present,
|
|
53
|
-
backreferences: `$1`, `$2`, … insert capture groups (`$0` the whole
|
|
54
|
-
Stacktraces and log messages are never masked
|
|
211
|
+
**Semantics — path scopes, regex matches within.** With only a `path`, the selected node is
|
|
212
|
+
replaced entirely. With only a `regex`, every matching string leaf is replaced. With both, the
|
|
213
|
+
regex is applied only within the path-selected node(s). When a `regex` is present,
|
|
214
|
+
`replacement_value` supports backreferences: `$1`, `$2`, … insert capture groups (`$0` the whole
|
|
215
|
+
match; `$$` for a literal `$`). Stacktraces and log messages/data are never masked (there is no
|
|
216
|
+
`log` entry in the masking field map).
|
|
217
|
+
|
|
218
|
+
## Framework integration
|
|
219
|
+
|
|
220
|
+
### Rails
|
|
221
|
+
|
|
222
|
+
Nothing to wire up manually. When `::Rails` is defined, `lib/end_point_blank.rb` requires
|
|
223
|
+
`EndPointBlank::Rails::Railtie`, which:
|
|
224
|
+
|
|
225
|
+
- inserts `EndPointBlank::Middleware::Rack::ReportInteraction` into the middleware stack right
|
|
226
|
+
after `ActionDispatch::DebugExceptions`, so every request/response is reported and exceptions
|
|
227
|
+
are captured before Rails' own exception rendering; and
|
|
228
|
+
- sets `Configuration.instance.logger ||= Rails.logger`, so `EndPointBlank.logger` writes through
|
|
229
|
+
`Rails.logger` unless you've already configured your own.
|
|
230
|
+
|
|
231
|
+
Optional concerns for controllers:
|
|
232
|
+
|
|
233
|
+
```ruby
|
|
234
|
+
class ApplicationController < ActionController::Base
|
|
235
|
+
rescue_from EndPointBlank::UnauthorizedError do |e|
|
|
236
|
+
render json: { error: e.message }, status: e.status
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
class OrdersController < ApplicationController
|
|
241
|
+
include EndPointBlank::Rails::Authorized # authorize inbound requests before each action
|
|
242
|
+
include EndPointBlank::Rails::Versioned
|
|
243
|
+
|
|
244
|
+
version ["v1", "v2"], only: [:index]
|
|
245
|
+
end
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`app_name` falls back to `Rails.application.name.underscore` automatically, so Rails apps
|
|
249
|
+
typically only need to configure `client_id` / `client_secret` (and `app_name` only to override
|
|
250
|
+
the Rails-derived default).
|
|
251
|
+
|
|
252
|
+
### Plain Ruby / Sinatra
|
|
253
|
+
|
|
254
|
+
There's no Rails to auto-load anything, so insert the Rack middleware yourself and set `app_name`
|
|
255
|
+
and `env_name` explicitly (via `configure` or `ENDPOINTBLANK_APP_NAME` / `ENDPOINTBLANK_ENV`,
|
|
256
|
+
since there's no `Rails.application.name` / `Rails.env` to infer them from):
|
|
257
|
+
|
|
258
|
+
```ruby
|
|
259
|
+
require "sinatra"
|
|
260
|
+
require "end_point_blank"
|
|
261
|
+
|
|
262
|
+
EndPointBlank.configure do |config|
|
|
263
|
+
config.client_id = ENV.fetch("ENDPOINTBLANK_CLIENT_ID")
|
|
264
|
+
config.client_secret = ENV.fetch("ENDPOINTBLANK_CLIENT_SECRET")
|
|
265
|
+
config.app_name = "my-sinatra-app" # or set ENDPOINTBLANK_APP_NAME and omit this
|
|
266
|
+
config.env_name = "production" # or set ENDPOINTBLANK_ENV / RACK_ENV and omit this
|
|
267
|
+
config.logger = Logger.new($stdout)
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
use EndPointBlank::Middleware::Rack::ReportInteraction
|
|
271
|
+
|
|
272
|
+
get "/" do
|
|
273
|
+
"ok"
|
|
274
|
+
end
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
The middleware calls `EndPointBlank::Rack::EnvStore.set(env)`, reports the request via
|
|
278
|
+
`RequestWriter`, invokes the app, and — in an `ensure` — reports the response via `ResponseWriter`
|
|
279
|
+
and clears the env store, reporting any raised exception via `ExceptionWriter` along the way. It
|
|
280
|
+
reads/writes plain Rack request objects (`::Rack::Request`), so it works identically under any
|
|
281
|
+
Rack-compatible server or framework, not only Sinatra.
|
|
55
282
|
|
|
56
283
|
## Development
|
|
57
284
|
|
|
58
|
-
|
|
285
|
+
```sh
|
|
286
|
+
bundle install
|
|
287
|
+
bundle exec rspec
|
|
288
|
+
bundle exec rubocop
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
`bundle exec rspec` runs the full suite, including specs that assert the framework-agnostic core
|
|
292
|
+
behaves correctly with `::Rails` undefined (`spec/no_rails_spec.rb`,
|
|
293
|
+
`spec/generate_access_token_no_rails_spec.rb`,
|
|
294
|
+
`spec/route_pattern_finder_and_version_finder_no_rails_spec.rb`).
|
|
295
|
+
|
|
296
|
+
## License
|
|
59
297
|
|
|
60
|
-
|
|
298
|
+
No `LICENSE` file or `spec.license` is currently present in this repository. Treat usage as
|
|
299
|
+
proprietary/all-rights-reserved until a license is added, or confirm terms with the repository
|
|
300
|
+
owners.
|
|
61
301
|
|
|
62
|
-
##
|
|
302
|
+
## Links
|
|
63
303
|
|
|
64
|
-
|
|
304
|
+
- Repository: https://github.com/EndPointBlank/end_point_blank_rails
|
|
305
|
+
- Issues: https://github.com/EndPointBlank/end_point_blank_rails/issues
|
data/end_point_blank.gemspec
CHANGED
|
@@ -12,6 +12,7 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.description = "EndPointBlank client library for Ruby. A framework-agnostic core runs in plain Ruby / Sinatra, with Rails supported as an auto-loaded adapter. Provides API endpoint tracking, authorization, and error/request/response/log reporting."
|
|
13
13
|
spec.homepage = "https://github.com/EndPointBlank/end_point_blank_rails"
|
|
14
14
|
spec.required_ruby_version = ">= 3.4.2"
|
|
15
|
+
spec.license = "Nonstandard"
|
|
15
16
|
|
|
16
17
|
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
17
18
|
|
|
@@ -13,7 +13,7 @@ module EndPointBlank
|
|
|
13
13
|
|
|
14
14
|
attr_writer :client_id, :client_secret, :base_url, :log_base_url, :app_name, :env_name
|
|
15
15
|
|
|
16
|
-
attr_accessor :
|
|
16
|
+
attr_accessor :worker_count, :log_mode,
|
|
17
17
|
:version_finder, :application_version, :token_ttl, :cache_ttl,
|
|
18
18
|
:masking_rules, :mask_hook, :logger
|
|
19
19
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "singleton"
|
|
2
4
|
|
|
3
5
|
module EndPointBlank
|
|
4
6
|
module Writers
|
|
@@ -14,6 +16,9 @@ module EndPointBlank
|
|
|
14
16
|
module DelayedWriter
|
|
15
17
|
MAX_QUEUE_SIZE = 1000
|
|
16
18
|
WARN_THROTTLE_SECONDS = 30
|
|
19
|
+
# Fallback thread count used when Configuration#worker_count is unset,
|
|
20
|
+
# preserving the previously-hardcoded pool size.
|
|
21
|
+
DEFAULT_WORKER_COUNT = 2
|
|
17
22
|
|
|
18
23
|
def direct_writer
|
|
19
24
|
@direct_writer ||= DirectWriter.new(url)
|
|
@@ -23,28 +28,32 @@ module EndPointBlank
|
|
|
23
28
|
@queue ||= Queue.new
|
|
24
29
|
end
|
|
25
30
|
|
|
31
|
+
def worker_count
|
|
32
|
+
EndPointBlank::Configuration.instance.worker_count || DEFAULT_WORKER_COUNT
|
|
33
|
+
end
|
|
34
|
+
|
|
26
35
|
def start_threads
|
|
27
36
|
@threads = []
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
worker_count.times do
|
|
30
39
|
@threads << Thread.new do
|
|
31
40
|
loop do
|
|
32
41
|
payload = queue.pop
|
|
33
42
|
payloads = [payload]
|
|
34
|
-
while (payload = pop_additional)
|
|
43
|
+
while (payload = pop_additional)
|
|
35
44
|
payloads << payload
|
|
36
45
|
end
|
|
37
46
|
|
|
38
47
|
payloads.compact!
|
|
39
|
-
while payloads.any?
|
|
48
|
+
while payloads.any?
|
|
40
49
|
list = payloads[0..5]
|
|
41
50
|
response = direct_writer.write(list)
|
|
42
51
|
if response.status < 299
|
|
43
52
|
on_success(response) if respond_to?(:on_success)
|
|
44
|
-
|
|
45
|
-
on_failure(response)
|
|
53
|
+
elsif respond_to?(:on_failure)
|
|
54
|
+
on_failure(response)
|
|
46
55
|
end
|
|
47
|
-
payloads
|
|
56
|
+
payloads -= list
|
|
48
57
|
end
|
|
49
58
|
end
|
|
50
59
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: end_point_blank
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Robert A. Lasch
|
|
8
8
|
bindir: exe
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 2026-07-08 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: excon
|
|
@@ -91,6 +91,7 @@ files:
|
|
|
91
91
|
- ".rspec"
|
|
92
92
|
- ".rubocop.yml"
|
|
93
93
|
- ".ruby-version"
|
|
94
|
+
- LICENSE
|
|
94
95
|
- README.md
|
|
95
96
|
- Rakefile
|
|
96
97
|
- build.sh
|
|
@@ -136,7 +137,8 @@ files:
|
|
|
136
137
|
- sig/end_point_blank_rack.rbs
|
|
137
138
|
- test.sh
|
|
138
139
|
homepage: https://github.com/EndPointBlank/end_point_blank_rails
|
|
139
|
-
licenses:
|
|
140
|
+
licenses:
|
|
141
|
+
- Nonstandard
|
|
140
142
|
metadata:
|
|
141
143
|
allowed_push_host: https://rubygems.org
|
|
142
144
|
homepage_uri: https://github.com/EndPointBlank/end_point_blank_rails
|
|
@@ -156,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
156
158
|
- !ruby/object:Gem::Version
|
|
157
159
|
version: '0'
|
|
158
160
|
requirements: []
|
|
159
|
-
rubygems_version:
|
|
161
|
+
rubygems_version: 3.6.2
|
|
160
162
|
specification_version: 4
|
|
161
163
|
summary: Ruby/Rails client for EndPointBlank — endpoint tracking, authorization, and
|
|
162
164
|
error/request/response/log reporting.
|