Skip to content

The run card: plan, progress and verdict on every thumbnail run ​

Requires BSI 5.0.0 or later

Earlier versions print an unstructured log stream, and several log lines changed — see log lines your scripts may grep for below.

Every qseow create-sheet-thumbnails, qscloud create-sheet-thumbnails, qseow remove-sheet-icons and qscloud remove-sheet-icons run prints a run card. Both dry and real runs open with a framed header and a PLAN block before anything is changed. A real run then adds countable progress lines while it works (app 2/3, sheet 4/11) and closes with a RESULT verdict; a dry run instead ends with the per-sheet decision report described on Dry Runs — no RESULT block, since nothing was attempted. The output is plain text through the normal log stream, so it lands unchanged in a file redirected from Windows Task Scheduler, in docker logs, and in CI transcripts. No new options are needed; there is nothing to configure.

On an interactive colour terminal at least 72 characters wide, these runs show the same plan and verdict as a colour board instead — see The Contact Sheet. Redirected and scheduled runs always get the plain card described on this page.

Why it exists ​

Butler Sheet Icons overwrites sheet thumbnails in place, with no undo. Before the run card, a run announced a version number and started writing: which apps were selected and why, what the exclude and blur rules actually matched, and where the images would go were all discoverable only by watching them happen. A run in which 20 thumbnails were written and a run in which a mistyped tag matched nothing ended identically — silently, both with exit code 0.

The run card answers the three questions a run raises, in order:

MomentQuestion it answers
PLANWhat is about to be changed, where, and why those apps?
ProgressIs it alive, how far in, and on what?
RESULTWhat actually changed, and did it work?

What a run looks like ​

Sample generated from the real renderer (QSEoW, three apps selected by a tag plus one named directly). Shown with log timestamps disabled — see Log timestamps below.

text
============================================================
 BUTLER SHEET ICONS x.y.z -- QSEoW sheet thumbnails
============================================================

PLAN
  server        sense.company.com   https, no virtual proxy
                engine 4747, qrs 4242, schema 12.612.0
  api user      INTERNAL\sa_api via ./cert/client.pem
  logon user    COMPANY\bsi_svc
  apps          3   1 named by --appid, 3 matched by --qliksensetag "sheet-thumbnails", 1 selected twice
  sheet part    2 of 4 -- objects + sheet title
  exclude       tag "no-thumbnail" (0 sheets), number 1
  blur          tag "confidential" (2 sheets)
  browser       chrome (version: recommended), headless, 5s per sheet
  images        ./img/qseow/<app-id>
  uploads to    content library "Butler sheet thumbnails"
  WILL OVERWRITE existing sheet thumbnails in 3 app(s), 2 of them published

app 1/3  c840670c-7178-4a5e-8c5d-2d3e5b0f9a12
  "Sales Discovery" -- 11 sheet(s), published
  sheet  1/11  excluded  'Scratch pad'  (--exclude-sheet-number)
  sheet  2/11  captured  'Overview'
  sheet  3/11  blurred   'Board pack'  (--blur-sheet-tag)
  sheet  4/11  captured  'Revenue by region'
  ...
  uploaded 20 image file(s) to content library "Butler sheet thumbnails"
  updated 10 of 11 sheet(s) with new thumbnails

  ...two more apps...

RESULT  ok
  apps          3 ok, 0 failed
  sheets        25 seen, 22 captured (2 blurred), 3 excluded
  thumbnails    22 sheet(s) given new thumbnails in content library "Butler sheet thumbnails"
  images kept   ./img/qseow   44 file(s), 2.6 MB
  elapsed       4m 41s
============================================================

Points worth knowing:

  • The match counts in the PLAN block include zeroes. tag "no-thumbnail" (0 sheets) printed before the first write is the cheapest possible "check your spelling" — a mistyped tag used to produce a run byte-identical to one where the option was never passed. Match counts are shown for tag rules on client-managed Qlik Sense; number, title and status rules are listed without counts because they are evaluated per sheet during the run. Qlik Sense Cloud has no sheet tags, so its plans show only number, title and status rules. See Sheet exclusion and Sheet blurring for the rules themselves.
  • The WILL OVERWRITE line is the warning there was no room for before. There is no undo for a thumbnail update. On a dry run the same line reads WOULD OVERWRITE. For qscloud remove-sheet-icons it reads WILL REMOVE sheet icons and thumbnail media files from N app(s).
  • Progress is countable. A run that hangs now hangs somewhere nameable. Sheet lines print when a sheet completes — they state facts, not intentions — so a hang is on the sheet after the last printed line: a log ending at sheet 7/11 captured ... means the run is stuck working on sheet 8 (a log with an app 2/3 line and no sheet lines yet is stuck opening that app or capturing its first sheet). Every sheet line names the option responsible for a non-default decision.
  • The RESULT block is new. There was previously no success summary at all. RESULT FAILED with 1 ok, 1 failed also appears when some apps failed — the per-app error lines above it carry the details. A selection that matched nothing ends with RESULT FAILED and apps 0 selected - nothing was done, and the run exits 1 as before. Scope of the guarantee: the PLAN and RESULT blocks render once app processing is reached. A run that aborts before that point — a failed connection test, missing certificates, a missing content library, an invalid option — exits 1 with the header and the error lines but no RESULT block, so a wrapper script should treat exit code 1 as the failure signal and the RESULT line as a summary, not as the only marker.
  • The browser line shows the version as requested (for example recommended or a pinned build id). The build actually used is still logged at launch, since resolving it may involve the download cache or the network. See Browser management.
  • The PLAN block appears after the first few connection lines (certificate check, content library check, tag lookup) because the app selection has to be resolved first — but always before anything is written.

