@PerformanceSensitive // NOTE: This is a hot method. Current implementation compiles to 30 bytes of byte code. // This is within the 35 byte MaxInlineSize threshold. Modify with care! private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { try { logMessageTrackRecursion(fqcn, level, marker, msg, throwable); } finally { // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString()) ReusableMessageFactory.release(msg); } }
@Test public void testCreateEventReturnsSameInstance() throws Exception { final ReusableMessageFactory factory = new ReusableMessageFactory(); final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4); ReusableMessageFactory.release(message1); final Message message2 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 9, 8, 7, 6); assertSame(message1, message2); ReusableMessageFactory.release(message2); final Message message3 = factory.newMessage("text, AAA={} BBB={} p2={} p3={}", 9, 8, 7, 6); assertSame(message2, message3); ReusableMessageFactory.release(message3); }
@Test public void testCreateEventReturnsDifferentInstanceIfNotReleased() throws Exception { final ReusableMessageFactory factory = new ReusableMessageFactory(); final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4); final Message message2 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 9, 8, 7, 6); assertNotSame(message1, message2); ReusableMessageFactory.release(message1); ReusableMessageFactory.release(message2); }
@Test public void testCreateEventOverwritesFields() throws Exception { final ReusableMessageFactory factory = new ReusableMessageFactory(); final Message message1 = factory.newMessage("text, p0={} p1={} p2={} p3={}", 1, 2, 3, 4); assertReusableParameterizeMessage(message1, "text, p0={} p1={} p2={} p3={}", new Object[]{ new Integer(1), // new Integer(2), // new Integer(3), // new Integer(4), // }); ReusableMessageFactory.release(message1); final Message message2 = factory.newMessage("other, A={} B={} C={} D={}", 1, 2, 3, 4); assertReusableParameterizeMessage(message1, "other, A={} B={} C={} D={}", new Object[]{ new Integer(1), // new Integer(2), // new Integer(3), // new Integer(4), // }); assertSame(message1, message2); ReusableMessageFactory.release(message2); }
@Test public void testMementoReuse() { final RingBufferLogEvent evt = new RingBufferLogEvent(); // Initialize the event with parameters evt.swapParameters(new Object[10]); final String loggerName = "logger.name"; final Marker marker = MarkerManager.getMarker("marked man"); final String fqcn = "f.q.c.n"; final Level level = Level.TRACE; ReusableMessageFactory factory = new ReusableMessageFactory(); Message message = factory.newMessage("Hello {}!", "World"); try { final Throwable t = new InternalError("not a real error"); final ContextStack contextStack = new MutableThreadContextStack(Arrays.asList("a", "b")); final String threadName = "main"; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, message, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(12345, 678), new DummyNanoClock(1)); ((StringMap) evt.getContextData()).putValue("key", "value"); final Message memento1 = evt.memento(); final Message memento2 = evt.memento(); assertThat(memento1, sameInstance(memento2)); } finally { ReusableMessageFactory.release(message); } }
@Test public void testCreateMementoRetainsParametersAndFormat() { final RingBufferLogEvent evt = new RingBufferLogEvent(); // Initialize the event with parameters evt.swapParameters(new Object[10]); final String loggerName = "logger.name"; final Marker marker = MarkerManager.getMarker("marked man"); final String fqcn = "f.q.c.n"; final Level level = Level.TRACE; ReusableMessageFactory factory = new ReusableMessageFactory(); Message message = factory.newMessage("Hello {}!", "World"); try { final Throwable t = new InternalError("not a real error"); final ContextStack contextStack = new MutableThreadContextStack(Arrays.asList("a", "b")); final String threadName = "main"; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, message, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(12345, 678), new DummyNanoClock(1)); ((StringMap) evt.getContextData()).putValue("key", "value"); final Message actual = evt.createMemento().getMessage(); assertEquals("Hello {}!", actual.getFormat()); assertArrayEquals(new String[]{"World"}, actual.getParameters()); assertEquals("Hello World!", actual.getFormattedMessage()); } finally { ReusableMessageFactory.release(message); } }
@Test public void testLayoutRingBufferEventReusableMessageWithCurlyBraces() throws Exception { final boolean propertiesAsList = false; final AbstractJacksonLayout layout = JsonLayout.newBuilder() .setLocationInfo(false) .setProperties(false) .setPropertiesAsList(propertiesAsList) .setComplete(false) .setCompact(true) .setEventEol(false) .setCharset(StandardCharsets.UTF_8) .setIncludeStacktrace(true) .build(); Message message = ReusableMessageFactory.INSTANCE.newMessage("Testing {}", new TestObj()); try { RingBufferLogEvent ringBufferEvent = new RingBufferLogEvent(); ringBufferEvent.setValues( null, "a.B", null, "f.q.c.n", Level.DEBUG, message, null, new SortedArrayStringMap(), ThreadContext.EMPTY_STACK, 1L, "threadName", 1, null, new SystemClock(), new DummyNanoClock()); final String str = layout.toSerializable(ringBufferEvent); final String expectedMessage = "Testing " + TestObj.TO_STRING_VALUE; assertThat(str, containsString("\"message\":\"" + expectedMessage + '"')); final Log4jLogEvent actual = new Log4jJsonObjectMapper(propertiesAsList, true, false, false).readValue(str, Log4jLogEvent.class); assertEquals(expectedMessage, actual.getMessage().getFormattedMessage()); } finally { ReusableMessageFactory.release(message); } }
assertEquals(expectedMessage, actual.getMessage().getFormattedMessage()); } finally { ReusableMessageFactory.release(message);
@PerformanceSensitive // NOTE: This is a hot method. Current implementation compiles to 30 bytes of byte code. // This is within the 35 byte MaxInlineSize threshold. Modify with care! private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { try { tryLogMessage(fqcn, level, marker, msg, throwable); } finally { // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString()) ReusableMessageFactory.release(msg); } }