Module: Agentilda::ProgressLog
- Defined in:
- lib/agentilda/progress_log.rb
Overview
One line of run --log FILE, laid out as fixed-width columns.
The log file is the only record of a headless run, and it is shared: two
agentilda run invocations pointed at the same --log both append to
it, interleaved, and so does every round within one run. That is what the
process id column is for. Without it a reader cannot tell one run's agents
from another's, and "started 003.00" twice looks like a bug rather than two
machines doing the same work.
Fixed columns are what make the file readable by eye and by awk alike. A
value wider than its column is cut rather than allowed to push the columns
out, and a value that is missing still occupies its width, so a round header
with no plan or agent of its own lines up with the lines underneath it.
Constant Summary collapse
- TIME_FORMAT =
Wall clock only. A log line answers "when", and the date is the file's.
"%H:%M:%S"- TIME_WIDTH =
Width of TIME_FORMAT's output.
8- PLAN_WIDTH =
"003.00".
6- STATUS_WIDTH =
Derived from the widest state as Status#to_s renders it, emoji included, so a state added to STATUSES with a longer label cannot silently knock the columns after it out of line — then trimmed by five cells: the emoji already names the state, so the longest labels can afford to lose their tails to keep the line short.
STATUSES.map { |status| UI.display_width(status.to_s) }.max - 5
- AGENT_WIDTH =
The longest specialist name in
agents/ispalpatine-plannerat 17, and the names are hyphenated words rather than a bounded vocabulary, so this leaves room for one more without a reflow. 20- PID_WIDTH =
Enough for a 32-bit process id, right justified.
7- ROUND_WIDTH =
"01". Rounds cap at two digits; a run that reaches a third has bigger problems than this column.
2- SECONDS_WIDTH =
" 907s". Anything longer than four digits of seconds is an agent nobody is still waiting on.
6- SEPARATOR =
Between columns, inside the brackets.
" | "- COLUMN_WIDTHS =
Cells from the opening bracket to the closing one, separators included. The message starts one space after this on every line, whatever fields that line happens to be missing, so a reader indenting a wrapped message has a number to indent by.
[TIME_WIDTH, PLAN_WIDTH, STATUS_WIDTH, AGENT_WIDTH, ROUND_WIDTH, PID_WIDTH, SECONDS_WIDTH].freeze
- LINE_WIDTH =
COLUMN_WIDTHS.sum + (SEPARATOR.length * (COLUMN_WIDTHS.size - 1)) + 2
Class Method Summary collapse
-
.duration(seconds) ⇒ String
Whole seconds with a trailing "s", or blank for nil.
-
.left(value, width) ⇒ String
Padded on the right to exactly
widthcells. -
.render(message, plan: nil, status: nil, agent: nil, seconds: nil, round: nil, pid: Process.pid, at: Time.now) ⇒ String
Render one log line: bracketed fixed-width columns, then the message.
-
.right(value, width) ⇒ String
UI.fit pads on the right, which is the wrong end for a number.
Class Method Details
.duration(seconds) ⇒ String
Returns whole seconds with a trailing "s", or blank for nil.
102 |
# File 'lib/agentilda/progress_log.rb', line 102 def duration(seconds) = seconds.nil? ? "" : "#{seconds.round}s" |
.left(value, width) ⇒ String
Returns padded on the right to exactly width cells.
107 |
# File 'lib/agentilda/progress_log.rb', line 107 def left(value, width) = UI.fit(value, width) |
.render(message, plan: nil, status: nil, agent: nil, seconds: nil, round: nil, pid: Process.pid, at: Time.now) ⇒ String
Render one log line: bracketed fixed-width columns, then the message.
No colour. The line goes to a file, where an escape sequence is neither readable nor the width it claims to be.
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/agentilda/progress_log.rb', line 83 def render(, plan: nil, status: nil, agent: nil, seconds: nil, round: nil, pid: Process.pid, at: Time.now) columns = [ left(at.strftime(TIME_FORMAT), TIME_WIDTH), left(plan, PLAN_WIDTH), left(status, STATUS_WIDTH), left(agent, AGENT_WIDTH), right(round, ROUND_WIDTH), right(pid, PID_WIDTH), right(duration(seconds), SECONDS_WIDTH) ] text = .to_s prefix = "[#{columns.join(SEPARATOR)}]" text.empty? ? prefix : "#{prefix} #{text}" end |
.right(value, width) ⇒ String
UI.fit pads on the right, which is the wrong end for a number. Fit first so an over-long value is still truncated to the column, then move the padding to the front.
116 117 118 119 |
# File 'lib/agentilda/progress_log.rb', line 116 def right(value, width) text = UI.fit(value, width).rstrip UI.fit("", width - UI.display_width(text)) + text end |