Plain ASCII on purpose ​

The frame — headings, rules, labels — is deliberately plain ASCII with no colour, so the run card survives legacy Windows consoles, non-UTF-8 code pages, and redirection to files, byte for byte. App and sheet names are your data and are printed exactly as they are, including any non-ASCII characters.

Interaction with BSI_LOG_TIMESTAMPS ​

Each line goes through the normal log stream, so by default it carries the timestamp-and-level prefix. The blocks line up either way, but the card is easiest to read with the prefix off, which is what the sample above shows:

powershell
$env:BSI_LOG_TIMESTAMPS = "false"
butler-sheet-icons.exe qseow create-sheet-thumbnails --host sense.company.com ...
bash
BSI_LOG_TIMESTAMPS=false ./butler-sheet-icons qseow create-sheet-thumbnails --host sense.company.com ...

In a scheduler that already timestamps every captured line, disabling the built-in prefix avoids double timestamps and keeps the plan and verdict columns aligned. See Timestamps in log output for the full behaviour of the switch.

Log levels ​

  • On a dry run, the plan and the dry-run report are the product of the command, so they are printed even at --log-level warn or error.
  • On a real run, the whole run card — header, PLAN, progress and RESULT — logs at info. A real run of the four thumbnail commands at --log-level warn stays quiet — choosing a quiet level is respected. (The other commands — browser, doctor, qscloud list-collections — print their header regardless of level, as the old App version: line always did.)
  • At --log-level verbose and below, the detailed per-sheet lines (sheet id, engine sheet id, description, approved, published, hidden) are still available — they moved there rather than being removed.

When a run stops before the header ​

Requires BSI 5.4.0 or later

Earlier versions print the error on its own, with no version anywhere in the output.

The header is where a run names its version, and the version is the first thing to include when you report a problem. Some runs never get that far: a required option is missing, an option is misspelled, or a value is not one Butler Sheet Icons accepts. Such a run prints a single version line just before its error, so the version is there exactly when something went wrong. This applies to every command, not only the four that print a run card.

Leaving out a required option, for example:

text
butler-sheet-icons x.y.z - built yyyy-mm-dd
error: required option '--host <host>' not specified
  • The line is what --version reports, folded onto one line. The downloadable executables include the date they were built, as above. The Docker image runs from source and has no build date, so its line is butler-sheet-icons x.y.z on its own.
  • On a terminal, a blank line comes first, separating the failure from the command you typed. When the output goes to a log file, a scheduler or another program, there is no blank line: just the version line and the error.
  • It is printed whatever --log-level is set to, even error.
  • Nothing else changes. The error text is the same as before, and the run still ends with exit code 1; see Exit codes.
  • A run that gets as far as its header does not add the line, even if it fails later. Usually the header has shown the version by then. The exception is the create-sheet-thumbnails and remove-sheet-icons commands at --log-level warn or error, which print no header (see Log levels): when one of those runs fails, its output has no version anywhere, so run butler-sheet-icons --version and include what it prints.

When reporting a problem

Copy the version line along with the error. It tells whoever helps you which build produced the message.

Breaking change: log lines that scripts may grep for ​

Anyone parsing Butler Sheet Icons log output should note:

BeforeNow
App version: <version> (printed by every command)The framed header: BUTLER SHEET ICONS <version> -- <job>
-------------------------------------------------- + About to process app <id>app 1/3 <id> (dry runs: plan app 1/3 <id>)
App name: "..." / App is published: ... / Number of sheets in app: N at infoOne line: "App name" -- N sheet(s), published (individual lines still at verbose)
Processing sheet 1: '...', sheet id '...', engine sheet id '...', ... (~230 columns)sheet 1/11 captured '...' (long form at verbose)
Excluded sheet: 1: '...'sheet 1/11 excluded '...' (--exclude-sheet-...)
Done processing app <id> at infoAt verbose; the RESULT block closes the run instead
Uploading images to Qlik Sense content library: ... / Uploading images in folder: ... (client-managed)uploaded N image file(s) to content library "..." (details at verbose)
Uploading images in folder: ... / Uploading file: <name> (Cloud, per file at info)uploaded thumbnails for N sheet(s) to the app's media library (per-file lines at verbose)
Number of sheets: N / Using blurred thumbnail for sheet N: ... / Using regular thumbnail for sheet N: ... / Skipping update of sheet N: ... (update step, both platforms)updated N of M sheet(s) with new thumbnails (per-sheet choices at verbose; the sheet lines above already say blurred)
Removing icon for sheet N: Name '...', ID ..., description '...' (qscloud remove-sheet-icons, per sheet at info)sheet 1/9 cleared '...' or sheet 2/9 no icon '...' (no icon currently set) (long form at verbose)
nothing (remove-sheet-icons media cleanup was silent at info)deleted N thumbnail media file(s) from the app media library per app
nothingRESULT ok / RESULT FAILED block closing every real run that reaches app processing (pre-loop aborts exit 1 with error lines and no RESULT — key wrappers on the exit code)

Exit codes are unchanged: 0 on success, 1 when anything failed or the selection was empty.

Released under the MIT License.