DiffusionGemma Run Log Writer
Your DiffusionGemma run, as JSONL — the writer that owns its own file
- canvas_trace
- run_config
- canvas_state
- log_path
Every run of DGemmaSampler or DGemmaDenoise produces a pile of interesting data - the config, the per-step frames, the final canvas state. If you're using this pack properly, you're going to want some of those runs preserved as files, and that's the whole job of DGemmaRunLogWriter: it writes a schema'd JSONL run log to disk. One header record, one record per captured frame (with its decoded step text), one final record. You get a timestamped .jsonl file you can diff, grep, and feed back into analysis later.
This is plumbing, plain and simple - but it's plumbing that was built for a reason. The pack's own notes trace it to a real observed failure: route multiline text through a generic text-save node and you get the escaped-newline trap, where real newlines become literal \n on disk. This node owns its own file handle and writes bytes itself, one json.dumps + newline per record, so that failure mode is structurally impossible. The log you get is actually the log you meant to save.
Wiring it up
Four inputs must come from the same sampler-class node - don't mix a trace from one run with a config from another:
run_config- the header bundle (seed, knobs, model identity).canvas_trace- the per-step trace.frames- the decoded per-step strings from the same node'sframesoutput.canvas_state- the final save-state.filename_prefix(defaultdgemma_run_log) - the file name stem.debug_log_path- optional, a directory (more below).
Output: log_path - the STRING path of the file it just wrote. Handy for wiring into a text display or a webhook.
The directory-vs-file trap
This is the one that'll bite you. debug_log_path is always a directory, and filename_prefix is always the file name. There is no code path where debug_log_path is treated as a file - even if your value ends in .jsonl, it's still a directory by contract. The writer creates the directory if it's missing and writes {filename_prefix}_{timestamp}.jsonl inside it. Leave debug_log_path empty (the default) and it falls back to ComfyUI's standard output directory, using the same SaveImage conventions.
So if you want a file at /data/logs/my_run.jsonl, you set debug_log_path to /data/logs and filename_prefix to my_run - and get /data/logs/my_run_20260827T101530.jsonl. The timestamp is why repeated runs never collide.
Install
It ships in ComfyUI-DiffusionGemma, so the install is the pack install: Manager search "ComfyUI-DiffusionGemma" or git clone into custom_nodes, restart, and confirm transformers==5.13.0 + diffusers>=0.39.0 installed into ComfyUI's own Python. The node itself is cheap - it only runs after a sampler has done the expensive work. If you're running many samples for a study, point this at a real directory early; the JSONL it writes is the kind of artifact you'll be glad you kept when you're reconstructing what happened three weeks later.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| canvas_trace | DGEMMA_CANVAS_TRACE | Per-step trace from the sampler-class node that produced this run. | |
| run_config | DGEMMA_RUN_CONFIG | Run header bundle from the SAME sampler-class node (seed, knobs, model identity). | |
| frames | STRING | The decoded per-step strings from the same node's frames output. | |
| canvas_state | DGEMMA_CANVAS_STATE | The final save-state from the same node's canvas_state output. | |
| filename_prefix | STRING | dgemma_run_log | The FILE name stem. The log is written as {filename_prefix}_{timestamp}.jsonl. |
| debug_log_pathopt | STRING | A DIRECTORY to write into (created if missing) — NOT a file path. The file name comes from filename_prefix. Leave empty to use ComfyUI's output directory. A trailing slash or a .jsonl-looking value is still treated as a directory. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| log_path | STRING | — |