1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j.core.appender.mom.jeromq;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.concurrent.TimeUnit;
24
25 import org.apache.logging.log4j.core.Appender;
26 import org.apache.logging.log4j.core.Filter;
27 import org.apache.logging.log4j.core.Layout;
28 import org.apache.logging.log4j.core.LogEvent;
29 import org.apache.logging.log4j.core.appender.AbstractAppender;
30 import org.apache.logging.log4j.core.config.Node;
31 import org.apache.logging.log4j.core.config.Property;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
34 import org.apache.logging.log4j.core.config.plugins.PluginElement;
35 import org.apache.logging.log4j.core.config.plugins.PluginFactory;
36 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
37 import org.apache.logging.log4j.core.layout.PatternLayout;
38 import org.apache.logging.log4j.util.Strings;
39
40
41
42
43
44
45
46
47
48
49
50 @Plugin(name = "JeroMQ", category = Node.CATEGORY, elementType = Appender.ELEMENT_TYPE, printObject = true)
51 public final class JeroMqAppender extends AbstractAppender {
52
53 private static final int DEFAULT_BACKLOG = 100;
54
55 private static final int DEFAULT_IVL = 100;
56
57 private static final int DEFAULT_RCV_HWM = 1000;
58
59 private static final int DEFAULT_SND_HWM = 1000;
60
61 private final JeroMqManager manager;
62 private final List<String> endpoints;
63 private int sendRcFalse;
64 private int sendRcTrue;
65
66 private JeroMqAppender(final String name, final Filter filter, final Layout<? extends Serializable> layout,
67 final boolean ignoreExceptions, final List<String> endpoints, final long affinity, final long backlog,
68 final boolean delayAttachOnConnect, final byte[] identity, final boolean ipv4Only, final long linger,
69 final long maxMsgSize, final long rcvHwm, final long receiveBufferSize, final int receiveTimeOut,
70 final long reconnectIVL, final long reconnectIVLMax, final long sendBufferSize, final int sendTimeOut,
71 final long sndHWM, final int tcpKeepAlive, final long tcpKeepAliveCount, final long tcpKeepAliveIdle,
72 final long tcpKeepAliveInterval, final boolean xpubVerbose) {
73 super(name, filter, layout, ignoreExceptions);
74 this.manager = JeroMqManager.getJeroMqManager(name, affinity, backlog, delayAttachOnConnect, identity, ipv4Only,
75 linger, maxMsgSize, rcvHwm, receiveBufferSize, receiveTimeOut, reconnectIVL, reconnectIVLMax,
76 sendBufferSize, sendTimeOut, sndHWM, tcpKeepAlive, tcpKeepAliveCount, tcpKeepAliveIdle,
77 tcpKeepAliveInterval, xpubVerbose, endpoints);
78 this.endpoints = endpoints;
79 }
80
81
82
83 @PluginFactory
84 public static JeroMqAppender createAppender(
85
86 @Required(message = "No name provided for JeroMqAppender") @PluginAttribute("name") final String name,
87 @PluginElement("Layout") Layout<?> layout,
88 @PluginElement("Filter") final Filter filter,
89 @PluginElement("Properties") final Property[] properties,
90
91 @PluginAttribute("ignoreExceptions") final boolean ignoreExceptions,
92
93 @PluginAttribute(value = "affinity", defaultLong = 0) final long affinity,
94 @PluginAttribute(value = "backlog", defaultLong = DEFAULT_BACKLOG) final long backlog,
95 @PluginAttribute(value = "delayAttachOnConnect") final boolean delayAttachOnConnect,
96 @PluginAttribute(value = "identity") final byte[] identity,
97 @PluginAttribute(value = "ipv4Only", defaultBoolean = true) final boolean ipv4Only,
98 @PluginAttribute(value = "linger", defaultLong = -1) final long linger,
99 @PluginAttribute(value = "maxMsgSize", defaultLong = -1) final long maxMsgSize,
100 @PluginAttribute(value = "rcvHwm", defaultLong = DEFAULT_RCV_HWM) final long rcvHwm,
101 @PluginAttribute(value = "receiveBufferSize", defaultLong = 0) final long receiveBufferSize,
102 @PluginAttribute(value = "receiveTimeOut", defaultLong = -1) final int receiveTimeOut,
103 @PluginAttribute(value = "reconnectIVL", defaultLong = DEFAULT_IVL) final long reconnectIVL,
104 @PluginAttribute(value = "reconnectIVLMax", defaultLong = 0) final long reconnectIVLMax,
105 @PluginAttribute(value = "sendBufferSize", defaultLong = 0) final long sendBufferSize,
106 @PluginAttribute(value = "sendTimeOut", defaultLong = -1) final int sendTimeOut,
107 @PluginAttribute(value = "sndHwm", defaultLong = DEFAULT_SND_HWM) final long sndHwm,
108 @PluginAttribute(value = "tcpKeepAlive", defaultInt = -1) final int tcpKeepAlive,
109 @PluginAttribute(value = "tcpKeepAliveCount", defaultLong = -1) final long tcpKeepAliveCount,
110 @PluginAttribute(value = "tcpKeepAliveIdle", defaultLong = -1) final long tcpKeepAliveIdle,
111 @PluginAttribute(value = "tcpKeepAliveInterval", defaultLong = -1) final long tcpKeepAliveInterval,
112 @PluginAttribute(value = "xpubVerbose") final boolean xpubVerbose
113
114 ) {
115 if (layout == null) {
116 layout = PatternLayout.createDefaultLayout();
117 }
118 List<String> endpoints;
119 if (properties == null) {
120 endpoints = new ArrayList<>(0);
121 } else {
122 endpoints = new ArrayList<>(properties.length);
123 for (final Property property : properties) {
124 if ("endpoint".equalsIgnoreCase(property.getName())) {
125 final String value = property.getValue();
126 if (Strings.isNotEmpty(value)) {
127 endpoints.add(value);
128 }
129 }
130 }
131 }
132 LOGGER.debug("Creating JeroMqAppender with name={}, filter={}, layout={}, ignoreExceptions={}, endpoints={}",
133 name, filter, layout, ignoreExceptions, endpoints);
134 return new JeroMqAppender(name, filter, layout, ignoreExceptions, endpoints, affinity, backlog,
135 delayAttachOnConnect, identity, ipv4Only, linger, maxMsgSize, rcvHwm, receiveBufferSize,
136 receiveTimeOut, reconnectIVL, reconnectIVLMax, sendBufferSize, sendTimeOut, sndHwm, tcpKeepAlive,
137 tcpKeepAliveCount, tcpKeepAliveIdle, tcpKeepAliveInterval, xpubVerbose);
138 }
139
140 @Override
141 public synchronized void append(final LogEvent event) {
142 final Layout<? extends Serializable> layout = getLayout();
143 final byte[] formattedMessage = layout.toByteArray(event);
144 if (manager.send(getLayout().toByteArray(event))) {
145 sendRcTrue++;
146 } else {
147 sendRcFalse++;
148 LOGGER.error("Appender {} could not send message {} to JeroMQ {}", getName(), sendRcFalse, formattedMessage);
149 }
150 }
151
152 @Override
153 public boolean stop(final long timeout, final TimeUnit timeUnit) {
154 setStopping();
155 boolean stopped = super.stop(timeout, timeUnit, false);
156 stopped &= manager.stop(timeout, timeUnit);
157 setStopped();
158 return stopped;
159 }
160
161
162 int getSendRcFalse() {
163 return sendRcFalse;
164 }
165
166
167 int getSendRcTrue() {
168 return sendRcTrue;
169 }
170
171
172 void resetSendRcs() {
173 sendRcTrue = sendRcFalse = 0;
174 }
175
176 @Override
177 public String toString() {
178 return "JeroMqAppender{" +
179 "name=" + getName() +
180 ", state=" + getState() +
181 ", manager=" + manager +
182 ", endpoints=" + endpoints +
183 '}';
184 }
185 }