Nodes/From 3D to Campaign/Casa · log run
ComfyUI Node

Casa · log run

One JSON line per run, so the cost of your pipeline isn't a guess

By meryboth·Created 25 days ago·Updated 25 days ago· 0
Casa · log run
    • line
    ◄stagegraph_render►
    ◄item►
    ◄backend▾►
    ◄seconds0.0►
    ◄tokens_in0►
    ◄tokens_out0►
    ◄cost_usd0.0000►
    ◄notes►

    "It cost about a tenth of a cent per image, I think" is not a number. This node is how the pack's author got to a real one: the whole project - every benchmark, A/B, grid and rejected render included - came to $0.145, and $0.021 per approved piece, because every stage wrote a line into a file and the table was generated from those lines instead of estimated after the fact.

    CasaLogRun is that writer. It appends one JSON object to out/runs.jsonl and hands the same object back as a string.

    What lands in the file

    {"ts":"2026-09-25T14:22:07+00:00","stage":"graph_render","item":"street/restored",
     "backend":"local_comfyui","ms":133000,"tokens_in":0,"tokens_out":0,
     "cost_usd":0.0,"cache_hit":false,"source":"comfy_graph","notes":"PASS edge 0.882 ..."}
    

    Not glamorous, but it's the right shape: a timestamp in UTC, the stage, the item, which backend did the work, wall time in milliseconds (you type seconds, it multiplies by 1000), token counts, dollars, and a free-text notes field.

    The inputs

    stage defaults to graph_render and is the row key in the cost table - render, qa_gate, copy, layout, whatever vocabulary you use. item is the thing being logged (street/restored in the master graph). backend is a three-way enum: local_comfyui, comfy_cloud, partner_api.

    That enum isn't decoration. The three cost you different things, and conflating them is exactly how people end up with a useless spreadsheet. A local_comfyui row has no dollars attached - the cost is your electricity and your GPU seconds, which the pack's cost table prices at $0.10/kWh as a stand-in. A comfy_cloud row is rented GPU time (the table uses Comfy Cloud's RTX 6000 Pro rate of $3.49/hour). A partner_api row is metered credits against a pay-as-you-go balance that is separate from a Cloud subscription - so it's the row most likely to be the reason your run stopped. seconds is actually seconds as a float, tokens_in / tokens_out are ints for LLM stages, cost_usd takes four decimal places so you can log sub-cent amounts, and notes is multiline.

    The output and why it's an output node

    line is the JSON that was just written, so you can pipe it into a text display and watch runs accumulate in the console area. The node is also marked as an output node, which in ComfyUI means it always executes - you don't have to wire line to anything for the write to happen. That's the right call for a logger: wiring up a consumer just to get a side effect is a workflow smell.

    Why you'd actually bother

    Because it makes two cheap tricks available. First, wire CasaQAGate.report into notes - the pack's master graph does exactly this - and every run line carries its own gate verdict next to its cost. You stop keeping a separate QA spreadsheet. Second, run the pack's aggregator:

    python pipeline/cost_table.py
    

    That reads out/runs.jsonl, groups by stage and backend, counts cache hits and errors, totals energy and dollars, then writes docs/costs.md including the line that matters - cost per approved piece, computed from the approved list in config/approved.json. The published table also carries the gate's own scoreboard underneath, and it's the most useful number in the file: 6 of 18 verdicts passed across all attempts. Two thirds of the renders failed and got thrown away, and it still came to two cents a piece, because the expensive part was never the retry.

    Install

    It's part of the same pack: ComfyUI Manager → From 3D to Campaign, or git clone into ComfyUI/custom_nodes. No models, no extra packages - it's stdlib JSON and file appends.

    Gotchas

    It writes inside the pack, not inside ComfyUI/output. The path is resolved relative to the repo root, so with a Manager install your log lands in ComfyUI/custom_nodes/from-3d-to-campaign/out/runs.jsonl. Backing up or clearing that file is on you; nothing rotates it, and it grows one line per stage per run forever.

    Don't call your gate stage qa_gate unless you mean it. The cost table deliberately skips rows with that stage name from its per-stage aggregation and prints the gate's pass/fail counts separately instead. Log the gate as qa_gate and you're opting out of the table - which is fine, as long as it's a choice.

    cache_hit is always written as false. For graph runs that's honest; it's the headless exporter and the CLI stages that set it true. If you want a real cache figure from the graph side, you already have it - CasaRender3D's info string tells you from cache or the render milliseconds, and that's the string worth putting in notes.

    The seconds field is easy to misuse. It's wall time, and for a sampler you'll be guessing unless you read it off the console. If precision matters to you more than convenience, log 0 and let the energy model in the cost table do the reasoning instead of pasting a made-up number into a field named seconds.

    Categoryfrom 3d to campaign

    Inputs (8)

    NameTypeDefaultDescription
    stageSTRINGgraph_render—
    itemSTRING—
    backendCOMBO3 options: local_comfyui, comfy_cloud, partner_api
    secondsFLOAT0.0—
    tokens_inINT0—
    tokens_outINT0—
    cost_usdFLOAT0.0000—
    notesSTRING—

    Outputs (1)

    NameTypeDescription
    lineSTRING—