mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.57k stars 1.07k forks source link

Can not find the mockserver_request.log #309

Closed VitalyKheifets closed 7 years ago

VitalyKheifets commented 7 years ago

When i start ClientAndProxy from eclipse like this:

ClientAndProxy proxy = startClientAndProxy(1090);
new ProxyClient("localhost", 1090)
        .dumpToLogAsJSON(
                request()
                        .withMethod("POST")
                        .withPath("/login")
        );

I can not find the mockserver_request.log

masooh commented 7 years ago

See my answer from issue #254.

VitalyKheifets commented 7 years ago

I tryed the logback.xml above, but it is not working for me..

When i use the following logback.xml https://github.com/jamesdbloom/mockserver/blob/master/mockserver-examples/src/main/resources/logback.xml

<configuration debug="false">
    <!-- To completely disable all logging completely -Droot.logLevel=OFF -Dmockserver.logLevel=OFF -->

    <!-- application log -->
    <appender name="FILE" class="org.mockserver.logging.DelayedFileCreationRollingFileAppender">
        <file>${log.dir:-./}mockserver.log</file>
        <encoder>
            <pattern>%date %level [%thread] %logger{35} [%file:%line] %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir:-./}mockserver.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>1</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- make application log asynchronous -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="FILE" />
    </appender>

    <!-- application console log (for errors and warnings) -->
    <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.err</target>
        <encoder>
            <pattern>%date %level %logger{20} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
    </appender>

    <!-- make console log (for errors and warnings) asynchronous -->
    <appender name="ASYNC_STDERR" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="STDERR" />
    </appender>

    <!-- application console log -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <pattern>%date %level %logger{20} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <expression>level &gt;= INFO &amp;&amp; level &lt; WARN</expression>
            </evaluator>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>NEUTRAL</OnMatch>
        </filter>
    </appender>

    <!-- make console log asynchronous -->
    <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="STDOUT" />
    </appender>

    <!-- request log configuration -->
    <appender name="REQUEST_LOG" class="org.mockserver.logging.DelayedFileCreationRollingFileAppender">
        <file>${log.dir:-./}mockserver_request.log</file>

        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir:-./}mockserver_request.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
    </appender>

    <logger name="REQUEST" level="INFO" additivity="false">
        <appender-ref ref="REQUEST_LOG"/>
    </logger>

    <logger name="org.mockserver" level="${mockserver.logLevel:-WARN}"/>
    <logger name="org.mockserver.proxy" level="${mockserver.logLevel:-INFO}"/>
    <logger name="org.mockserver.mockserver" level="${mockserver.logLevel:-INFO}"/>

    <root level="${root.logLevel:-WARN}">
        <appender-ref ref="ASYNC_FILE"/>
        <appender-ref ref="ASYNC_STDERR"/>
        <appender-ref ref="ASYNC_STDOUT"/>
    </root>
</configuration>

I can not see the mockserver_request.log (only the mockserver.log)

I played with the logback.xml file and when i use the following:

<configuration debug="false">
    <!-- request log configuration -->
    <appender name="REQUEST_LOG"
        class="org.mockserver.logging.DelayedFileCreationRollingFileAppender">
        <file>${log.dir:-./}mockserver_request.log</file>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir:-./}mockserver_request.%d{yyyy-MM-dd}.%i.log
            </fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy
                class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
    </appender>

    <logger name="REQUEST" level="INFO" additivity="false">
        <appender-ref ref="REQUEST_LOG" />
    </logger>

    <root level="${root.logLevel:-INFO}">
        <appender-ref ref="REQUEST_LOG" />
    </root>
</configuration>

I get something like that in my mockserver_request.log

