<!-- Generated from https://trafficparrot.com/documentation/5.65.x/logging.html by scripts/generate-md-mirrors.sh. Do not edit: edit the .html and regenerate. -->

# How to control logging and debug verbosity in Traffic Parrot

<a id="overview"></a>
## Logging and debug verbosity overview

Traffic Parrot is a standalone mock and service virtualization server that is [compatible with WireMock](https://trafficparrot.com/features.html) stub mappings. If you are coming from WireMock and searching for how to **enable verbose logging**, **change the log level**, **turn off debug output**, or simply find **where the logs are**, this page is the Traffic Parrot answer.

The key difference to keep in mind: in Traffic Parrot you control logging by editing a **logging configuration file** in the install directory and then restarting the server. There is **no `--verbose` command-line flag**; unlike WireMock standalone, Traffic Parrot does not take a verbosity switch on the launch command. The log level lives in the configuration file.

It also helps to know that Traffic Parrot has two distinct places where it records what happened to a request:

- The **log files on disk** (and console output): controlled by the logging configuration file described on this page. This is where startup, errors, and per-request entries are written.
- The **in-memory Request Log** in the web UI: a live journal of every request with full headers, bodies, timing, and a field-by-field [near-miss comparison](#why-no-match) for unmatched requests. This is the best place to answer "why didn't my request match?".

The sections below cover both, starting with the files on disk.

<a id="where-are-the-logs"></a>
## Where are the logs?

Traffic Parrot writes its log files to a `logs` folder inside the install directory (the folder you unzipped, the same place that contains `start.sh` and the configuration files). The default destinations are:

| Location | What it contains |
| --- | --- |
| `logs/trafficparrot.log` | The main application log: startup, configuration, errors, and one entry per request received by the virtual service. This is a rolling file (1 MB per file, up to 100 backups), so older entries roll into `trafficparrot.log.1`, `trafficparrot.log.2`, and so on. |
| `tp.out` | Console / boot output captured at the install root when you start Traffic Parrot. Useful for diagnosing problems that occur before logging is fully initialised. |
| `logs/http-ui-access/`<br>`logs/http-vs-access/` | Jetty HTTP access logs (one request per line) for the management UI port and the virtual service port respectively. See [turning logging down](#turning-down) to disable these. |

When you start Traffic Parrot in the foreground with `start-foreground.sh`, the application log is also surfaced on the console so you can watch it live. When you start it in the background with `start.sh`, the application log stream is not duplicated to the background process's standard output; read `logs/trafficparrot.log` directly in that case.

<a id="change-log-level"></a>
## Enabling verbose logging and changing the log level

The log level for the files and console is controlled by a single configuration file that ships in the install directory:

```
trafficparrotserver.log4j.properties
```

This file sits at the **install root** (the folder you unzipped); there is no `bin` subdirectory. It is a standard log4j 1.x properties file. The shipped default looks like this:

```properties
log4j.rootLogger=INFO,file,stdout

log4j.appender.file=org.apache.log4j.RollingFileAppender
log4j.appender.file.File=logs/trafficparrot.log
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=100
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %t %m%n----------------------------------------------------------------------%n
log4j.appender.file.encoding=UTF8

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-5p %t %m%n----------------------------------------------------------------------%n
log4j.appender.stdout.encoding=UTF8

log4j.logger.WireMock=INFO
log4j.logger.dorkbox.util.jna=ERROR
log4j.logger.dorkbox.systemTray=ERROR
log4j.logger.org.eclipse.jetty.util.ssl.SslContextFactory=WARN
log4j.logger.org.glassfish.jersey.internal.inject.Providers=ERROR
log4j.logger.io.swagger.v3.parser.OpenAPIV3Parser=ERROR

log4j.category.com.trafficparrot.messaging.ibmmq.connection.monitor.ReportingIbmMqPerformanceMonitor=INFO
```

The first line is the one you change to raise or lower verbosity. The value before the comma is the level (`TRACE`, `DEBUG`, `INFO`, `WARN`, `ERROR`); the names after it are the appenders (here `file` and `stdout`) that the level applies to.

##### To turn on full verbose / debug logging

Change the root logger from `INFO` to `DEBUG`:

```properties
log4j.rootLogger=DEBUG,file,stdout
```

Then **restart Traffic Parrot**.

> **A restart is required.** The logging configuration file is read once, at startup. Editing it while Traffic Parrot is running has no effect; there is no hot-reload. Stop and start the server for your change to take effect.

> **Debug is very noisy.** Setting the root logger to `DEBUG` turns on a flood of internal Jetty and HTTP-parser messages: over two thousand lines are written during startup alone, and because the file rolls at 1 MB it cycles quickly. Use `DEBUG` when you are actively diagnosing a problem, then set it back to `INFO` for normal running.

##### Raising the level for one category only

Rather than turning everything up, you can keep the root logger at `INFO` and raise the level of a single category. For example, lines such as the third-party suppressors above raise (quieten) specific packages to `WARN` or `ERROR`.

> **Note about the per-request HTTP log line.** Traffic Parrot writes one `Request received:` entry per HTTP request at `INFO` unconditionally. Setting `log4j.logger.WireMock=DEBUG` on its own does *not* add extra HTTP request-matching detail to `trafficparrot.log`. To see the full picture of why a request matched or did not match a stub, use the [GUI Request Log near-miss view](#why-no-match) described below.

<a id="why-no-match"></a>
## Seeing why an HTTP request didn't match

This is the most common reason WireMock users go looking for verbose logging: a request returned a `404` / "not matched" response and they want to know which part of the stub didn't line up. In Traffic Parrot the answer is **not** in the log file; it is in the GUI Request Log.

##### What the log file shows

For an unmatched HTTP request, `logs/trafficparrot.log` records that a request arrived and that no stub was configured for it, but it does **not** contain a field-by-field comparison. A real entry looks like this:

```
2026-05-31 03:43:00,438 INFO  http-vs-Default-136 Request received:
[0:0:0:0:0:0:0:1] - GET /api/users

Host: [localhost:18281]
Accept: [text/plain]


Matched response definition:
(no response definition configured)

Response:
HTTP/1.1 404
(no headers)
----------------------------------------------------------------------
```

That tells you the request reached Traffic Parrot and no mapping matched it, but not *why*. For the "why", use the Request Log.

##### The GUI Request Log near-miss view

Open the HTTP **Request Log** from the HTTP dropdown in the top navigation bar (the [Requests](https://trafficparrot.com/documentation/5.65.x/http.html#request-log) page). Every request the virtual service has received is listed, with a green **Yes** badge for matched requests and a red **No** badge for unmatched ones.

![Traffic Parrot HTTP Request Log listing a matched GET request with a green Yes badge and an unmatched GET request with a red No badge](https://trafficparrot.com/documentation/5.65.x/img/http/logging-request-log-overview.png)

Expand the unmatched (red **No**) row to reveal the request headers, the response status, and a **Near Misses** section. Each near miss is a stub that came close to matching, shown as a comparison table with an *Expected (stub)* column, an *Actual (request)* column, a match-percentage badge (for example **96% match**), and a **View Stub** link to jump straight to editing that stub. A green tick marks each field that matched; a red cross (and a highlighted row) marks each field that did not.

![Expanded unmatched request in the Traffic Parrot Request Log showing a Near Misses comparison table where Method and URL path match but the Accept header expected application/json while the request sent text/plain, with a 96% match badge and a View Stub link](https://trafficparrot.com/documentation/5.65.x/img/http/logging-request-log-near-miss.png)

In the example above the stub expects `GET /api/users` with `Accept: application/json`, but the request sent `Accept: text/plain`. The method and URL path rows match (green ticks); the **Header: Accept** row is highlighted with a red cross, making it immediately clear why the request was not matched. See the HTTP page for the full reference on [near misses for unmatched requests](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-near-misses).

##### The same information programmatically

If you prefer to read the journal from a script, request the recorded requests through the management API. Each entry includes a `"wasMatched": false` flag for unmatched requests and a `subEvents` entry of type `REQUEST_NOT_MATCHED`:

```bash
curl http://localhost:8080/__admin/requests
```

Replace `8080` with your `trafficparrot.gui.http.port` if you changed it. See the [programmatic setup tutorial](https://trafficparrot.com/tutorials/traffic-parrot-programmatic-setup-using-apis.html) for more management-API examples.

<a id="left-out-at-start"></a>
## Traffic Parrot started but one of my mocks or extensions is missing

One item that cannot be loaded does not stop Traffic Parrot from starting, and does not make every request fail. The item is left out, logged and shown, and everything else is served:

- An HTTP or gRPC **mapping file** that is not valid JSON, is not a mapping, is empty, or names a request body file under `__files` that is missing. The other mappings, in that file's directory and elsewhere, are served. A `trafficparrot.sh validate` run still fails on such a file.
- A class named in [`trafficparrot.http.responsetransformers`](https://trafficparrot.com/documentation/5.65.x/properties.html#extension-system-properties) that cannot be loaded or created: it is not on the classpath, it has neither a public no-argument constructor nor a public constructor taking a `TrafficParrotServices`, or its constructor throws (a jar that carries its own copy of the SDK, or one built for a newer Java, fails this way). The other extensions and every mapping are served. The main HTTP port and each scenario served on its own port load the extensions separately, so a class can be left out on one of them and not another.

##### What the log file shows

Each item is an `ERROR` in `logs/trafficparrot.log` naming it and the reason. A mapping file's is written when it is left out and again only if the reason changes. An extension's is written each time a server starts without it: once for the main port and once per scenario served on its own port at start, and again when recording or proxying stops, which restarts the server. The samples below are trimmed: the shipped pattern adds the timestamp before `ERROR` and the thread name after it, and an extension left out with a cause is followed by its stack trace:

```
ERROR Skipping mapping file /opt/trafficparrot/mappings/broken.json, the other mappings are still served: Unrecognized token 'not': was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')
ERROR Skipping HTTP extension com.example.NotOnTheClasspath, the other extensions and the mappings are still served: it was not found on the classpath
```

##### What the mappings list shows

The [HTTP](https://trafficparrot.com/documentation/5.65.x/http.html#add-edit-http-mappings) and [gRPC](https://trafficparrot.com/documentation/5.65.x/grpc.html#edit-grpc) mappings lists show a notice above the table with one line per item. A left-out mapping file is listed as `mapping file <path>: <reason>` under the heading *Left out because they could not be loaded; every other mapping is served*, naming the file exactly as the log does so the line can be searched for there; on the HTTP list a left-out extension follows as `HTTP extension <class> was left out: <reason>`, and when only extensions are left out the notice is those lines alone, without the heading. The notice is refreshed with the list's automatic reload and goes once the item loads.

##### The same information programmatically

Three management endpoints answer the same lists as JSON, an array of `{"skipped": "...", "reason": "..."}` that is empty when nothing is left out:

```bash
curl http://localhost:8080/http/management/skippedMappingFiles
curl http://localhost:8080/grpc/management/skippedMappingFiles
curl http://localhost:8080/http/management/skippedExtensions
```

The file lists are current: a fixed file drops off on the next load and a newly broken one joins. The extension list is current as of each WireMock server's last start, one entry per class and reason in the property's order, and a class left out on only some servers has its reason end with them, for example `; on the main port (8081)` or `; on scenario orders (port 8091)`. Replace `8080` with your `trafficparrot.gui.http.port` if you changed it. The three are in the [OpenAPI reference](https://trafficparrot.com/documentation/5.65.x/openapi/index.html).

<a id="turning-down"></a>
## Turning logging down or off

To make Traffic Parrot quieter, do the reverse of enabling verbose logging: raise the level so fewer messages are written. In `trafficparrotserver.log4j.properties`, set the root logger (or specific categories) to `WARN` or `ERROR`, then restart:

```properties
# Only warnings and errors in the log file
log4j.rootLogger=WARN,file,stdout
# The WireMock category writes the per-request entries and is set to INFO in the shipped file
log4j.logger.WireMock=WARN
```

Two related settings live in [`trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/properties.html) (also at the install root) rather than in the logging file:

| Property | Default | Effect |
| --- | --- | --- |
| `trafficparrot.virtualservice.accessLogsEnabled` | `true` | Set to `false` to stop writing the Jetty access logs under `logs/http-ui-access/` and `logs/http-vs-access/`. |
| `trafficparrot.virtualservice.httpRequestLoggingDisabled` | `false` | Set to `true` to stop writing the `Request received:` entry that `logs/trafficparrot.log` gets for each request to the HTTP virtual service (useful for maximum throughput in performance tests). The in-memory request journal that powers the [Request Log](#why-no-match) is separate: [`trafficparrot.virtualservice.maxRequestJournalEntries`](https://trafficparrot.com/documentation/5.65.x/properties.html#virtualservice-properties) sizes it, and `0` switches it off. |

Both of these are standard Traffic Parrot properties; see the [Configuration Reference](https://trafficparrot.com/documentation/5.65.x/properties.html) for the full list and [how to edit `trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/user_guide.html#properties).

<a id="alternatives"></a>
## Using Logback or Log4j2 instead

Traffic Parrot uses the log4j 1.x properties file by default, but it also ships two alternative configuration files at the install root for teams that prefer a different logging framework:

- `trafficparrotserver.logback.xml`: Logback configuration
- `trafficparrotserver.log4j2.xml`: Log4j2 configuration

To switch, edit the `jvm.args` file (also at the install root) and point the `-Dtrafficparrotserver.logging.properties.filename=` argument at the file you want, then restart. For example:

```
-Dtrafficparrotserver.logging.properties.filename=trafficparrotserver.logback.xml
```

Most users do not need to do this; editing the default `trafficparrotserver.log4j.properties` as shown above is sufficient. See [JVM arguments](https://trafficparrot.com/documentation/5.65.x/user_guide.html#jvm-arguments) for more about the `jvm.args` file.

<a id="next-steps"></a>
## Next steps

- [HTTP Request Log](https://trafficparrot.com/documentation/5.65.x/http.html#request-log): full reference for the in-GUI request journal and [near-miss comparison](https://trafficparrot.com/documentation/5.65.x/http.html#request-log-near-misses).
- [Request matching](https://trafficparrot.com/documentation/5.65.x/request_matching.html): how Traffic Parrot decides which stub responds, and the matchers available for each field.
- [Configuration Reference](https://trafficparrot.com/documentation/5.65.x/properties.html) and [editing `trafficparrot.properties`](https://trafficparrot.com/documentation/5.65.x/user_guide.html#properties): every configurable property, including the logging-related ones above.
- [Traffic Parrot for WireMock users](https://trafficparrot.com/features.html): how Traffic Parrot relates to WireMock, including stub compatibility.
