@Test public void testSerializationDeserialization() throws IOException, ClassNotFoundException { final RingBufferLogEvent evt = new RingBufferLogEvent(); final String loggerName = "logger.name"; final Marker marker = null; final String threadName = "main"; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(12345, 678), new DummyNanoClock(1)); ((StringMap) evt.getContextData()).putValue("key", "value"); assertEquals(loggerName, other.getLoggerName()); assertEquals(marker, other.getMarker()); assertEquals(fqcn, other.getLoggerFqcn()); assertEquals(level, other.getLevel()); assertEquals(data, other.getMessage()); assertNull("null after serialization", other.getThrown()); assertEquals(new ThrowableProxy(t), other.getThrownProxy()); assertEquals(evt.getContextData(), other.getContextData()); assertEquals(contextStack, other.getContextStack()); assertEquals(threadName, other.getThreadName()); assertEquals(location, other.getSource()); assertEquals(12345, other.getTimeMillis()); assertEquals(678, other.getInstant().getNanoOfMillisecond());
@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 testForEachParameterNothingSet() { final RingBufferLogEvent evt = new RingBufferLogEvent(); evt.forEachParameter(new ParameterConsumer<Void>() { @Override public void accept(Object parameter, int parameterIndex, Void state) { fail("Should not have been called"); } }, null); } }
@Test public void testMessageTextNeverThrowsNpe() { final RingBufferLogEvent evt = new RingBufferLogEvent(); try { evt.getFormattedMessage(); } catch (final NullPointerException e) { fail("the messageText field was not set"); } }
@Test public void testGetLevelReturnsOffIfNullLevelSet() { final RingBufferLogEvent evt = new RingBufferLogEvent(); final String loggerName = null; final Marker marker = null; final String fqcn = null; final Level level = null; final Message data = null; final Throwable t = null; final ContextStack contextStack = null; final String threadName = null; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(), new DummyNanoClock(1)); assertEquals(Level.OFF, evt.getLevel()); }
@Test public void testGetMillisReturnsConstructorMillisForNormalMessage() { final RingBufferLogEvent evt = new RingBufferLogEvent(); final String loggerName = null; final Marker marker = null; final String fqcn = null; final Level level = null; final Message data = null; final Throwable t = null; final ContextStack contextStack = null; final String threadName = null; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(123, 456), new DummyNanoClock(1)); assertEquals(123, evt.getTimeMillis()); assertEquals(456, evt.getInstant().getNanoOfMillisecond()); }
@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 testGetMessageReturnsNonNullMessage() { final RingBufferLogEvent evt = new RingBufferLogEvent(); final String loggerName = null; final Marker marker = null; final String fqcn = null; final Level level = null; final Message data = null; final Throwable t = null; final ContextStack contextStack = null; final String threadName = null; final StackTraceElement location = null; evt.setValues(null, loggerName, marker, fqcn, level, data, t, (StringMap) evt.getContextData(), contextStack, -1, threadName, -1, location, new FixedPreciseClock(), new DummyNanoClock(1)); assertNotNull(evt.getMessage()); }
@Override public void translateTo(final RingBufferLogEvent event, final long sequence) { event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, thrown, // config properties are taken care of in the EventHandler thread // in the AsyncLogger#actualAsyncLog method injector.injectContextData(null, (StringMap) event.getContextData()), contextStack, threadId, threadName, threadPriority, location, currentTimeMillis, nanoTime); clear(); // clear the translator }
@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); } }
StringMap contextData = (StringMap) event.getContextData(); if (contextData.isFrozen()) { final StringMap temp = ContextDataFactory.createContextData(); contextData.putValue(prop.getName(), value); event.setContextData(contextData);
/** * Initializes the specified {@code Log4jLogEvent.Builder} from this {@code RingBufferLogEvent}. * @param builder the builder whose fields to populate */ public void initializeBuilder(final Log4jLogEvent.Builder builder) { builder.setContextData(contextData) // .setContextStack(contextStack) // .setEndOfBatch(endOfBatch) // .setIncludeLocation(includeLocation) // .setLevel(getLevel()) // ensure non-null .setLoggerFqcn(fqcn) // .setLoggerName(loggerName) // .setMarker(marker) // .setMessage(getNonNullImmutableMessage()) // ensure non-null & immutable .setNanoTime(nanoTime) // .setSource(location) // .setThreadId(threadId) // .setThreadName(threadName) // .setThreadPriority(threadPriority) // .setThrown(getThrown()) // may deserialize from thrownProxy .setThrownProxy(thrownProxy) // avoid unnecessarily creating thrownProxy .setTimeMillis(currentTimeMillis); }
@Test public void testToImmutable() { final LogEvent logEvent = new RingBufferLogEvent(); Assert.assertNotSame(logEvent, logEvent.toImmutable()); }
private LogEvent ensureImmutable(final LogEvent event) { LogEvent result = event; if (event instanceof RingBufferLogEvent) { // Deal with special case where both types of Async Loggers are used together: // RingBufferLogEvents are created by the all-loggers-async type, but // this event is also consumed by the some-loggers-async type (this class). // The original event will be re-used and modified in an application thread later, // so take a snapshot of it, which can be safely processed in the // some-loggers-async background thread. result = ((RingBufferLogEvent) event).createMemento(); } return result; }
/** * @see ReusableMessage#getThrowable() */ @Override public Throwable getThrowable() { return getThrown(); }
private void writeObject(final java.io.ObjectOutputStream out) throws IOException { getThrownProxy(); // initialize the ThrowableProxy before serializing out.defaultWriteObject(); }
@Override public void onEvent(final RingBufferLogEvent event, final long sequence, final boolean endOfBatch) throws Exception { event.execute(endOfBatch); event.clear(); // notify the BatchEventProcessor that the sequence has progressed. // Without this callback the sequence would not be progressed // until the batch has completely finished. if (++counter > NOTIFY_PROGRESS_THRESHOLD) { sequenceCallback.set(sequence); counter = 0; } }
@Override public void translateTo(final RingBufferLogEvent event, final long sequence, final Object... args) { // Implementation note: candidate for optimization: exceeds 35 bytecodes. final AsyncLogger asyncLogger = (AsyncLogger) args[0]; final StackTraceElement location = (StackTraceElement) args[1]; final String fqcn = (String) args[2]; final Level level = (Level) args[3]; final Marker marker = (Marker) args[4]; final Message message = (Message) args[5]; final Throwable thrown = (Throwable) args[6]; // needs shallow copy to be fast (LOG4J2-154) final ContextStack contextStack = ThreadContext.getImmutableStack(); final Thread currentThread = Thread.currentThread(); final String threadName = THREAD_NAME_CACHING_STRATEGY.getThreadName(); event.setValues(asyncLogger, asyncLogger.getName(), marker, fqcn, level, message, thrown, // config properties are taken care of in the EventHandler thread // in the AsyncLogger#actualAsyncLog method CONTEXT_DATA_INJECTOR.injectContextData(null, (StringMap) event.getContextData()), contextStack, currentThread.getId(), threadName, currentThread.getPriority(), location, CLOCK.currentTimeMillis(), nanoClock.nanoTime()); }
@Override public RingBufferLogEvent newInstance() { final RingBufferLogEvent result = new RingBufferLogEvent(); if (Constants.ENABLE_THREADLOCALS) { result.messageText = new StringBuilder(Constants.INITIAL_REUSABLE_MESSAGE_SIZE); result.parameters = new Object[10]; } return result; } }
@Override public LogEvent toImmutable() { return createMemento(); }