MockServer started on port: 1080
creating expectation:

    {
      "httpRequest" : {
        "method" : "POST",
        "path" : "/login"
      },
      "times" : {
        "remainingTimes" : 0,
        "unlimited" : true
      },
      "timeToLive" : {
        "unlimited" : true
      },
      "httpResponse" : {
        "statusCode" : 200,
        "headers" : [ {
          "name" : "Content-Type",
          "values" : [ "application/json; charset=utf-8" ]
        }, {
          "name" : "Cache-Control",
          "values" : [ "public, max-age=86400" ]
        } ],
        "body" : "{ message: 'incorrect username and password combination' }"
      }
    }

MockServer proxy started on port: 1090 connected to remote server: localhost:1080
request:

    {
      "method" : "POST",
      "path" : "/login",
      "headers" : [ {
        "name" : "User-Agent",
        "values" : [ "Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.6.0_45)" ]
      }, {
        "name" : "Host",
        "values" : [ "localhost:1080" ]
      }, {
        "name" : "Accept-Encoding",
        "values" : [ "gzip,deflate" ]
      }, {
        "name" : "Content-Length",
        "values" : [ "0" ]
      }, {
        "name" : "Connection",
        "values" : [ "keep-alive" ]
      } ],
      "keepAlive" : true,
      "secure" : false
    }

 matched expectation:

    {
      "method" : "POST",
      "path" : "/login"
    }

returning response:

    {
      "statusCode" : 200,
      "headers" : [ {
        "name" : "Content-Type",
        "values" : [ "application/json; charset=utf-8" ]
      }, {
        "name" : "Cache-Control",
        "values" : [ "public, max-age=86400" ]
      } ],
      "body" : "{ message: 'incorrect username and password combination' }"
    }

 for request:

    {
      "method" : "POST",
      "path" : "/login",
      "headers" : [ {
        "name" : "User-Agent",
        "values" : [ "Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.6.0_45)" ]
      }, {
        "name" : "Host",
        "values" : [ "localhost:1080" ]
      }, {
        "name" : "Accept-Encoding",
        "values" : [ "gzip,deflate" ]
      }, {
        "name" : "Content-Length",
        "values" : [ "0" ]
      } ],
      "keepAlive" : true,
      "secure" : false
    }

returning response:

    {
      "statusCode" : 200,
      "headers" : [ {
        "name" : "Content-Length",
        "values" : [ "58" ]
      }, {
        "name" : "Connection",
        "values" : [ "keep-alive" ]
      }, {
        "name" : "Content-Type",
        "values" : [ "application/json; charset=utf-8" ]
      }, {
        "name" : "Cache-Control",
        "values" : [ "public, max-age=86400" ]
      } ],
      "body" : "{ message: 'incorrect username and password combination' }"
    }

 for request as json:

    {
      "method" : "POST",
      "path" : "/login",
      "headers" : [ {
        "name" : "Content-Length",
        "values" : [ "0" ]
      }, {
        "name" : "Host",
        "values" : [ "localhost:1090" ]
      }, {
        "name" : "User-Agent",
        "values" : [ "Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.6.0_45)" ]
      }, {
        "name" : "Accept-Encoding",
        "values" : [ "gzip,deflate" ]
      } ],
      "keepAlive" : true,
      "secure" : false
    }

 as curl:

    curl -v 'http://localhost:1090/login' -X POST -H 'Content-Length: 0' -H 'Host: localhost:1090' -H 'User-Agent: Apache-HttpClient/4.4.1 (Java 1.5 minimum; Java/1.6.0_45)' -H 'Accept-Encoding: gzip,deflate' --compress

In mock-server website i see an example of mockserver_request.log file of the following format: http://www.mock-server.com/proxy/record_and_replay.html

