/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache license, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the license for the specific language governing permissions and
 * limitations under the license.
 */
package org.apache.logging.log4j.perf.jmh;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.impl.Log4jLogEvent;
import org.apache.logging.log4j.message.Message;
import org.apache.logging.log4j.message.SimpleMessage;
import org.openjdk.jmh.annotations.GenerateMicroBenchmark;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.logic.BlackHole;

import java.io.Serializable;

@State(Scope.Thread)
public class Log4jLogEventBenchmark {
    private static Message MESSAGE;
    private static Throwable ERROR;

    @Setup
    public void setup() {
        MESSAGE = new SimpleMessage("Test message");
        ERROR = new Exception("test");
    }

    @GenerateMicroBenchmark
    public void testBaseline(final BlackHole bh) {
    }

    @GenerateMicroBenchmark
    public void testNoException(final BlackHole bh) {
        final Throwable t = null;
        final Log4jLogEvent event = new Log4jLogEvent("a.b.c", null, "a.b.c", Level.INFO, MESSAGE, t);
        bh.consume(event);
    }

    @GenerateMicroBenchmark
    public void testNoExceptionUsingBuilder(final BlackHole bh) {
        final LogEvent event = Log4jLogEvent.newBuilder()
            .setLoggerName("a.b.c")
            .setLoggerFqcn("a.b.c")
            .setLevel(Level.INFO)
            .setMessage(MESSAGE)
            .build();
        bh.consume(event);
    }

    @GenerateMicroBenchmark
    public void testException(final BlackHole bh) {
        final LogEvent event = Log4jLogEvent.newBuilder()
            .setLoggerName("a.b.c")
            .setLoggerFqcn("a.b.c")
            .setLevel(Level.INFO)
            .setMessage(MESSAGE)
            .setThrown(ERROR)
            .build();
        bh.consume(event);
    }

    @GenerateMicroBenchmark
    public void testSourceLocation(final BlackHole bh) {
        final LogEvent event = Log4jLogEvent.newBuilder()
            .setLoggerName(this.getClass().getName())
            .setLoggerFqcn(this.getClass().getName())
            .setLevel(Level.INFO)
            .setMessage(MESSAGE)
            .build();
        event.setIncludeLocation(true);
        final StackTraceElement source = event.getSource();
        bh.consume(source);
    }

    @GenerateMicroBenchmark
    public void testSerializationWithoutException(final BlackHole bh) {
        final Log4jLogEvent event = new Log4jLogEvent("a.b.c", null, "a.b.c", Level.INFO, MESSAGE, null);
        final Serializable serializable = Log4jLogEvent.serialize(event, false);
        bh.consume(serializable);
    }

    @GenerateMicroBenchmark
    public void testSerializationWithException(final BlackHole bh) {
        final Log4jLogEvent event = new Log4jLogEvent("a.b.c", null, "a.b.c", Level.INFO, MESSAGE, ERROR);
        final Serializable serializable = Log4jLogEvent.serialize(event, false);
        bh.consume(serializable);
    }

    // ============================== HOW TO RUN THIS TEST: ====================================
    //
    // In sampling mode (latency test):
    // java -jar log4j-perf/target/microbenchmarks.jar ".*Log4jLogEventBenchmark.*" -i 5 -f 1 -wi 5 -bm sample -tu ns
    //
    // Throughput test:
    // java -jar microbenchmarks.jar ".*Log4jLogEventBenchmark.*" -i 5 -f 1 -wi 5 -bm Throughput -tu ms
    //
    // Usage help:
    // java -jar log4j-perf/target/microbenchmarks.jar -help
    //
}

@@ -1738,120 +1738,66 @@
 lic 
-void testNoException(final BlackHole bh) %7B%0A        final Throwable t = null;%0A        final Log4jLogEvent event =
+LogEvent createLogEventWithoutException() %7B%0A        return
  new
@@ -1860,36 +1860,12 @@
 GE, 
-t);%0A        bh.consume(event
+null
 );%0A 
@@ -1913,93 +1913,78 @@
 lic 
-void testNoExceptionUsingBuilder(final BlackHole bh) %7B%0A        final LogEvent event =
+LogEvent createLogEventWithoutExceptionUsingBuilder() %7B%0A        return
  Log
@@ -2172,35 +2172,8 @@
 ();%0A
-        bh.consume(event);%0A
     
@@ -2218,79 +2218,75 @@
 lic 
-void testException(final BlackHole bh) %7B%0A        final LogEvent event =
+LogEvent createLogEventWithExceptionUsingBuilder() %7B%0A        return
  Log
@@ -2504,35 +2504,8 @@
 ();%0A
-        bh.consume(event);%0A
     
@@ -2550,50 +2550,54 @@
 lic 
-void testSourceLocation(final BlackHole bh
+StackTraceElement getSourceLocationOfLogEvent(
 ) %7B%0A
@@ -2903,191 +2903,141 @@
     
-final StackTraceElement source = event.getSource();%0A        bh.consume(source);%0A    %7D%0A%0A    @GenerateMicroBenchmark%0A    public void testSerializationWithoutException(final BlackHole bh
+return event.getSource();%0A    %7D%0A%0A    @GenerateMicroBenchmark%0A    public Serializable createSerializableLogEventProxyWithoutException(
 ) %7B%0A
@@ -3154,41 +3154,14 @@
     
-final Serializable serializable =
+return
  Log
@@ -3200,42 +3200,8 @@
 e);%0A
-        bh.consume(serializable);%0A
     
@@ -3246,30 +3246,52 @@
 lic 
-void testSerialization
+Serializable createSerializableLogEventProxy
 With
@@ -3441,41 +3441,14 @@
     
-final Serializable serializable =
+return
  Log
@@ -3487,42 +3487,8 @@
 e);%0A
-        bh.consume(serializable);%0A
     

Use return values instead of BlackHole. Improves test readability since we're only generating single values in these tests.