Two log streams per run, a color-coded console mirror, automatic numbered backups, and engine-notice routing that differs by platform. Everything a CI pipeline needs from a deploy tool.
By the SchemaSmith Team · Last reviewed
Good logs are the difference between a quick diagnosis and a long night.
All CLI tools use Apache Log4Net. Each tool ships with an embedded Log4Net configuration that is loaded automatically at startup — there's nothing to configure.
Each tool writes two log files per run:
| Tool | Progress log | Error log |
|---|---|---|
| SchemaQuench | SchemaQuench - Progress.log |
SchemaQuench - Errors.log |
| SchemaTongs | SchemaTongs - Progress.log |
SchemaTongs - Errors.log |
| DataTongs | DataTongs - Progress.log |
DataTongs - Errors.log |
The progress log receives all informational output: the startup banner, active configuration, per-object progress, and completion status. Everything written to the progress log also appears on the console in real time.
The error log receives only error-level entries (such as SQL execution errors) and does not echo to the console.
Both log files are overwritten at the start of each run. Previous runs are preserved through the backup rotation described below.
The console is a live mirror of the progress log, not a separate channel. Watching the console while a quench runs lets you follow startup, per-object progress, and completion in real time without tailing a file. Log4Net colorizes the console stream by level so trouble catches your eye the moment it appears:
| Level | Console color |
|---|---|
| Informational | Green |
| Warning | Yellow |
| Error | Red |
When a script fails, you see a short error summary on the console and in the progress
log (red, so it's hard to miss): the failing script path and the engine's error
message, along with a Debug Script: pointer when a generated procedure
is the source. That's enough to know what failed and where to look.
The full token-expanded SQL the server rejected is written to a
separate, re-runnable .sql artifact file rather than dumped into the log
stream; the log points you to it with a Resolved SQL written to: or
Debug Script: line. That keeps the progress and error logs safe to ship
— no expanded secrets, no multi-KB batch dumps — while the artifact stays on
the deploy host as your local reproduction tool. See
Working a failed deployment to trace one end to end.
On multi-target runs the log stays greppable: every schema-template iteration prefixes
its lines with [Schema: <name>], and a many-database fan-out uses
[server].[database]. Filter the progress log to one prefix to isolate a
single tenant's sequence end to end.
CI agents that capture stdout get the progress stream for free. If your pipeline step only saves stdout, you still have a readable transcript of successes and error summaries; archive the error log separately to keep the failed-batch detail.
By default, logs are written to the tool's executable directory. Override this with
--LogPath:
SchemaQuench --LogPath:C:\Logs
SchemaTongs --LogPath:C:\Logs\schemasmith
DataTongs --LogPath:D:\BuildLogs
SchemaQuench --LogPath:/var/log/schemasmith
SchemaTongs --LogPath:/var/log/schemasmith
DataTongs --LogPath:/var/log/buildlogs
Immediately after loading configuration, every tool logs its complete active configuration to the progress log. This includes the tool name and version number, followed by every configuration key and its value (with passwords masked). This makes it straightforward to verify what settings were in effect for any given run.
Any value whose name matches the built-in sensitive-name set — Password,
Pwd, Secret, ApiKey, Token,
ConnectionString, Credential (case-insensitive, substring match)
— is replaced with *** while its name still prints, so you can confirm
the setting exists without exposing it. An embedded Password= /
Pwd= inside a connection-string value is stripped even when the surrounding
name isn't sensitive. All other values are logged as-is.
You can tune what gets scrubbed — add exact names or patterns, or opt a false
positive back out — and suppress token logging entirely via the LogHygiene
settings block. See
Sensitive value masking
in the configuration reference.
2026-03-06 09:14:01,234 - SchemaQuench
2026-03-06 09:14:01,235 - Version: 5.2.1.0
2026-03-06 09:14:01,236 - Configuration:
2026-03-06 09:14:01,237 - Server: sql-prod-01
2026-03-06 09:14:01,238 - User: schemasmith
2026-03-06 09:14:01,239 - Password: ***
2026-03-06 09:14:01,240 - VerboseLogging: false
When a tool finishes (whether successfully or after an error), it backs up its log files before the process exits:
--LogPath value, or the executable directory if not specified).<ToolName>.0001. If that directory already exists, it increments: .0002, .0003, and so on.<ToolName> - *.log into the new subdirectory.The base log files in the log directory are not deleted after backup. Each run overwrites the base files and writes a copy into a new numbered subdirectory. This preserves the history of every run while keeping the base files current with the latest.
Example after three SchemaQuench runs:
C:\Tools\
SchemaQuench - Progress.log (latest run)
SchemaQuench - Errors.log (latest run)
SchemaQuench.0001\ (first run backup)
SchemaQuench.0002\ (second run backup)
SchemaQuench.0003\ (third run backup)
A failed quench leaves two things for you: a log entry telling you what broke, and a .sql artifact file holding the exact SQL that the server rejected. Here's how to move from "deployment failed" to "I know what's wrong and I can fix it."
SchemaQuench - Progress.log) and search for Resolved SQL written to: (user scripts and data-delivery merges) or Debug Script: (generated quench SQL). Either line gives you the full path to the artifact file.
Unable to quench 'Before/01-seed-config.sql': Invalid column name 'Region'.
Resolved SQL written to: C:\deploy\SchemaQuench - Failed 01-seed-config prod-db.TargetDB.sql
Artifacts land in the ArtifactPath directory (default: the working directory you ran SchemaQuench from), not the log directory — deliberately, so zipping your logs for a support ticket doesn't sweep up raw SQL that may contain expanded sensitive values..sql file: a comment header identifying the server, database, schema, and which script failed, followed by every batch the engine sent, separated by GO. The batch SchemaQuench attempted last is marked:
-- >>> FAILING BATCH (#2) >>>
ALTER TABLE [dbo].[Orders] ADD [Region] NVARCHAR(50) NOT NULL ...
GO
The marker is a best-effort hint — the engine marks the last batch it attempted, usually (but not always) the one that caused the error. The values are real and fully expanded (tokens resolved, connection-string parameters substituted), which is exactly what you need to reproduce the failure.{{Token}} instead of the expanded value — a misspelled token, a token out of scope for this script's slot (a {{SchemaName}} token in a product-level script, say), or a token that was never defined.ScrubArtifacts: true before re-running: the artifact then redacts sensitive token values and inline connection-string passwords into a shareable variant. See Failure artifacts in the configuration reference.When SchemaQuench runs one of its generated procedures against your target database, it dumps the exact SQL it sent to a companion .sql file — the same artifact the Debug Script: line points at. Generated procedures cover missing tables and columns, modified tables, indexes, foreign keys, materialized views, indexed views, and the table-JSON parse step. Debug files follow the pattern SchemaQuench - <operation> <server>.<database>.sql:
SchemaQuench - Quench Missing Tables And Columns prod.NW.sql
SchemaQuench - Quench Modified Tables prod.NW.sql
SchemaQuench - Quench Indexes prod.NW.sql
SchemaQuench - Quench Foreign Keys prod.NW.sql
SchemaQuench - Quench Materialized Views prod.NW.sql
SchemaQuench - Quench Indexed Views prod.NW.sql
SchemaQuench - Parse Table Json prod.NW.sql
Each run overwrites the debug files for the operations it actually performed. Operations that don't apply to your platform (indexed views on PostgreSQL, materialized views on MySQL) produce no file. Debug files land in the ArtifactPath directory (default: current working directory) — --LogPath controls the progress and error logs, not artifact or debug SQL.
SchemaSmith surfaces the database engine's informational output — notices, prints, and server-side status messages — into the progress log so you can see what the engine is telling you. The wiring differs per platform because each driver exposes that stream differently.
PRINT output and severity-10-or-lower errors arrive through the
InfoMessage event. By default SchemaSmith promotes only
severity-above-10 errors and RAISERROR ... WITH STATE 100
notifications to the progress log; set VerboseLogging: true to
include every PRINT and informational message.
RAISE NOTICE and RAISE WARNING output arrives
through the Npgsql Notice event and lands in the progress log.
SchemaSmith filters out the "... does not exist, skipping" and
"... already exists, skipping" notices that
DROP ... IF EXISTS and CREATE ... IF NOT EXISTS
produce during normal runs, so your log stays readable.
The MySQL connector doesn't fire info-message events for long-running stored
procedures, so SchemaSmith uses a table-based status channel. A
SchemaSmith_StatusMessages table in the target database (created
automatically during kindling) holds per-session progress rows; the generated
quench procedures INSERT into it as they work, and a background
poller on a separate connection reads the new rows every 200ms and writes them
to the progress log. SessionId is scoped to
CONNECTION_ID() so concurrent runs don't cross-talk, and the
monitor deletes its rows on shutdown. There's no VerboseLogging
dial on MySQL — what you see is whatever the procedures chose to publish.
VerboseLogging is a SchemaQuench setting and applies only to SQL Server's
InfoMessage stream. The PostgreSQL and MySQL paths already behave the way
VerboseLogging: true behaves on SQL Server — SchemaSmith surfaces
every engine-side notice (PostgreSQL) or procedure-emitted status message (MySQL) by default.
| Code | Condition | Recommended action |
|---|---|---|
0 |
Normal completion | None — the operation succeeded. |
2 |
One or more database quenches failed (SchemaQuench only) | Check the progress and error logs for details on which databases failed and why. Fix the failing scripts and re-run. |
3 |
Unhandled exception | An unexpected error occurred. The exception is logged to both the progress and error logs before exit. Report the error with the log contents if the cause isn't obvious. |
4 |
Log backup failure | The tool completed its main work but couldn't back up the log files. Check directory permissions and disk space in the log directory. The base log files may still be readable even though the backup failed. |
Pre-flight checks that fail before any deployment — a --TestConnection
failure, a server below the product's MinimumVersion floor, or a
--PreviewTargets run that finds a required template with zero targets
— also exit 2, so a readiness gate in CI can treat any non-zero exit
the same way.