{
    "httpRequest": {
        "method": "POST",
        "path": "/login",
        "body": {
            "type": "STRING",
            "value": "{username: 'foo', password: 'bar'}",
        },
        "cookies": [
            {
                "name": "sid",
                "values": [ "05F1A3D2F2143C49727" ]
            }
        ],
        "headers": [
            {
                "name": "Accept-Language",
                "values": [ "en-US,en;q=0.8,fa;q=0.6" ]
            },
            {
                "name": "Cookie",
                "values": [ "sid=05F1A3D2F2143C49727" ]
            },
            {
                "name": "Host",
                "values": [ "localhost:2021" ]
            },
            {
                "name": "Content-Length",
                "values": [ "34" ]
            },
            {
                "name": "Accept-Encoding",
                "values": [ "gzip,deflate,sdch" ]
            },
            {
                "name": "User-Agent",
                "values": [ "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36" ]
            },
            {
                "name": "Accept",
                "values": [ "*/*" ]
            },
            {
                "name": "Content-Type",
                "values": [ "text/plain" ]
            }
        ]
    },
    "httpResponse": {
        "statusCode": 200,
        "body": "{ message: 'success' }",
        "headers": [
            {
                "name": "Content-Type",
                "values": [ "application/json; charset=utf-8" ]
            },
            {
                "name": "Cache-Control",
                "values": [ "no-cache, no-store" ]
            }
        ]
    },
    "times": {
        "remainingTimes": 1,
        "unlimited": false
    }
}

How can i get the same?

jamesdbloom commented 7 years ago

You need to make a call to the '/dumpToLog' endpoint as described in https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/10.8.

If your using the Java or JavaScript clients there is a method to trigger this.

The log file is only created once your so this as no log file is created until the first log entry is written.

jamesdbloom commented 7 years ago

The following example shows how to use this feature:

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.junit.Test;
import org.mockserver.integration.ClientAndProxy;
import org.mockserver.socket.KeyStoreFactory;

import java.io.IOException;
import java.net.URISyntaxException;

import static org.mockserver.integration.ClientAndProxy.startClientAndProxy;
import static org.mockserver.model.HttpRequest.request;

/**
 * @author jamesdbloom
 */
public class testDumpLog {

    @Test
    public void shouldDumpRequestsToLog() throws URISyntaxException, IOException {
        // start proxy
        System.setProperty("logback.configurationFile", "/Users/jamesbloom/git/mockserver/mockserver/mockserver-netty/src/main/resources/example_logback.xml");
        ClientAndProxy proxyClient = startClientAndProxy(1090);

        // create java client configured with proxy
        CloseableHttpClient httpClient = HttpClients
                .custom()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(KeyStoreFactory.keyStoreFactory().sslContext(), NoopHostnameVerifier.INSTANCE))
                .setRoutePlanner(new DefaultProxyRoutePlanner(
                        new HttpHost(
                                System.getProperty("http.proxyHost", "localhost"),
                                Integer.parseInt(System.getProperty("http.proxyPort", String.valueOf(1090)))
                        )
                )).build();

        // send request using java client
        HttpPost request = new HttpPost(
                new URIBuilder()
                        .setScheme("http")
                        .setHost("localhost")
                        .setPort(1080)
                        .setPath("/login")
                        .build()
        );
        request.setEntity(new StringEntity("an_example_body"));
        HttpResponse response = httpClient.execute(request);

        // print out response
        System.out.println("response = " + response);

        // dump proxy logs to file
        proxyClient.dumpToLogAsJava(
                request()
                        .withMethod("POST")
                        .withPath("/login")
        );
    }
}

This produces the following output in the mockserver_request.log file (in the working directory of the JVM running the test):

new MockServerClient("localhost", 1080)
.when(
        request()
                .withMethod("POST")
                .withPath("/login")
                .withHeaders(
                        new Header("Content-Length", "15"),
                        new Header("Content-Type", "text/plain; charset=ISO-8859-1"),
                        new Header("Host", "localhost:1080"),
                        new Header("Proxy-Connection", "Keep-Alive"),
                        new Header("User-Agent", "Apache-HttpClient/4.4.1 (Java/1.6.0_65)"),
                        new Header("Accept-Encoding", "gzip,deflate")
                )
                .withSecure(false)
                .withKeepAlive(true)
                .withBody(new StringBody("an_example_body")),
        Times.once()
)
.respond(
        response()
                .withStatusCode(404)
                .withHeaders(
                        new Header("Access-Control-Expose-Headers", "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary"),
                        new Header("connection", "keep-alive"),
                        new Header("Access-Control-Allow-Headers", "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary"),
                        new Header("Access-Control-Allow-Origin", "*"),
                        new Header("content-length", "0"),
                        new Header("Access-Control-Max-Age", "1"),
                        new Header("Access-Control-Allow-Methods", "CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE"),
                        new Header("X-CORS", "MockServer CORS support enabled by default, to disable ConfigurationProperties.enableCORSForAPI(false) or -Dmockserver.disableCORS=false")
                )
);

