module

Krikri::ProfileTasks

Emulation of the ansible.posix.profile_tasks aggregate callback (byte-shaped against ansible-core 2.19.11 + ansible.posix 2.1.0, live-verified): a timestamp line under every TASK / RUNNING HANDLER banner - <weekday> <day> <month> <year> <HH:MM:SS> <tz-offset> (<previous task's wall clock>) <running total> ****** - and a TASKS RECAP block after PLAY RECAP listing every tracked task sorted slowest first.

The real callback's own shape source (profile_tasks.py):

  • filled(msg): msg + " " then * padding out to 80 columns TOTAL, then one trailing space; the timestamp line is therefore always exactly 80 columns wide regardless of the tty width (the 79 in filled() is a literal, not Display.columns).
  • tasktime(): the parenthesized duration is the time elapsed since the PREVIOUS tasktime call (i.e. the previous task's wall clock, connection overhead included), the unpadded value is the running total since the module was imported (playbook start), separated by exactly seven spaces before filled adds its own.
  • Duration format H:MM:SS.mmm - hours are NOT zero-padded.
  • Timestamp format "%A %d %B %Y %H:%M:%S %z" - two spaces between the year and the clock, English weekday/month names.
  • TASKS RECAP: Display.banner("TASKS RECAP") (blank line + 80-wide banner), a tasktime line of its own, a full-width = rule, then one row per tracked task: name padded with dashes to Display.columns - 9 and X.XXs right-aligned in 9 columns with dashes, sorted by elapsed duration descending (stable - ties keep first-seen order), capped at 20 rows (the callback's default task_output_limit).
  • Handlers appear in the recap under their own names (live-verified), and looped tasks are one row total (one task, one entry).

Deliberately not implemented (see KNOWN_MISSING.md): the callback's own config surface (PROFILE_TASKS_TASK_OUTPUT_LIMIT, PROFILE_TASKS_SORT_ORDER, PROFILE_TASKS_SUMMARY_ONLY) and the -vv+ per-row task path: line.

Constants

FACTS_TASK_IDENTITY = Reference.new

Synthetic identity for the implicit Gathering Facts task - it is not a Task object in this engine, but it still gets its own recap row (live-verified).

RECAP_ROW_LIMIT = 20

The real callback's default task_output_limit.

Class methods

enable
Source
enabled?
Source
record_task_start(task, name : String) : Nil

One tracked task start: prints the timestamp line (under the banner the caller has just printed - the caller owns banner placement, so PLAY/PLAY RECAP banners stay unaffected), closes out the previous task's duration, and opens the new one. Called once per task (not per host), keyed by the Task object itself so serial: re-runs of the same task accumulate into one row, matching the real callback's per-UUID stats dict.

Source
seconds_to_str(total_ms : Int64) : String

The real callback's secondsToStr: %d:%02d:%02d.%03d - hours NOT zero-padded.

Source