001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.component.log;
018
019 import java.io.PrintWriter;
020 import java.io.StringWriter;
021 import java.util.concurrent.Future;
022
023 import org.apache.camel.Exchange;
024 import org.apache.camel.Message;
025 import org.apache.camel.spi.ExchangeFormatter;
026 import org.apache.camel.util.MessageHelper;
027 import org.apache.camel.util.ObjectHelper;
028
029 /**
030 * Logger formatter to format the logging output.
031 */
032 public class LogFormatter implements ExchangeFormatter {
033
034 protected static final String LS = System.getProperty("line.separator");
035
036 private boolean showExchangeId;
037 private boolean showExchangePattern = true;
038 private boolean showProperties;
039 private boolean showHeaders;
040 private boolean showBodyType = true;
041 private boolean showBody = true;
042 private boolean showOut;
043 private boolean showException;
044 private boolean showCaughtException;
045 private boolean showStackTrace;
046 private boolean showAll;
047 private boolean multiline;
048 private boolean showFuture;
049 private boolean showStreams;
050 private boolean showFiles;
051 private int maxChars = 10000;
052
053 public String format(Exchange exchange) {
054 Message in = exchange.getIn();
055
056 StringBuilder sb = new StringBuilder();
057 if (showAll || showExchangeId) {
058 if (multiline) {
059 sb.append(LS);
060 }
061 sb.append(", Id:").append(exchange.getExchangeId());
062 }
063 if (showAll || showExchangePattern) {
064 if (multiline) {
065 sb.append(LS);
066 }
067 sb.append(", ExchangePattern:").append(exchange.getPattern());
068 }
069
070 if (showAll || showProperties) {
071 if (multiline) {
072 sb.append(LS);
073 }
074 sb.append(", Properties:").append(exchange.getProperties());
075 }
076 if (showAll || showHeaders) {
077 if (multiline) {
078 sb.append(LS);
079 }
080 sb.append(", Headers:").append(in.getHeaders());
081 }
082 if (showAll || showBodyType) {
083 if (multiline) {
084 sb.append(LS);
085 }
086 sb.append(", BodyType:").append(getBodyTypeAsString(in));
087 }
088 if (showAll || showBody) {
089 if (multiline) {
090 sb.append(LS);
091 }
092 sb.append(", Body:").append(getBodyAsString(in));
093 }
094
095 if (showAll || showException || showCaughtException) {
096
097 // try exception on exchange first
098 Exception exception = exchange.getException();
099 boolean caught = false;
100 if ((showAll || showCaughtException) && exception == null) {
101 // fallback to caught exception
102 exception = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
103 caught = true;
104 }
105
106 if (exception != null) {
107 if (multiline) {
108 sb.append(LS);
109 }
110 if (caught) {
111 sb.append(", CaughtExceptionType:").append(exception.getClass().getCanonicalName());
112 sb.append(", CaughtExceptionMessage:").append(exception.getMessage());
113 } else {
114 sb.append(", ExceptionType:").append(exception.getClass().getCanonicalName());
115 sb.append(", ExceptionMessage:").append(exception.getMessage());
116 }
117 if (showAll || showStackTrace) {
118 StringWriter sw = new StringWriter();
119 exception.printStackTrace(new PrintWriter(sw));
120 sb.append(", StackTrace:").append(sw.toString());
121 }
122 }
123 }
124
125 if (showAll || showOut) {
126 if (exchange.hasOut()) {
127 Message out = exchange.getOut();
128 if (showAll || showHeaders) {
129 if (multiline) {
130 sb.append(LS);
131 }
132 sb.append(", OutHeaders:").append(out.getHeaders());
133 }
134 if (showAll || showBodyType) {
135 if (multiline) {
136 sb.append(LS);
137 }
138 sb.append(", OutBodyType:").append(getBodyTypeAsString(out));
139 }
140 if (showAll || showBody) {
141 if (multiline) {
142 sb.append(LS);
143 }
144 sb.append(", OutBody:").append(getBodyAsString(out));
145 }
146 } else {
147 if (multiline) {
148 sb.append(LS);
149 }
150 sb.append(", Out: null");
151 }
152 }
153
154 if (maxChars > 0) {
155 StringBuilder answer = new StringBuilder();
156 for (String s : sb.toString().split(LS)) {
157 if (s != null) {
158 if (s.length() > maxChars) {
159 s = s.substring(0, maxChars);
160 answer.append(s).append("...");
161 } else {
162 answer.append(s);
163 }
164 if (multiline) {
165 answer.append(LS);
166 }
167 }
168 }
169
170 // get rid of the leading space comma if needed
171 return "Exchange[" + (multiline ? answer.append(']').toString() : answer.toString().substring(2) + "]");
172 }
173
174 // get rid of the leading space comma if needed
175 return "Exchange[" + (multiline ? sb.append(']').toString() : sb.toString().substring(2) + "]");
176 }
177
178 public boolean isShowExchangeId() {
179 return showExchangeId;
180 }
181
182 public void setShowExchangeId(boolean showExchangeId) {
183 this.showExchangeId = showExchangeId;
184 }
185
186 public boolean isShowProperties() {
187 return showProperties;
188 }
189
190 public void setShowProperties(boolean showProperties) {
191 this.showProperties = showProperties;
192 }
193
194 public boolean isShowHeaders() {
195 return showHeaders;
196 }
197
198 public void setShowHeaders(boolean showHeaders) {
199 this.showHeaders = showHeaders;
200 }
201
202 public boolean isShowBodyType() {
203 return showBodyType;
204 }
205
206 public void setShowBodyType(boolean showBodyType) {
207 this.showBodyType = showBodyType;
208 }
209
210 public boolean isShowBody() {
211 return showBody;
212 }
213
214 public void setShowBody(boolean showBody) {
215 this.showBody = showBody;
216 }
217
218 public boolean isShowOut() {
219 return showOut;
220 }
221
222 public void setShowOut(boolean showOut) {
223 this.showOut = showOut;
224 }
225
226 public boolean isShowAll() {
227 return showAll;
228 }
229
230 public void setShowAll(boolean showAll) {
231 this.showAll = showAll;
232 }
233
234 public boolean isShowException() {
235 return showException;
236 }
237
238 public void setShowException(boolean showException) {
239 this.showException = showException;
240 }
241
242 public boolean isShowStackTrace() {
243 return showStackTrace;
244 }
245
246 public void setShowStackTrace(boolean showStackTrace) {
247 this.showStackTrace = showStackTrace;
248 }
249
250 public boolean isShowCaughtException() {
251 return showCaughtException;
252 }
253
254 public void setShowCaughtException(boolean showCaughtException) {
255 this.showCaughtException = showCaughtException;
256 }
257
258 public boolean isMultiline() {
259 return multiline;
260 }
261
262 public int getMaxChars() {
263 return maxChars;
264 }
265
266 public void setMaxChars(int maxChars) {
267 this.maxChars = maxChars;
268 }
269
270 /**
271 * If enabled then each information is outputted on a newline.
272 */
273 public void setMultiline(boolean multiline) {
274 this.multiline = multiline;
275 }
276
277 public boolean isShowFuture() {
278 return showFuture;
279 }
280
281 /**
282 * If enabled Camel will on Future objects wait for it to complete to obtain the payload to be logged.
283 * <p/>
284 * Is default disabled.
285 */
286 public void setShowFuture(boolean showFuture) {
287 this.showFuture = showFuture;
288 }
289
290 public boolean isShowExchangePattern() {
291 return showExchangePattern;
292 }
293
294 public void setShowExchangePattern(boolean showExchangePattern) {
295 this.showExchangePattern = showExchangePattern;
296 }
297
298 public boolean isShowStreams() {
299 return showStreams;
300 }
301
302 /**
303 * If enabled Camel will output stream objects
304 * <p/>
305 * Is default disabled.
306 */
307 public void setShowStreams(boolean showStreams) {
308 this.showStreams = showStreams;
309 }
310
311 public boolean isShowFiles() {
312 return showFiles;
313 }
314
315 /**
316 * If enabled Camel will output files
317 * <p/>
318 * Is default disabled.
319 */
320 public void setShowFiles(boolean showFiles) {
321 this.showFiles = showFiles;
322 }
323
324 // Implementation methods
325 //-------------------------------------------------------------------------
326 protected String getBodyAsString(Message message) {
327 if (message.getBody() instanceof Future) {
328 if (!isShowFuture()) {
329 // just use a to string of the future object
330 return message.getBody().toString();
331 }
332 }
333
334 return MessageHelper.extractBodyForLogging(message, "", isShowStreams(), isShowFiles(), -1);
335 }
336
337 protected String getBodyTypeAsString(Message message) {
338 String answer = ObjectHelper.classCanonicalName(message.getBody());
339 if (answer != null && answer.startsWith("java.lang.")) {
340 return answer.substring(10);
341 }
342 return answer;
343 }
344
345 }