If you prefer dumping the requests as JSON the following example does this:

Note: the only difference with the example above is that proxyClient.dumpToLogAsJava(...) is replaced with proxyClient.dumpToLogAsJSON(...)

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
import org.junit.Test;
import org.mockserver.integration.ClientAndProxy;
import org.mockserver.socket.KeyStoreFactory;

import java.io.IOException;
import java.net.URISyntaxException;

import static org.mockserver.integration.ClientAndProxy.startClientAndProxy;
import static org.mockserver.model.HttpRequest.request;

/**
 * @author jamesdbloom
 */
public class testDumpLog {

    @Test
    public void shouldDumpRequestsToLog() throws URISyntaxException, IOException {
        // start proxy
        System.setProperty("logback.configurationFile", "/Users/jamesbloom/git/mockserver/mockserver/mockserver-netty/src/main/resources/example_logback.xml");
        ClientAndProxy proxyClient = startClientAndProxy(1090);

        // create java client configured with proxy
        CloseableHttpClient httpClient = HttpClients
                .custom()
                .setSSLSocketFactory(new SSLConnectionSocketFactory(KeyStoreFactory.keyStoreFactory().sslContext(), NoopHostnameVerifier.INSTANCE))
                .setRoutePlanner(new DefaultProxyRoutePlanner(
                        new HttpHost(
                                System.getProperty("http.proxyHost", "localhost"),
                                Integer.parseInt(System.getProperty("http.proxyPort", String.valueOf(1090)))
                        )
                )).build();

        // send request using java client
        HttpPost request = new HttpPost(
                new URIBuilder()
                        .setScheme("http")
                        .setHost("localhost")
                        .setPort(1080)
                        .setPath("/login")
                        .build()
        );
        request.setEntity(new StringEntity("an_example_body"));
        HttpResponse response = httpClient.execute(request);

        // print out response
        System.out.println("response = " + response);

        // dump proxy logs to file
        proxyClient.dumpToLogAsJSON(
                request()
                        .withMethod("POST")
                        .withPath("/login")
        );
    }
}

This produces the following output in the mockserver_request.log file (in the working directory of the JVM running the test):

{
  "httpRequest" : {
    "method" : "POST",
    "path" : "/login",
    "headers" : [ {
      "name" : "Content-Length",
      "values" : [ "15" ]
    }, {
      "name" : "Content-Type",
      "values" : [ "text/plain; charset=ISO-8859-1" ]
    }, {
      "name" : "Host",
      "values" : [ "localhost:1080" ]
    }, {
      "name" : "Proxy-Connection",
      "values" : [ "Keep-Alive" ]
    }, {
      "name" : "User-Agent",
      "values" : [ "Apache-HttpClient/4.4.1 (Java/1.6.0_65)" ]
    }, {
      "name" : "Accept-Encoding",
      "values" : [ "gzip,deflate" ]
    } ],
    "keepAlive" : true,
    "secure" : false,
    "body" : "an_example_body"
  },
  "httpResponse" : {
    "statusCode" : 404,
    "headers" : [ {
      "name" : "Access-Control-Expose-Headers",
      "values" : [ "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary" ]
    }, {
      "name" : "connection",
      "values" : [ "keep-alive" ]
    }, {
      "name" : "Access-Control-Allow-Headers",
      "values" : [ "Allow, Content-Encoding, Content-Length, Content-Type, ETag, Expires, Last-Modified, Location, Server, Vary" ]
    }, {
      "name" : "Access-Control-Allow-Origin",
      "values" : [ "*" ]
    }, {
      "name" : "content-length",
      "values" : [ "0" ]
    }, {
      "name" : "Access-Control-Max-Age",
      "values" : [ "1" ]
    }, {
      "name" : "Access-Control-Allow-Methods",
      "values" : [ "CONNECT, DELETE, GET, HEAD, OPTIONS, POST, PUT, TRACE" ]
    }, {
      "name" : "X-CORS",
      "values" : [ "MockServer CORS support enabled by default, to disable ConfigurationProperties.enableCORSForAPI(false) or -Dmockserver.disableCORS=false" ]
    } ]
  },
  "times" : {
    "remainingTimes" : 1,
    "unlimited" : false
  },
  "timeToLive" : {
    "unlimited" : true
  }
}
jamesdbloom commented 7 years ago

