+ * Requires the JeroMQ jar (LGPL as of 0.3.5) + *
+ */ +// TODO +// Some methods are synchronized because a ZMQ.Socket is not thread-safe +// Using a ThreadLocal for the publisher hangs tests on shutdown. There must be +// some issue on threads owning certain resources as opposed to others. +@Plugin(name = "JeroMQ", category = "Core", elementType = "appender", printObject = true) +public final class JeroMqAppender extends AbstractAppender { + + // Per ZMQ docs, there should usually only be one ZMQ context per process. + private static volatile ZMQ.Context context; + + private static Logger logger; + + // ZMQ sockets are not thread safe. + private static ZMQ.Socket publisher; + + private static final long serialVersionUID = 1L; + + private static final String SIMPLE_NAME = JeroMqAppender.class.getSimpleName(); + + static final String SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK = "log4j.jeromq.enableShutdownHook"; + + static final String SYS_PROPERTY_IO_THREADS = "log4j.jeromq.ioThreads"; + + static { + logger = StatusLogger.getLogger(); + final PropertiesUtil managerProps = PropertiesUtil.getProperties(); + final Integer ioThreads = managerProps.getIntegerProperty(SYS_PROPERTY_IO_THREADS, 1); + final Boolean enableShutdownHook = managerProps.getBooleanProperty(SYS_PROPERTY_ENABLE_SHUTDOWN_HOOK, true); + final String simpleName = SIMPLE_NAME; + logger.trace("{} using ZMQ version {}", simpleName, ZMQ.getVersionString()); + logger.trace("{} creating ZMQ context with ioThreads={}", simpleName, ioThreads); + context = ZMQ.context(ioThreads); + logger.trace("{} created ZMQ context {}", simpleName, context); + if (enableShutdownHook) { + final Thread hook = new Thread(simpleName + "-shutdown") { + @Override + public void run() { + shutdown(); + } + }; + logger.trace("{} adding shutdown hook {}", simpleName, hook); + Runtime.getRuntime().addShutdownHook(hook); + } + } + + // The ZMQ.Socket class has other set methods that we do not cover because + // they throw unsupported operation exceptions. + @PluginFactory + public static JeroMqAppender createAppender( + // @formatter:off + @Required(message = "No name provided for JeroMqAppender") @PluginAttribute("name") final String name, + @PluginElement("Layout") Layout> layout, + @PluginElement("Filters") final Filter filter, + @PluginElement("Properties") final Property[] properties, + // Super attributes + @PluginAttribute("ignoreExceptions") final boolean ignoreExceptions, + // ZMQ attributes; defaults picked from zmq.Options. + @PluginAttribute(value="affinity", defaultLong=0) final long affinity, + @PluginAttribute(value="backlog", defaultLong=100) final long backlog, + @PluginAttribute(value="delayAttachOnConnect", defaultBoolean=false) final boolean delayAttachOnConnect, + @PluginAttribute(value="identity") final byte[] identity, + @PluginAttribute(value="ipv4Only", defaultBoolean=true) final boolean ipv4Only, + @PluginAttribute(value="linger", defaultLong=-1) final long linger, + @PluginAttribute(value="maxMsgSize", defaultLong=-1) final long maxMsgSize, + @PluginAttribute(value="rcvHwm", defaultLong=1000) final long rcvHwm, + @PluginAttribute(value="receiveBufferSize", defaultLong=0) final long receiveBufferSize, + @PluginAttribute(value="receiveTimeOut", defaultLong=-1) final int receiveTimeOut, + @PluginAttribute(value="reconnectIVL", defaultLong=100) final long reconnectIVL, + @PluginAttribute(value="reconnectIVLMax", defaultLong=0) final long reconnectIVLMax, + @PluginAttribute(value="sendBufferSize", defaultLong=0) final long sendBufferSize, + @PluginAttribute(value="sendTimeOut", defaultLong=-1) final int sendTimeOut, + @PluginAttribute(value="sndHwm", defaultLong=1000) final long sndHwm, + @PluginAttribute(value="tcpKeepAlive", defaultInt=-1) final int tcpKeepAlive, + @PluginAttribute(value="tcpKeepAliveCount", defaultLong=-1) final long tcpKeepAliveCount, + @PluginAttribute(value="tcpKeepAliveIdle", defaultLong=-1) final long tcpKeepAliveIdle, + @PluginAttribute(value="tcpKeepAliveInterval", defaultLong=-1) final long tcpKeepAliveInterval, + @PluginAttribute(value="xpubVerbose", defaultBoolean=false) final boolean xpubVerbose + // @formatter:on + ) { + if (layout == null) { + layout = PatternLayout.createDefaultLayout(); + } + List+ The ZeroMQ appender uses the JeroMQ library to send log + events to one or more endpoints. +
++ This is a simple JeroMQ configuration: +
++++ ]]>+ ++ +tcp://*:5556 +ipc://info-topic ++ ++ ++
+ The table below describes all options. Please consult the JeroMQ and ZeroMQ documentation for details. +
+| Parameter Name | +Type | +Description | +
|---|---|---|
| name | +String | +The name of the Appender. | +
| Layout | +Layout | +The Layout of the Appender. | +
| Filters | +Filter | +The Filters of the Appender. | +
| Property | +Property | +One or more Property elements, named endpoint. | +
| ignoreExceptions | +boolean | +If true, exceptions will be logged and suppressed. If false errors will be logged and then passed to the application. | +
| affinity | +long | +The ZMQ_AFFINITY option. Defaults to 0. | +
| backlog | +long | +The ZMQ_BACKLOG option. Defaults to 100. | +
| delayAttachOnConnect | +boolean | +The ZMQ_DELAY_ATTACH_ON_CONNECT option. Defaults to false. | +
| identity | +byte[] | +The ZMQ_IDENTITY option. Defaults to none. | +
| ipv4Only | +boolean | +The ZMQ_IPV4ONLY option. Defaults to true. | +
| linger | +long | +The ZMQ_LINGER option. Defaults to -1. | +
| maxMsgSize | +long | +The ZMQ_MAXMSGSIZE option. Defaults to -1. | +
| rcvHwm | +long | +The ZMQ_RCVHWM option. Defaults to 1000. | +
| receiveBufferSize | +long | +The ZMQ_RCVBUF option. Defaults to 0. | +
| receiveTimeOut | +int | +The ZMQ_RCVTIMEO option. Defaults to -1. | +
| reconnectIVL | +long | +The ZMQ_RECONNECT_IVL option. Defaults to 100. | +
| reconnectIVLMax | +long | +The ZMQ_RECONNECT_IVL_MAX option. Defaults to 0. | +
| sendBufferSize | +long | +The ZMQ_SNDBUF option. Defaults to 0. | +
| sendTimeOut | +int | +The ZMQ_SNDTIMEO option. Defaults to -1. | +
| sndHwm | +long | +The ZMQ_SNDHWM option. Defaults to 1000. | +
| tcpKeepAlive | +int | +The ZMQ_TCP_KEEPALIVE option. Defaults to -1. | +
| tcpKeepAliveCount | +long | +The ZMQ_TCP_KEEPALIVE_CNT option. Defaults to -1. | +
| tcpKeepAliveIdle | +long | +The ZMQ_TCP_KEEPALIVE_IDLE option. Defaults to -1. | +
| tcpKeepAliveInterval | +long | +The ZMQ_TCP_KEEPALIVE_INTVL option. Defaults to -1. | +
| xpubVerbose | +boolean | +The ZMQ_XPUB_VERBOSE option. Defaults to false. | +