# Logging and diagnostics

QV2QS writes structured diagnostic logs during every run. The logging system has two tiers: a persistent system log that survives across runs, and a per-run structured log that ships with the conversion output.

## System log

QV2QS maintains a rolling log file at a fixed location on disk. The system log starts when the executable launches and records application-level events independent of any project or batch.

Location: `%LOCALAPPDATA%\QV2QS\qv2qs.log`

The system log uses a rotating file handler with the following settings.

| Setting | Value |
| --- | --- |
| Maximum file size | 25 MB |
| Backup files kept | 3 |
| File pattern | `qv2qs.log`, `qv2qs.log.1`, `qv2qs.log.2`, `qv2qs.log.3` |

When the active log file reaches 25 MB, QV2QS rotates the file and creates a new log file. The three most recent backups are retained. Older backups are deleted automatically.

## Per-run structured log

Each conversion run produces a separate log file containing detailed events for that run. The file is named `qv2qs_run_<version>_<timestamp>.log` and is written in tab-separated values (TSV) format with a JSON data column.

Default location: `%LOCALAPPDATA%\QV2QS\logs\`

In single-project mode, QV2QS promotes the log file into the `logs/` subfolder of the project output folder (for example, `<outputDir>/Sales/logs/`) after the output folder is initialized. The log file is included in the conversion output.

In batch mode, per-project logs are written to the `logs/` subfolder within each project output folder.

### Log file format

Each log file begins with a TSV header row:

```
ts_utc	level	version	run_id	logger	event	message	data
```

| Column | Description |
| --- | --- |
| `ts_utc` | ISO 8601 timestamp in UTC with millisecond precision |
| `level` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR`, or `CRITICAL` |
| `version` | QV2QS version |
| `run_id` | Unique run identifier in the format `YYYYMMDD-HHMMSS-<hex>` |
| `logger` | Logger name (typically `qv2qs`) |
| `event` | Event type string (for example, `startup`, `conversion_complete`, `batch_local_complete`) |
| `message` | Human-readable description |
| `data` | JSON object with contextual key-value pairs |

### Timestamp collisions

If two runs start within the same second and produce the same timestamp, QV2QS appends `_2`, `_3`, or subsequent numbers to the filename to avoid overwriting.

## Which log to check

QV2QS writes to two separate logs at different stages of a run. The system log is always available. The per-run log is only created after startup initialization completes.

| Scenario | Log to check first | Why |
| --- | --- | --- |
| The process crashes or exits immediately | System log | The per-run log has not been created yet |
| PRJ generation fails before conversion starts | System log | PRJ events are logged before the output directory is initialized |
| A batch run shows failed files with no details | System log | Batch-level errors (missing QlikView Desktop, prerequisite failures) are recorded in the system log |
| Conversion produces unexpected output | Per-run log in the output directory | Object-level conversion decisions and warnings are recorded in the per-run log |
| Cloud deployment fails | Per-run log in the output directory | API calls, authentication errors, and upload progress are recorded in the per-run log |

Information note

The system log and the per-run log record the same events during the overlap period when both are active. The system log begins at process launch. The per-run log begins after command-line arguments are parsed and the output directory is created. If a failure occurs before the per-run log is created, only the system log contains diagnostic information.

## Log levels

Five log levels are available, listed from most to least verbose.

| Level | Description |
| --- | --- |
| `DEBUG` | Detailed diagnostic information for troubleshooting |
| `INFO` | General operational messages (default) |
| `WARNING` | Unexpected conditions that do not prevent conversion |
| `ERROR` | Failures that affect individual objects or operations |
| `CRITICAL` | Severe failures that halt execution |

Set the log level with `--logLevel` or the `QV2QS_LOG_LEVEL` environment variable. The CLI flag takes precedence when both are set.

Set `--logLevel DEBUG` to capture the most detailed output. Debug-level entries include conversion decisions, cloud API calls, script modifications, and object processing details.

To enable debug logging without modifying the command line, set the environment variable before running QV2QS:

```
set QV2QS_LOG_LEVEL=DEBUG
QV2QS.exe --prjPath ./MyApp-prj --outputDir ./output --qvw MyApp.qvw --unbuildOnly
```

## Log cleanup

Log files accumulate across runs in the persistent log directory. Use `--cleanLogs` to delete log files older than 30 days at the start of a run. The cleanup applies to the persistent log directory only; per-project logs in output directories are not affected.

## Secret masking

Log entries automatically mask sensitive values. API keys, tokens, passwords, and client secrets are redacted to show only the last four characters. Command-line arguments containing secrets are also masked when logged.

## QlikView Desktop engine logging

When PRJ generation is enabled, QV2QS logs which QlikView Desktop engine is used for each file. The log event `prj_generate_start` records whether the bundled portable engine or a system-installed version is active and includes the bundled executable's file version when available.

After the connection to QlikView Desktop is established, the `prj_qv_ready` event records the QlikView version reported by the running engine (for example, `12.100.20100.0`). When the bundled engine is used, the `exe_file_version` field records the file version read from the executable.

In batch mode, the log event `prj_batch_prereq` records the engine selection and bundled version for the entire batch before any files are processed. If neither a bundled engine nor a system installation is available, the error is logged as `prj_batch_no_qv` in the system log.

Set `--logLevel DEBUG` to capture detailed engine resolution steps, including the file paths checked during engine discovery.

## Console output vs. file logging

Console output and file logging are independent systems.

| Aspect | Console | File log |
| --- | --- | --- |
| Format | Formatted text with optional colors and spinners | Structured TSV with JSON data |
| Controlled by | `--console pretty\\|plain\\|silent\\|ui` | `--logLevel`, `--logDir` |
| Content | User-facing progress and results | Complete diagnostic events |
| Secret masking | Not applicable | Applied automatically |

Console output does not appear in the log files. The `--console silent` flag suppresses console output without affecting file logging.

## CLI arguments

| Argument | Description | Default |
| --- | --- | --- |
| `--logLevel LEVEL` | Log verbosity: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` | `INFO` |
| `--logDir FOLDER` | Override the per-run log output folder. Relative paths resolve from the current working directory, not from the output directory. Does not affect the persistent system log at `%LOCALAPPDATA%`. | `%LOCALAPPDATA%\QV2QS\logs\` (single-project) or `<outputDir>/logs/` (batch) |
| `--cleanLogs` | Delete log files older than 30 days before the run | Off |

## Learn more

* [Argument reference](https://help.qlik.com/en-US/migration/Content/Qv2qsMigration/command-line-interface/argument-reference.htm)
* [Troubleshooting](https://help.qlik.com/en-US/migration/Content/Qv2qsMigration/troubleshooting/index.htm)