I am closing this ticket as I can not reproduce this issue.

jamesdbloom commented 7 years ago

Also note the example_logback.xml referred to in the above example code is the file that is bundled with mockserver-netty, but for completeness is look as follows:

<configuration debug="false">
    <!-- to use add system property logback.configurationFile, for example: -Dlogback.configurationFile=/Users/james.bloom/git/mockserver/mockserver-netty/src/main/resources/example_logback.xml -->

    <!-- To completely disable all logging completely -Droot.logLevel=OFF -->

    <!-- application log -->
    <appender name="FILE" class="org.mockserver.logging.DelayedFileCreationRollingFileAppender">
        <file>${log.dir:-./}mockserver.log</file>
        <encoder>
            <pattern>%date %level [%thread] %logger{35} [%file:%line] %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>TRACE</level>
        </filter>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir:-./}mockserver.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>1</maxHistory>
        </rollingPolicy>
    </appender>

    <!-- make application log asynchronous -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="FILE" />
    </appender>

    <!-- application console log (for errors and warnings) -->
    <appender name="STDERR" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.err</target>
        <encoder>
            <pattern>%date %level %logger{20} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>WARN</level>
        </filter>
    </appender>

    <!-- make console log (for errors and warnings) asynchronous -->
    <appender name="ASYNC_STDERR" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="STDERR" />
    </appender>

    <!-- application console log -->
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <target>System.out</target>
        <encoder>
            <pattern>%date %level %logger{20} %msg%n</pattern>
        </encoder>
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator>
                <!--<expression>level &gt;= INFO &amp;&amp; level &lt; WARN</expression>-->
                <expression>level &lt; WARN</expression>
            </evaluator>
            <OnMismatch>DENY</OnMismatch>
            <OnMatch>NEUTRAL</OnMatch>
        </filter>
    </appender>

    <!-- make console log asynchronous -->
    <appender name="ASYNC_STDOUT" class="ch.qos.logback.classic.AsyncAppender">
        <queueSize>128</queueSize>
        <discardingThreshold>0</discardingThreshold>
        <appender-ref ref="STDOUT" />
    </appender>

    <!-- request log configuration -->
    <appender name="REQUEST_LOG" class="org.mockserver.logging.DelayedFileCreationRollingFileAppender">
        <file>${log.dir:-./}mockserver_request.log</file>

        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.dir:-./}mockserver_request.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>100MB</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
    </appender>

    <logger name="REQUEST" level="INFO" additivity="false">
        <appender-ref ref="REQUEST_LOG"/>
    </logger>

    <logger name="org.mockserver" level="${mockserver.logLevel:-WARN}"/>

    <root level="${root.logLevel:-WARN}">
        <appender-ref ref="ASYNC_FILE"/>
        <appender-ref ref="ASYNC_STDERR"/>
        <appender-ref ref="ASYNC_STDOUT"/>
    </root>
</configuration>