Module: FiberAudit::Runtime::JSONL::Schema
- Defined in:
- lib/fiber_audit/runtime/jsonl/schema.rb
Overview
Versioned builders and validators stay together to keep one schema authority. rubocop:disable Metrics/ModuleLength
Constant Summary collapse
- SCHEMA_VERSION =
'1.0'- RECORD_TYPES =
%w[session_start event session_end].freeze
- ENVELOPE_KEYS =
%w[ schema_version record_type session_id sequence recorded_at monotonic_ns payload ].freeze
- POLICY_KEYS =
%w[ redaction sampling_rate max_events_per_second max_events_per_session max_record_bytes max_session_bytes fail_open ].freeze
- EVENT_KEYS =
%w[ kind source duration_ns operation location execution_context thread_id fiber_id measurements ].freeze
- LOCATION_KEYS =
%w[path line column].freeze
- END_KEYS =
%w[status events_observed events_emitted dropped internal_errors].freeze
- DROPPED_KEYS =
%w[ sampling rate_limit session_event_limit session_byte_limit record_size_limit ].freeze
- UUID =
Validation::UUID
- TIMESTAMP =
/\A\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}Z\z/
Class Method Summary collapse
- .dump(record, max_record_bytes:) ⇒ Object
- .end_record(session_id:, sequence:, summary:) ⇒ Object
- .event_record(session_id:, sequence:, event:) ⇒ Object
- .start_record(session) ⇒ Object
- .validate!(record) ⇒ Object
Class Method Details
.dump(record, max_record_bytes:) ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/fiber_audit/runtime/jsonl/schema.rb', line 121 def dump(record, max_record_bytes:) validate!(record) unless max_record_bytes.is_a?(Integer) && max_record_bytes.positive? raise RuntimeContractError, 'max_record_bytes must be a positive Integer' end json = "#{::JSON.generate(record)}\n" if json.bytesize > max_record_bytes raise RuntimeSafetyError, "runtime JSONL record is #{json.bytesize} bytes; limit is #{max_record_bytes}" end json.freeze rescue ::JSON::GeneratorError => e raise RuntimeContractError, "runtime JSONL record is not JSON-safe: #{e.}" end |
.end_record(session_id:, sequence:, summary:) ⇒ Object
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/fiber_audit/runtime/jsonl/schema.rb', line 75 def end_record(session_id:, sequence:, summary:) require_type!(summary, SessionSummary, 'summary') build_record( record_type: 'session_end', session_id: session_id, sequence: sequence, recorded_at: summary.ended_at, monotonic_ns: summary.ended_monotonic_ns, payload: { 'status' => summary.status.to_s, 'events_observed' => summary.events_observed, 'events_emitted' => summary.events_emitted, 'dropped' => { 'sampling' => summary.sampled_out, 'rate_limit' => summary.rate_limited, 'session_event_limit' => summary.session_event_limited, 'session_byte_limit' => summary.session_byte_limited, 'record_size_limit' => summary.oversize }, 'internal_errors' => summary.internal_errors } ) end |
.event_record(session_id:, sequence:, event:) ⇒ Object
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/fiber_audit/runtime/jsonl/schema.rb', line 53 def event_record(session_id:, sequence:, event:) require_type!(event, Event, 'event') build_record( record_type: 'event', session_id: session_id, sequence: sequence, recorded_at: event.occurred_at, monotonic_ns: event.monotonic_ns, payload: { 'kind' => event.kind.to_s, 'source' => event.source.to_s, 'duration_ns' => event.duration_ns, 'operation' => event.operation, 'location' => location_payload(event.location), 'execution_context' => event.execution_context.to_s, 'thread_id' => event.thread_id, 'fiber_id' => event.fiber_id, 'measurements' => event.measurements } ) end |
.start_record(session) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/fiber_audit/runtime/jsonl/schema.rb', line 37 def start_record(session) require_type!(session, Session, 'session') build_record( record_type: 'session_start', session_id: session.id, sequence: 0, recorded_at: session.started_at, monotonic_ns: session.started_monotonic_ns, payload: { 'tool_version' => session.tool_version, 'ruby_version' => session.ruby_version, 'policy' => policy_payload(session.policy) } ) end |
.validate!(record) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/fiber_audit/runtime/jsonl/schema.rb', line 99 def validate!(record) require_exact_keys!(record, ENVELOPE_KEYS, 'record') require_value!(record['schema_version'] == SCHEMA_VERSION, 'schema_version must be 1.0') require_value!(RECORD_TYPES.include?(record['record_type']), 'record_type is invalid') validate_uuid!(record['session_id']) validate_sequence!(record['sequence'], record['record_type']) (record['recorded_at'], 'recorded_at') require_non_negative_integer!(record['monotonic_ns'], 'monotonic_ns') case record['record_type'] when 'session_start' then validate_start_payload!(record['payload']) when 'event' then validate_event_payload!(record) when 'session_end' then validate_end_payload!(record) end record rescue RuntimeContractError raise rescue StandardError => e raise RuntimeContractError, "invalid runtime JSONL record: #{e.}" end |