apidepth 0.2.2 → 0.2.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/lib/apidepth/collector.rb +7 -2
- data/lib/apidepth/registry_loader.rb +109 -1
- data/lib/apidepth/version.rb +1 -1
- metadata +5 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f499652eea585017c268ea82a997a9e11af46e36c912b6f672fa91fd7d354eb4
|
|
4
|
+
data.tar.gz: aa70866eaf7876101236b986472ad14b24ea68bcaa9a38a68ed901d88e1f06b5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 22a04205584e05a111b2422209733b4c06b0008dada3840caa340915d2d9ffb7195dec530c4791b692990812f357b4148a714da904ada5fba15e5b20f854460e
|
|
7
|
+
data.tar.gz: 607dca2a4455e60fcf21bd3502382107a3840b02ca23102a0dac4fc4c903c62101bf46b099210591182aa6350f229ffc0209f650a71076060c1e482b83340cee
|
data/lib/apidepth/collector.rb
CHANGED
|
@@ -92,16 +92,21 @@ module Apidepth
|
|
|
92
92
|
end
|
|
93
93
|
end
|
|
94
94
|
|
|
95
|
+
# Canonical test cases live in apidepth-collector/tests/fixtures/private_host_cases.json.
|
|
96
|
+
# All SDK implementations load that fixture and must pass every case. Any change here
|
|
97
|
+
# must be accompanied by a fixture update and a matching change in every other SDK.
|
|
95
98
|
PRIVATE_HOST_PATTERN = /
|
|
96
99
|
\Alocalhost\z |
|
|
97
100
|
\A127\. |
|
|
98
101
|
\A0\.0\.0\.0\z |
|
|
102
|
+
\A0\z |
|
|
103
|
+
|
|
99
104
|
\A169\.254\. |
|
|
100
105
|
\A10\. |
|
|
101
106
|
\A172\.(1[6-9]|2\d|3[01])\. |
|
|
102
107
|
\A192\.168\. |
|
|
103
108
|
\A\[?::1\]?\z |
|
|
104
|
-
\A\[?
|
|
109
|
+
\A\[?f[cd] |
|
|
105
110
|
\A\[?fe80:
|
|
106
111
|
/xi.freeze
|
|
107
112
|
|
|
@@ -287,7 +292,7 @@ module Apidepth
|
|
|
287
292
|
|
|
288
293
|
if host.match?(/\A\d+\z/)
|
|
289
294
|
int = host.to_i
|
|
290
|
-
if int
|
|
295
|
+
if int >= 0 && int <= 0xFFFFFFFF
|
|
291
296
|
host = [int >> 24, (int >> 16) & 0xFF, (int >> 8) & 0xFF,
|
|
292
297
|
int & 0xFF].join(".")
|
|
293
298
|
end
|
|
@@ -57,6 +57,11 @@ module Apidepth
|
|
|
57
57
|
|
|
58
58
|
registry = JSON.parse(res.body)
|
|
59
59
|
|
|
60
|
+
# Apply registry-managed customer vendors and emit developer warnings.
|
|
61
|
+
# Must run before replace() so the vendor list is complete when it lands.
|
|
62
|
+
apply_customer_vendors(registry)
|
|
63
|
+
emit_warnings(registry)
|
|
64
|
+
|
|
60
65
|
# Warm the disk cache so the next cold-start skips the network fetch.
|
|
61
66
|
begin
|
|
62
67
|
validate_cache_path!(Apidepth.configuration.registry_cache_path)
|
|
@@ -79,6 +84,103 @@ module Apidepth
|
|
|
79
84
|
Thread.current[:apidepth_skip] = false
|
|
80
85
|
end
|
|
81
86
|
|
|
87
|
+
# Apply the collector-managed customer_vendors from the registry response.
|
|
88
|
+
#
|
|
89
|
+
# The collector is the source of truth after first declaration. Registry
|
|
90
|
+
# vendors are loaded on top of locally-declared extra_vendors; registry wins
|
|
91
|
+
# on any host conflict. Conflict warnings are emitted once per vendor per
|
|
92
|
+
# process lifetime (see emit_warnings).
|
|
93
|
+
def self.apply_customer_vendors(registry)
|
|
94
|
+
remote = registry["customer_vendors"]
|
|
95
|
+
return unless remote.is_a?(Hash) && !remote.empty?
|
|
96
|
+
|
|
97
|
+
local = Apidepth.configuration.extra_vendors || {}
|
|
98
|
+
|
|
99
|
+
# Filter to string key-value pairs before passing to load_extra_vendors.
|
|
100
|
+
# The server response is trusted but load_extra_vendors calls .to_s on
|
|
101
|
+
# everything — a non-string key like 42 would silently register as "42".
|
|
102
|
+
clean = {}
|
|
103
|
+
remote.each do |name, remote_host|
|
|
104
|
+
next unless name.is_a?(String) && remote_host.is_a?(String)
|
|
105
|
+
|
|
106
|
+
clean[name] = remote_host
|
|
107
|
+
local_host = local[name]
|
|
108
|
+
# Track conflicts before overwriting — emit_warnings reads this later.
|
|
109
|
+
@mutex.synchronize do
|
|
110
|
+
if local_host && local_host != remote_host
|
|
111
|
+
@conflict_vendors ||= {}
|
|
112
|
+
@conflict_vendors[name] = { local: local_host, remote: remote_host }
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
VendorRegistry.load_extra_vendors(clean)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Emit developer-facing warnings from the registry response.
|
|
121
|
+
#
|
|
122
|
+
# Stale vendor warning: vendor exists in registry but no events in 7+ days.
|
|
123
|
+
# Conflict warning: local extra_vendors host differs from registry host.
|
|
124
|
+
#
|
|
125
|
+
# Both follow the warn-once pattern — an instance flag per vendor prevents
|
|
126
|
+
# log spam in long-running processes. Warnings fire on registry fetch, not
|
|
127
|
+
# on every event.
|
|
128
|
+
def self.emit_warnings(registry)
|
|
129
|
+
# Stale vendor warnings — sourced from the registry warnings block.
|
|
130
|
+
# Only present in responses from collector v0.3+; older cached responses skip.
|
|
131
|
+
warnings = registry["warnings"]
|
|
132
|
+
emit_stale_warnings(warnings["stale_vendors"]) if warnings.is_a?(Hash)
|
|
133
|
+
|
|
134
|
+
# Conflict warnings — collected by apply_customer_vendors, emitted here.
|
|
135
|
+
# Fires regardless of whether the registry has a warnings block, so that
|
|
136
|
+
# conflicts detected against a cached/older registry are still surfaced.
|
|
137
|
+
emit_conflict_warnings
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def self.emit_stale_warnings(stale)
|
|
141
|
+
return unless stale.is_a?(Array)
|
|
142
|
+
|
|
143
|
+
to_warn = []
|
|
144
|
+
@mutex.synchronize do
|
|
145
|
+
@warned_stale ||= {}
|
|
146
|
+
stale.each do |name|
|
|
147
|
+
next unless name.is_a?(String)
|
|
148
|
+
next if @warned_stale[name]
|
|
149
|
+
|
|
150
|
+
@warned_stale[name] = true
|
|
151
|
+
to_warn << name
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
to_warn.each do |name|
|
|
156
|
+
Apidepth.logger&.warn(
|
|
157
|
+
"[Apidepth] No events received from '#{name}' in 7+ days — " \
|
|
158
|
+
"is it still declared in extra_vendors? If intentional, remove " \
|
|
159
|
+
"it at www.apidepth.io."
|
|
160
|
+
)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def self.emit_conflict_warnings
|
|
165
|
+
conflicts, = @mutex.synchronize do
|
|
166
|
+
c = @conflict_vendors || {}
|
|
167
|
+
@conflict_vendors = {}
|
|
168
|
+
@warned_conflict ||= {}
|
|
169
|
+
to_warn = c.reject { |name, _| @warned_conflict[name] }
|
|
170
|
+
to_warn.each_key { |name| @warned_conflict[name] = true }
|
|
171
|
+
[to_warn]
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
conflicts.each do |name, hosts|
|
|
175
|
+
Apidepth.logger&.warn(
|
|
176
|
+
"[Apidepth] extra_vendors conflict: '#{name}' is configured as " \
|
|
177
|
+
"'#{hosts[:local]}' locally but the registry has '#{hosts[:remote]}' " \
|
|
178
|
+
"— registry takes precedence. Update your initializer or remove " \
|
|
179
|
+
"the entry from your dashboard at www.apidepth.io."
|
|
180
|
+
)
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
82
184
|
def self.load_from_disk
|
|
83
185
|
path = Apidepth.configuration.registry_cache_path
|
|
84
186
|
|
|
@@ -115,6 +217,12 @@ module Apidepth
|
|
|
115
217
|
# public class methods regardless of placement inside a private block.
|
|
116
218
|
# private_class_method is the correct idiom.
|
|
117
219
|
private_class_method :start_refresh_thread, :fetch_remote,
|
|
118
|
-
:load_from_disk, :validate_cache_path
|
|
220
|
+
:load_from_disk, :validate_cache_path!,
|
|
221
|
+
:apply_customer_vendors, :emit_warnings,
|
|
222
|
+
:emit_stale_warnings, :emit_conflict_warnings
|
|
223
|
+
|
|
224
|
+
# Mutex protecting @conflict_vendors, @warned_stale, and @warned_conflict.
|
|
225
|
+
# Initialized at require time like VendorRegistry's own @mutex.
|
|
226
|
+
@mutex = Mutex.new
|
|
119
227
|
end
|
|
120
228
|
end
|
data/lib/apidepth/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: apidepth
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Apidepth
|
|
@@ -93,8 +93,7 @@ dependencies:
|
|
|
93
93
|
- - "~>"
|
|
94
94
|
- !ruby/object:Gem::Version
|
|
95
95
|
version: '1.65'
|
|
96
|
-
description:
|
|
97
|
-
Know if your API slowness is your code or the vendor's. Apidepth instruments
|
|
96
|
+
description: Know if your API slowness is your code or the vendor's. Apidepth instruments
|
|
98
97
|
Net::HTTP to track real production latency to Stripe, OpenAI, Twilio and others
|
|
99
98
|
— then benchmarks your p95 against anonymized fleet data so you can see if it's
|
|
100
99
|
you, or everyone.
|
|
@@ -121,9 +120,9 @@ licenses:
|
|
|
121
120
|
- MIT
|
|
122
121
|
metadata:
|
|
123
122
|
homepage_uri: https://apidepth.io
|
|
124
|
-
source_code_uri: https://github.com/
|
|
125
|
-
changelog_uri: https://github.com/
|
|
126
|
-
bug_tracker_uri: https://github.com/
|
|
123
|
+
source_code_uri: https://github.com/cmwright33/apidepth-ruby
|
|
124
|
+
changelog_uri: https://github.com/cmwright33/apidepth-ruby/blob/main/CHANGELOG.md
|
|
125
|
+
bug_tracker_uri: https://github.com/cmwright33/apidepth-ruby/issues
|
|
127
126
|
rubygems_mfa_required: 'true'
|
|
128
127
|
rdoc_options: []
|
|
129
128
|
require_paths:
|