1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.layout;
18
19 import java.nio.charset.Charset;
20 import java.nio.charset.StandardCharsets;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.Locale;
25 import java.util.Map;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29 import org.apache.logging.log4j.core.Layout;
30 import org.apache.logging.log4j.core.LogEvent;
31 import org.apache.logging.log4j.core.config.Node;
32 import org.apache.logging.log4j.core.config.plugins.Plugin;
33 import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
34 import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
35 import org.apache.logging.log4j.core.net.Facility;
36 import org.apache.logging.log4j.core.net.Priority;
37 import org.apache.logging.log4j.core.util.NetUtils;
38 import org.apache.logging.log4j.util.Chars;
39
40
41
42
43 @Plugin(name = "SyslogLayout", category = Node.CATEGORY, elementType = Layout.ELEMENT_TYPE, printObject = true)
44 public final class SyslogLayout extends AbstractStringLayout {
45
46
47
48
49
50
51
52
53
54
55
56
57 public static class Builder<B extends Builder<B>> extends AbstractStringLayout.Builder<B>
58 implements org.apache.logging.log4j.core.util.Builder<SyslogLayout> {
59
60 public Builder() {
61 super();
62 setCharset(StandardCharsets.UTF_8);
63 }
64
65 @PluginBuilderAttribute
66 private Facility facility = Facility.LOCAL0;
67
68 @PluginBuilderAttribute("newLine")
69 private boolean includeNewLine;
70
71 @PluginBuilderAttribute("newLineEscape")
72 private String escapeNL;
73
74 @Override
75 public SyslogLayout build() {
76 return new SyslogLayout(facility, includeNewLine, escapeNL, getCharset());
77 }
78
79 public Facility getFacility() {
80 return facility;
81 }
82
83 public boolean isIncludeNewLine() {
84 return includeNewLine;
85 }
86
87 public String getEscapeNL() {
88 return escapeNL;
89 }
90
91 public B setFacility(final Facility facility) {
92 this.facility = facility;
93 return asBuilder();
94 }
95
96 public B setIncludeNewLine(final boolean includeNewLine) {
97 this.includeNewLine = includeNewLine;
98 return asBuilder();
99 }
100
101 public B setEscapeNL(final String escapeNL) {
102 this.escapeNL = escapeNL;
103 return asBuilder();
104 }
105
106 }
107
108 @PluginBuilderFactory
109 public static <B extends Builder<B>> B newBuilder() {
110 return new Builder<B>().asBuilder();
111 }
112
113
114
115
116 public static final Pattern NEWLINE_PATTERN = Pattern.compile("\\r?\\n");
117
118 private final Facility facility;
119 private final boolean includeNewLine;
120 private final String escapeNewLine;
121
122
123
124
125 private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMM dd HH:mm:ss", Locale.ENGLISH);
126
127
128
129
130 private final String localHostname = NetUtils.getLocalHostname();
131
132 protected SyslogLayout(final Facility facility, final boolean includeNL, final String escapeNL, final Charset charset) {
133 super(charset);
134 this.facility = facility;
135 this.includeNewLine = includeNL;
136 this.escapeNewLine = escapeNL == null ? null : Matcher.quoteReplacement(escapeNL);
137 }
138
139
140
141
142
143
144
145 @Override
146 public String toSerializable(final LogEvent event) {
147 final StringBuilder buf = getStringBuilder();
148
149 buf.append('<');
150 buf.append(Priority.getPriority(facility, event.getLevel()));
151 buf.append('>');
152 addDate(event.getTimeMillis(), buf);
153 buf.append(Chars.SPACE);
154 buf.append(localHostname);
155 buf.append(Chars.SPACE);
156
157 String message = event.getMessage().getFormattedMessage();
158 if (null != escapeNewLine) {
159 message = NEWLINE_PATTERN.matcher(message).replaceAll(escapeNewLine);
160 }
161 buf.append(message);
162
163 if (includeNewLine) {
164 buf.append('\n');
165 }
166 return buf.toString();
167 }
168
169 private synchronized void addDate(final long timestamp, final StringBuilder buf) {
170 final int index = buf.length() + 4;
171 buf.append(dateFormat.format(new Date(timestamp)));
172
173 if (buf.charAt(index) == '0') {
174 buf.setCharAt(index, Chars.SPACE);
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189
190 @Override
191 public Map<String, String> getContentFormat() {
192 final Map<String, String> result = new HashMap<>();
193 result.put("structured", "false");
194 result.put("formatType", "logfilepatternreceiver");
195 result.put("dateFormat", dateFormat.toPattern());
196 result.put("format", "<LEVEL>TIMESTAMP PROP(HOSTNAME) MESSAGE");
197 return result;
198 }
199
200
201
202
203
204
205
206
207
208
209
210 @Deprecated
211 public static SyslogLayout createLayout(final Facility facility, final boolean includeNewLine,
212 final String escapeNL, final Charset charset) {
213 return new SyslogLayout(facility, includeNewLine, escapeNL, charset);
214 }
215
216
217
218
219
220
221 public Facility getFacility() {
222 return facility;
223 }
224 }