Skip to content

Instantly share code, notes, and snippets.

@remkop
Created May 29, 2016 12:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save remkop/715fcd6035c4f798c264e21450106399 to your computer and use it in GitHub Desktop.
Save remkop/715fcd6035c4f798c264e21450106399 to your computer and use it in GitHub Desktop.
Example layout for logging ByteBuffers straight to disk
import java.nio.ByteBuffer;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Node;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;
/**
* Layout for writing ObjectMessages containing a ByteBuffer to the appender.
* The ByteBuffer is expected to be ready for reading, with its current position at the start of the data,
* and its limit at the end of the data.
*/
@Plugin(name = "ByteBufferMessageLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
public final class ByteBufferMessageLayout extends AbstractLayout<byte[]> {
private ByteBufferMessageLayout() {
super(null, null, null);
}
/**
* Creates a ByteBufferMessageLayout.
* @return A ByteBufferMessageLayout.
*/
@PluginFactory
public static ByteBufferMessageLayout createLayout() {
return new ByteBufferMessageLayout();
}
/**
* Extracts and logs the ByteBuffer from the LogEvent message.
* Does nothing if the message payload is not a ByteBuffer.
* <p>
* The ByteBuffer is expected to be ready for reading, with its current
* position at the start of the data, and its limit at the end of the data.
* </p>
*
* @param event The LogEvent.
* @param destination the destination to write the data to
*/
@Override
public void encode(final LogEvent event, final ByteBufferDestination destination) {
final ByteBuffer src = extractByteBuffer(event);
if (src != null) {
ByteBuffer dest = destination.getByteBuffer();
int todo = src.remaining();
int pos = src.position();
while (todo > 0) {
if (dest.remaining() < todo) {
dest = destination.drain(dest);
}
final int count = Math.min(dest.remaining(), src.remaining());
src.position(pos);
src.limit(pos + count);
dest.put(src);
todo -= count;
pos += count;
}
}
}
private ByteBuffer extractByteBuffer(final LogEvent logEvent) {
final Object[] params = logEvent.getMessage().getParameters();
if (params[0] instanceof ByteBuffer) {
return (ByteBuffer) params[0];
}
return null;
}
/**
* Fallback layout method used by appenders if
* {@link org.apache.logging.log4j.core.util.Constants#ENABLE_DIRECT_ENCODERS} is set to false.
*
* @param event The Logging Event.
* @return the data to write to the appender
*/
@Override
public byte[] toByteArray(final LogEvent event) {
final ByteBuffer byteBuffer = extractByteBuffer(event);
if (byteBuffer == null) {
return new byte[0];
}
if (byteBuffer.hasArray() && byteBuffer.remaining() == byteBuffer.capacity()) {
return byteBuffer.array();
}
final byte[] result = new byte[byteBuffer.remaining()];
byteBuffer.get(result);
return result;
}
// not called
@Override
public byte[] toSerializable(final LogEvent event) {
return toByteArray(event);
}
/**
* ByteBufferMessageLayout returns a binary stream.
* @return The content type.
*/
@Override
public String getContentType() {
return "application/octet-stream";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment