Class: Textus::Read::Audit
- Inherits:
-
Object
- Object
- Textus::Read::Audit
- Defined in:
- lib/textus/read/audit.rb
Overview
Queries .textus/audit.log. Filters: key, zone, role, verb, since, correlation_id, limit. Reads the log file as JSON-Lines (legacy TSV rows produce nil and are skipped).
Defined Under Namespace
Classes: Query
Class Method Summary collapse
-
.parse_since(str, now: Time.now.utc) ⇒ Object
Accepts ISO8601 (“2026-01-15”, “2026-01-15T10:00:00Z”) or a relative offset matching /A(d+)()z/.
Instance Method Summary collapse
- #call(**filters) ⇒ Object
-
#initialize(container:, call: nil) ⇒ Audit
constructor
rubocop:disable Lint/UnusedMethodArgument.
Constructor Details
#initialize(container:, call: nil) ⇒ Audit
rubocop:disable Lint/UnusedMethodArgument
33 34 35 36 37 38 |
# File 'lib/textus/read/audit.rb', line 33 def initialize(container:, call: nil) # rubocop:disable Lint/UnusedMethodArgument @manifest = container.manifest @root = container.root @log_path = File.join(container.root, "audit.log") @audit_log = container.audit_log end |
Class Method Details
.parse_since(str, now: Time.now.utc) ⇒ Object
Accepts ISO8601 (“2026-01-15”, “2026-01-15T10:00:00Z”) or a relative offset matching /A(d+)()z/. Returns nil for unparseable input.
65 66 67 68 69 70 71 72 |
# File 'lib/textus/read/audit.rb', line 65 def self.parse_since(str, now: Time.now.utc) return nil if str.nil? || str.empty? return Time.parse(str) if str =~ /\A\d{4}-\d{2}-\d{2}/ m = str.match(/\A(\d+)([smhd])\z/) or return nil mult = { "s" => 1, "m" => 60, "h" => 3600, "d" => 86_400 }[m[2]] now - (m[1].to_i * mult) end |
Instance Method Details
#call(**filters) ⇒ Object
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/textus/read/audit.rb', line 40 def call(**filters) query = Query.build(**filters) check_cursor_expiry!(query.seq_since) files = all_log_files return [] if files.empty? rows = [] files.each do |file| File.foreach(file) do |line| parsed = parse_row(line.chomp) next unless parsed next unless query.matches?(parsed) next if query.zone && !key_in_zone?(parsed["key"], query.zone) rows << parsed break if limit_reached?(rows, query) end break if limit_reached?(rows, query) end rows end |