#!/usr/bin/env ruby # frozen_string_literal: true # Deterministic sample-log generator for the Relaystation eval fixture. # Produces relay-*.log and worker-*.log files under logs/ (default: the # project root next to this script, or ARGV[0] if given). No Random, no # Time.now — every byte of output is a pure function of loop indices, so # running this script twice produces byte-identical files. TARGET_DIR = ARGV[0] || File.expand_path('..', __dir__) LOGS_DIR = File.join(TARGET_DIR, 'logs') Dir.mkdir(LOGS_DIR) unless Dir.exist?(LOGS_DIR) DAYS = %w[2026-07-01 2026-07-02 2026-07-03 2026-07-04].freeze TENANTS = %w[acme globex initech umbrella soylent].freeze SERVICES = %w[billing crm analytics email sms audit search webhooks reports].freeze WORKERS = %w[worker-1 worker-2 worker-3 worker-4 worker-5].freeze STEP_MS = 180 TOTAL_LINES = 760 def timestamp(date, index) total_ms = index * STEP_MS total_seconds = total_ms / 1000 ms = total_ms % 1000 hh = (total_seconds / 3600) % 24 mm = (total_seconds / 60) % 60 ss = total_seconds % 60 format('%s %02d:%02d:%02d.%03d', date, hh, mm, ss, ms) end def event_id(index) format('evt_%04d', index % 10_000) end def fmt_line(date, index, level, component, message) "#{timestamp(date, index)} #{level} [#{component}] #{message}\n" end def routine_relay_line(date, index) tenant = TENANTS[index % TENANTS.length] service = SERVICES[index % SERVICES.length] case index % 4 when 0 fmt_line(date, index, 'INFO', 'ingest', "event #{event_id(index)} accepted from tenant #{tenant}") when 1 fmt_line(date, index, 'INFO', 'dispatch', "event #{event_id(index)} delivered to service #{service}") when 2 fmt_line(date, index, 'INFO', 'auth', "signature verified for tenant #{tenant}") else fmt_line(date, index, 'DEBUG', 'metrics', "events.ingested=#{index}") end end def routine_worker_line(date, index) worker = WORKERS[index % WORKERS.length] case index % 3 when 0 fmt_line(date, index, 'INFO', 'worker', "#{worker} processed #{event_id(index)} in #{(index % 40) + 5}ms") when 1 fmt_line(date, index, 'DEBUG', 'heartbeat', "#{worker} heartbeat ok") else fmt_line(date, index, 'INFO', 'scaler', "pool size stable at #{WORKERS.length} workers") end end def write_relay_log(date, incident) path = File.join(LOGS_DIR, "relay-#{date}.log") File.open(path, 'w') do |f| (0...TOTAL_LINES).each do |index| f.write(incident.call(date, index) || routine_relay_line(date, index)) end end end def write_worker_log(date, incident) path = File.join(LOGS_DIR, "worker-#{date}.log") File.open(path, 'w') do |f| (0...TOTAL_LINES).each do |index| f.write(incident.call(date, index) || routine_worker_line(date, index)) end end end no_incident = ->(_date, _index) { nil } # 2026-07-01 — routine traffic, no incidents. write_relay_log('2026-07-01', no_incident) write_worker_log('2026-07-01', no_incident) # 2026-07-02 — relay: auth token expiry causes a 401 retry storm. # worker: normal. auth_storm = lambda do |date, index| next nil unless index >= 400 && index < 640 offset = index - 400 case offset % 3 when 0 fmt_line(date, index, 'WARN', 'auth', 'signature token expired for tenant acme') when 1 fmt_line(date, index, 'ERROR', 'dispatch', 'upstream responded 401') else attempt = ((offset / 3) % 8) + 1 fmt_line(date, index, 'INFO', 'retry', "scheduling retry (attempt #{attempt}) after 401") end end write_relay_log('2026-07-02', auth_storm) write_worker_log('2026-07-02', no_incident) # 2026-07-03 — routine traffic, no incidents. write_relay_log('2026-07-03', no_incident) write_worker_log('2026-07-03', no_incident) # 2026-07-04 — worker-3 dies, capacity drops, queue fills, events are # dropped. Worker heartbeat misses begin shortly before the relay's queue # depth escalation starts. worker_death = lambda do |date, index| if index >= 550 && index < 660 && (index - 550) % 20 == 0 fmt_line(date, index, 'WARN', 'heartbeat', 'worker-3 heartbeat missed') elsif index == 660 fmt_line(date, index, 'ERROR', 'worker', 'worker-3 marked dead') end end write_worker_log('2026-07-04', worker_death) queue_backup = lambda do |date, index| if index >= 600 && index < 700 step = index - 600 depth = 100 + (step * 4900 / 99) depth = 5000 if depth > 5000 fmt_line(date, index, 'WARN', 'queue', "queue depth #{depth}") elsif index >= 700 fmt_line(date, index, 'ERROR', 'dispatch', "DROPPED event #{event_id(index)} (queue full)") end end write_relay_log('2026-07-04', queue_backup) puts "wrote #{DAYS.length * 2} log files to #{LOGS_DIR}"