Module: FiberAudit::Runtime::Environment
- Defined in:
- lib/fiber_audit/runtime/environment.rb
Overview
rubocop:disable Metrics/ModuleLength
Defined Under Namespace
Classes: Settings
Constant Summary collapse
- PROTOCOL_VERSION =
1- ACTIVATION_KEY =
'FIBER_AUDIT_RUNTIME_BOOT'- SETTINGS_KEY =
'FIBER_AUDIT_RUNTIME_SETTINGS'- FAILURE_MODE_KEY =
'FIBER_AUDIT_RUNTIME_FAILURE_MODE'- WATCHDOG_SETTINGS_KEY =
'FIBER_AUDIT_RUNTIME_WATCHDOG_SETTINGS'- PROBES_KEY =
'FIBER_AUDIT_RUNTIME_PROBES'- BOOT_REQUIRE =
'-rfiber_audit/runtime/boot'- MAX_SETTINGS_BYTES =
16_384- MAX_WATCHDOG_SETTINGS_BYTES =
1_024- SETTINGS_KEYS =
%w[protocol_version launch_id project_root output_directory policy].freeze
- POLICY_KEYS =
%w[ redaction sampling_rate max_events_per_second max_events_per_session max_record_bytes max_session_bytes fail_open ].freeze
- WATCHDOG_KEYS =
%w[ protocol_version enabled heartbeat_interval_ms stall_threshold_ms max_frames ].freeze
Class Method Summary collapse
- .activated?(environment = ENV) ⇒ Boolean
- .build(policy:, output_directory:, project_root:, launch_id: SecureRandom.uuid) ⇒ Object
- .child_environment(settings:, watchdog_policy: nil, probes_enabled: false, base_environment: ENV, library_path: default_library_path) ⇒ Object
- .dump(settings) ⇒ Object
- .dump_watchdog_policy(policy) ⇒ Object
- .failure_mode(environment = ENV) ⇒ Object
- .load(environment = ENV) ⇒ Object
- .load_watchdog_policy(environment = ENV) ⇒ Object
- .normalize_directory(value, field) ⇒ Object
- .prepare_output_directory(path) ⇒ Object
- .probes_enabled?(environment = ENV) ⇒ Boolean
Class Method Details
.activated?(environment = ENV) ⇒ Boolean
149 150 151 152 153 154 155 |
# File 'lib/fiber_audit/runtime/environment.rb', line 149 def activated?(environment = ENV) marker = environment[ACTIVATION_KEY] return false if marker.nil? return true if marker == '1' raise RuntimeContractError, "#{ACTIVATION_KEY} must be 1" end |
.build(policy:, output_directory:, project_root:, launch_id: SecureRandom.uuid) ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/fiber_audit/runtime/environment.rb', line 57 def build(policy:, output_directory:, project_root:, launch_id: SecureRandom.uuid) Settings.new( protocol_version: PROTOCOL_VERSION, launch_id: launch_id, project_root: project_root, output_directory: output_directory, policy: policy ) end |
.child_environment(settings:, watchdog_policy: nil, probes_enabled: false, base_environment: ENV, library_path: default_library_path) ⇒ Object
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/fiber_audit/runtime/environment.rb', line 173 def child_environment( settings:, watchdog_policy: nil, probes_enabled: false, base_environment: ENV, library_path: default_library_path ) require_settings!(settings) require_watchdog_policy!(watchdog_policy) if watchdog_policy raise RuntimeContractError, 'probes_enabled must be a Boolean' unless [true, false].include?(probes_enabled) raise RuntimeContractError, 'base_environment must be a Hash-like object' unless base_environment.respond_to?(:[]) environment = { ACTIVATION_KEY => '1', SETTINGS_KEY => dump(settings), FAILURE_MODE_KEY => settings.policy.fail_open? ? 'open' : 'closed', 'RUBYOPT' => prepend_token(base_environment['RUBYOPT'], BOOT_REQUIRE, separator: ' '), 'RUBYLIB' => prepend_token(base_environment['RUBYLIB'], library_path, separator: File::PATH_SEPARATOR) } environment[WATCHDOG_SETTINGS_KEY] = dump_watchdog_policy(watchdog_policy) if watchdog_policy environment[PROBES_KEY] = '1' if probes_enabled environment.transform_values(&:freeze).freeze end |
.dump(settings) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/fiber_audit/runtime/environment.rb', line 67 def dump(settings) require_settings!(settings) payload = { 'protocol_version' => settings.protocol_version, 'launch_id' => settings.launch_id, 'project_root' => settings.project_root, 'output_directory' => settings.output_directory, 'policy' => policy_payload(settings.policy) } encoded = JSON.generate(payload) raise RuntimeSafetyError, 'runtime activation settings are too large' if encoded.bytesize > MAX_SETTINGS_BYTES encoded.freeze end |
.dump_watchdog_policy(policy) ⇒ Object
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/fiber_audit/runtime/environment.rb', line 109 def dump_watchdog_policy(policy) require_watchdog_policy!(policy) payload = { 'protocol_version' => PROTOCOL_VERSION, 'enabled' => policy.enabled, 'heartbeat_interval_ms' => policy.heartbeat_interval_ms, 'stall_threshold_ms' => policy.stall_threshold_ms, 'max_frames' => policy.max_frames } encoded = JSON.generate(payload) if encoded.bytesize > MAX_WATCHDOG_SETTINGS_BYTES raise RuntimeSafetyError, 'runtime watchdog activation settings are too large' end encoded.freeze end |
.failure_mode(environment = ENV) ⇒ Object
157 158 159 160 161 162 163 |
# File 'lib/fiber_audit/runtime/environment.rb', line 157 def failure_mode(environment = ENV) value = environment[FAILURE_MODE_KEY] return :open if value.nil? || value == 'open' return :closed if value == 'closed' raise RuntimeContractError, "#{FAILURE_MODE_KEY} must be open or closed" end |
.load(environment = ENV) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/fiber_audit/runtime/environment.rb', line 82 def load(environment = ENV) return unless activated?(environment) value = environment.fetch(SETTINGS_KEY) do raise RuntimeContractError, "missing runtime activation variable: #{SETTINGS_KEY}" end unless value.is_a?(String) && value.valid_encoding? && value.bytesize <= MAX_SETTINGS_BYTES raise RuntimeContractError, 'runtime activation settings are invalid' end payload = JSON.parse(value) require_exact_keys!(payload, SETTINGS_KEYS, 'runtime activation settings') policy_values = payload.fetch('policy') require_exact_keys!(policy_values, POLICY_KEYS, 'runtime activation policy') settings = Settings.new( protocol_version: payload.fetch('protocol_version'), launch_id: payload.fetch('launch_id'), project_root: payload.fetch('project_root'), output_directory: payload.fetch('output_directory'), policy: Policy.new(**symbolize_policy(policy_values)) ) validate_failure_mode!(environment, settings.policy) settings rescue JSON::ParserError, ArgumentError => e raise RuntimeContractError, "invalid runtime activation settings: #{e.}" end |
.load_watchdog_policy(environment = ENV) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
# File 'lib/fiber_audit/runtime/environment.rb', line 126 def load_watchdog_policy(environment = ENV) value = environment[WATCHDOG_SETTINGS_KEY] return WatchdogPolicy::DISABLED if value.nil? unless value.is_a?(String) && value.valid_encoding? && value.bytesize <= MAX_WATCHDOG_SETTINGS_BYTES raise RuntimeContractError, 'runtime watchdog activation settings are invalid' end payload = JSON.parse(value) require_exact_keys!(payload, WATCHDOG_KEYS, 'runtime watchdog activation settings') unless payload.fetch('protocol_version') == PROTOCOL_VERSION raise RuntimeContractError, "runtime watchdog activation protocol must be #{PROTOCOL_VERSION}" end WatchdogPolicy.new( enabled: payload.fetch('enabled'), heartbeat_interval_ms: payload.fetch('heartbeat_interval_ms'), stall_threshold_ms: payload.fetch('stall_threshold_ms'), max_frames: payload.fetch('max_frames') ) rescue JSON::ParserError, ArgumentError => e raise RuntimeContractError, "invalid runtime watchdog activation settings: #{e.}" end |
.normalize_directory(value, field) ⇒ Object
212 213 214 215 216 217 |
# File 'lib/fiber_audit/runtime/environment.rb', line 212 def normalize_directory(value, field) normalized = normalize_absolute_path(value, field) raise RuntimeContractError, "#{field} must be an existing directory" unless File.directory?(normalized) normalized.freeze end |
.prepare_output_directory(path) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/fiber_audit/runtime/environment.rb', line 197 def prepare_output_directory(path) normalized = normalize_absolute_path(path, 'output directory') if File.exist?(normalized) raise RuntimeSafetyError, "runtime output is not a directory: #{normalized}" unless File.directory?(normalized) return normalized end FileUtils.mkdir_p(normalized, mode: 0o700) File.chmod(0o700, normalized) normalized rescue SystemCallError => e raise RuntimeSafetyError, "cannot prepare runtime output directory: #{e.}" end |
.probes_enabled?(environment = ENV) ⇒ Boolean
165 166 167 168 169 170 171 |
# File 'lib/fiber_audit/runtime/environment.rb', line 165 def probes_enabled?(environment = ENV) value = environment[PROBES_KEY] return false if value.nil? return true if value == '1' raise RuntimeContractError, "#{PROBES_KEY} must be 1 when present" end |