nurse_andrea 0.2.3 → 0.2.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ae308e57dd4f7a8bf6182f34e49a8223cc695448e9a0ef0146b37396e6deea19
4
- data.tar.gz: 7323b870d40f057ac56130b11061ca84bb9d9db9f97f61697c1234d392df296b
3
+ metadata.gz: c6b94793dda326f7f9733ff52b0c6186ce4d8d5ec638f939ef7f18db382890e0
4
+ data.tar.gz: f49b5d9bdaffc62d0752988213dfe37b8868f1ca792ebce9fc7819ead551e4a1
5
5
  SHA512:
6
- metadata.gz: 4848f27cff94597a94a21b6fe366da00c547831aad652717e59a41255d25005142bf6a1b8fb9181f37a7358ee88e08e4e597b5e1c83cdff8da052ea716c2b583
7
- data.tar.gz: f01a8a679ddcd4be389125c43ca2cfeca6703acc5dcf29f53a392896406f6384e87aaba578d24fd86d4a8e474400779c47dd2e02b02e3b751131458a604c7ee2
6
+ metadata.gz: c4d4f410da8ca576d2465b1e54df730ad1bfb7305537b5045e2571088c131ace035691c0dbe37a31dd9a807cfd32a770f751cbb5a85b736b45a64aa88a48f9d9
7
+ data.tar.gz: 8fbefdc77087c52bf2e9bbb4d7ae60a16a46bfc8dac69865180a926a76288f22ab1bba5934cfc548b762833b8d1bcaa7588a5326156d703415e18ac0ab53c0db
@@ -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
@@ -71,7 +71,10 @@ module NurseAndrea
71
71
  level: e[:level],
72
72
  message: e[:message],
73
73
  occurred_at: e[:timestamp],
74
- source: NurseAndrea.config.service_name || "nurse_andrea_gem",
74
+ # Per-entry source override (e.g. for cross-service cascade
75
+ # detection from a single integration) takes precedence; fall
76
+ # back to the configured service_name, then a static default.
77
+ source: e[:source] || NurseAndrea.config.service_name || "nurse_andrea_gem",
75
78
  batch_id: SecureRandom.uuid,
76
79
  payload: e[:metadata] || {}
77
80
  }
@@ -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
@@ -1,3 +1,3 @@
1
1
  module NurseAndrea
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.5"
3
3
  end
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)
data/nurse_andrea.gemspec CHANGED
@@ -14,8 +14,8 @@ Gem::Specification.new do |spec|
14
14
 
15
15
  spec.metadata = {
16
16
  "homepage_uri" => spec.homepage,
17
- "source_code_uri" => "https://github.com/narteyb/nurse-andrea",
18
- "changelog_uri" => "https://github.com/narteyb/nurse-andrea/blob/main/gems/nurse_andrea/CHANGELOG.md",
17
+ "source_code_uri" => "https://github.com/narteyb/nurse-andrea-sdks",
18
+ "changelog_uri" => "https://github.com/narteyb/nurse-andrea-sdks/blob/main/packages/ruby/CHANGELOG.md",
19
19
  "rubygems_mfa_required" => "true"
20
20
  }
21
21
 
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.3
4
+ version: 0.2.5
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
@@ -52,8 +53,8 @@ licenses:
52
53
  - MIT
53
54
  metadata:
54
55
  homepage_uri: https://nurseandrea.io
55
- source_code_uri: https://github.com/narteyb/nurse-andrea
56
- changelog_uri: https://github.com/narteyb/nurse-andrea/blob/main/gems/nurse_andrea/CHANGELOG.md
56
+ source_code_uri: https://github.com/narteyb/nurse-andrea-sdks
57
+ changelog_uri: https://github.com/narteyb/nurse-andrea-sdks/blob/main/packages/ruby/CHANGELOG.md
57
58
  rubygems_mfa_required: 'true'
58
59
  rdoc_options: []
59
60
  require_paths: