nurse_andrea 0.2.3 → 0.2.4
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/nurse_andrea/configuration.rb +4 -1
- data/lib/nurse_andrea/continuous_scanner.rb +92 -0
- data/lib/nurse_andrea/railtie.rb +6 -0
- data/lib/nurse_andrea/version.rb +1 -1
- data/lib/nurse_andrea.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: 7af261428fe8313fb24aa0c2a90ba94a14791040d1c83cd3bb52ee743f6a3e58
|
|
4
|
+
data.tar.gz: 0ef0cb18d33855bf8c510cc7da7ced9e0bfc7d67603add9bc739e1cb7b3809a0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4e7b22b9c82fb8f952148d7b5c30ba0cee5714f2b596631f5f89ef6618887a6cd86f4556ec456811b68eae92be802a32eb9cc86f360d93c5f9bba68dfe3e5385
|
|
7
|
+
data.tar.gz: 5c28c6a373e0c22582006ddfe5a237a5b99e57efc2f37bb786985db5a724d07894443891846043f5e29b41debde88cf969372e477fc4f80575d1cd81b02a6025
|
|
@@ -6,7 +6,8 @@ module NurseAndrea
|
|
|
6
6
|
:sdk_version, :sdk_language,
|
|
7
7
|
:hooks_enabled, :hooks_database, :hooks_cache,
|
|
8
8
|
:hooks_jobs, :hooks_mailer, :hook_interval_ms,
|
|
9
|
-
:platform_detection, :service_discovery, :auto_connect
|
|
9
|
+
:platform_detection, :service_discovery, :auto_connect,
|
|
10
|
+
:disable_continuous_scan, :continuous_scan_interval
|
|
10
11
|
|
|
11
12
|
LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3, fatal: 4 }.freeze
|
|
12
13
|
DEFAULT_HOST = "https://nurseandrea.io"
|
|
@@ -33,6 +34,8 @@ module NurseAndrea
|
|
|
33
34
|
@platform_detection = true
|
|
34
35
|
@service_discovery = true
|
|
35
36
|
@auto_connect = false
|
|
37
|
+
@disable_continuous_scan = false
|
|
38
|
+
@continuous_scan_interval = 5 * 60 # seconds
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
alias_method :token, :api_key
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# PRIVACY: Same guarantees as ManagedServiceScanner — only derived
|
|
2
|
+
# metadata is transmitted, never raw env values. See
|
|
3
|
+
# DATA_PRIVACY_POLICY.rb for the full policy.
|
|
4
|
+
#
|
|
5
|
+
# Periodically re-runs the env-based discovery scan so dependencies
|
|
6
|
+
# added after boot (new env vars, services attached to running
|
|
7
|
+
# instances, configuration reloads) eventually surface as
|
|
8
|
+
# discoveries on the workspace dashboard.
|
|
9
|
+
#
|
|
10
|
+
# Properties guaranteed by the contract below:
|
|
11
|
+
# * Non-blocking — runs on a dedicated background thread, never on
|
|
12
|
+
# the request path.
|
|
13
|
+
# * Bounded — only one thread; calling start! twice is a no-op.
|
|
14
|
+
# * Fail-safe — any error inside the scan is swallowed; the host
|
|
15
|
+
# application never crashes from a discovery error.
|
|
16
|
+
# * Self-aware — short-circuits when SelfFilter.platform_self?
|
|
17
|
+
# because every URL would be NurseAndrea's own infra.
|
|
18
|
+
# * Stoppable — explicit stop! signals the thread to exit at the
|
|
19
|
+
# next sleep boundary; configuration.disable_continuous_scan
|
|
20
|
+
# prevents start! from creating the thread at all.
|
|
21
|
+
#
|
|
22
|
+
# Fork-safety note: the thread does NOT survive Process._fork (Puma
|
|
23
|
+
# clustered mode, Sidekiq workers). If the host forks after boot, the
|
|
24
|
+
# parent's scanner thread is gone and a new one is not auto-started.
|
|
25
|
+
# Address in a follow-up if it shows up in practice — for one-off
|
|
26
|
+
# webservers and single-process deployments the current design is
|
|
27
|
+
# sufficient.
|
|
28
|
+
|
|
29
|
+
module NurseAndrea
|
|
30
|
+
class ContinuousScanner
|
|
31
|
+
@thread = nil
|
|
32
|
+
@stop = false
|
|
33
|
+
@mutex = Mutex.new
|
|
34
|
+
|
|
35
|
+
class << self
|
|
36
|
+
attr_reader :thread
|
|
37
|
+
|
|
38
|
+
def start!
|
|
39
|
+
@mutex.synchronize do
|
|
40
|
+
return if @thread&.alive?
|
|
41
|
+
return if NurseAndrea.config.disable_continuous_scan
|
|
42
|
+
|
|
43
|
+
@stop = false
|
|
44
|
+
@thread = Thread.new { run_loop }
|
|
45
|
+
@thread.name = "nurse_andrea_continuous_scanner"
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def stop!
|
|
50
|
+
@mutex.synchronize do
|
|
51
|
+
@stop = true
|
|
52
|
+
end
|
|
53
|
+
@thread&.wakeup rescue nil
|
|
54
|
+
@thread&.join(2)
|
|
55
|
+
@thread = nil
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def running?
|
|
59
|
+
@thread&.alive? == true
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Public so specs can call it without spinning the loop.
|
|
63
|
+
def rescan_safely
|
|
64
|
+
return if NurseAndrea::SelfFilter.platform_self?
|
|
65
|
+
|
|
66
|
+
discoveries = NurseAndrea::ManagedServiceScanner.scan
|
|
67
|
+
return if discoveries.empty?
|
|
68
|
+
|
|
69
|
+
# Only push new items — ManagedServiceScanner already dedups
|
|
70
|
+
# by (type, tech, provider) within a single call, so we just
|
|
71
|
+
# need to avoid resubmitting items already queued for the
|
|
72
|
+
# current flush.
|
|
73
|
+
existing_keys = NurseAndrea.component_discoveries.map { |d| [ d[:type], d[:tech], d[:provider] ] }
|
|
74
|
+
discoveries.reject! { |d| existing_keys.include?([ d[:type], d[:tech], d[:provider] ]) }
|
|
75
|
+
NurseAndrea.component_discoveries.concat(discoveries) if discoveries.any?
|
|
76
|
+
rescue => e
|
|
77
|
+
NurseAndrea.debug("[ContinuousScanner] error: #{e.class}: #{e.message}")
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def run_loop
|
|
83
|
+
interval = NurseAndrea.config.continuous_scan_interval
|
|
84
|
+
until @stop
|
|
85
|
+
sleep interval
|
|
86
|
+
break if @stop
|
|
87
|
+
rescan_safely
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
data/lib/nurse_andrea/railtie.rb
CHANGED
|
@@ -45,6 +45,11 @@ module NurseAndrea
|
|
|
45
45
|
discoveries = NurseAndrea::ManagedServiceScanner.scan
|
|
46
46
|
NurseAndrea.component_discoveries.concat(discoveries)
|
|
47
47
|
NurseAndrea.debug("[NurseAndrea] Discovered #{discoveries.size} managed services")
|
|
48
|
+
|
|
49
|
+
# Periodic rescan — picks up dependencies added after boot
|
|
50
|
+
# (env reloads, attached services). Respects
|
|
51
|
+
# disable_continuous_scan and SelfFilter short-circuit.
|
|
52
|
+
NurseAndrea::ContinuousScanner.start!
|
|
48
53
|
end
|
|
49
54
|
|
|
50
55
|
# Hook subscriptions (sql.active_record, cache_*, perform.active_job, etc.)
|
|
@@ -60,6 +65,7 @@ module NurseAndrea
|
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
at_exit do
|
|
68
|
+
NurseAndrea::ContinuousScanner.stop! rescue nil
|
|
63
69
|
NurseAndrea::MemorySampler.stop rescue nil
|
|
64
70
|
NurseAndrea::LogShipper.instance.flush! rescue nil
|
|
65
71
|
NurseAndrea::MetricsShipper.instance.flush! rescue nil
|
data/lib/nurse_andrea/version.rb
CHANGED
data/lib/nurse_andrea.rb
CHANGED
|
@@ -17,6 +17,7 @@ require "nurse_andrea/instrumentation_subscriber"
|
|
|
17
17
|
require "nurse_andrea/memory_sampler"
|
|
18
18
|
require "nurse_andrea/deploy"
|
|
19
19
|
require "nurse_andrea/self_filter"
|
|
20
|
+
require "nurse_andrea/continuous_scanner"
|
|
20
21
|
|
|
21
22
|
require "nurse_andrea/railtie" if defined?(Rails::Railtie)
|
|
22
23
|
require "nurse_andrea/engine" if defined?(Rails::Engine)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: nurse_andrea
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ago AI LLC
|
|
@@ -28,6 +28,7 @@ files:
|
|
|
28
28
|
- lib/nurse_andrea/backfill.rb
|
|
29
29
|
- lib/nurse_andrea/component_telemetry.rb
|
|
30
30
|
- lib/nurse_andrea/configuration.rb
|
|
31
|
+
- lib/nurse_andrea/continuous_scanner.rb
|
|
31
32
|
- lib/nurse_andrea/deploy.rb
|
|
32
33
|
- lib/nurse_andrea/engine.rb
|
|
33
34
|
- lib/nurse_andrea/http_client.rb
|