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 // switch string buffer 171 sb = answer; 172 } 173 174 if (multiline) { 175 sb.insert(0, "Exchange["); 176 sb.append("]"); 177 return sb.toString(); 178 } else { 179 // get rid of the leading space comma if needed 180 if (sb.length() > 0 && sb.charAt(0) == ',' && sb.charAt(1) == ' ') { 181 sb.replace(0, 2, ""); 182 } 183 sb.insert(0, "Exchange["); 184 sb.append("]"); 185 186 return sb.toString(); 187 } 188 } 189 190 public boolean isShowExchangeId() { 191 return showExchangeId; 192 } 193 194 public void setShowExchangeId(boolean showExchangeId) { 195 this.showExchangeId = showExchangeId; 196 } 197 198 public boolean isShowProperties() { 199 return showProperties; 200 } 201 202 public void setShowProperties(boolean showProperties) { 203 this.showProperties = showProperties; 204 } 205 206 public boolean isShowHeaders() { 207 return showHeaders; 208 } 209 210 public void setShowHeaders(boolean showHeaders) { 211 this.showHeaders = showHeaders; 212 } 213 214 public boolean isShowBodyType() { 215 return showBodyType; 216 } 217 218 public void setShowBodyType(boolean showBodyType) { 219 this.showBodyType = showBodyType; 220 } 221 222 public boolean isShowBody() { 223 return showBody; 224 } 225 226 public void setShowBody(boolean showBody) { 227 this.showBody = showBody; 228 } 229 230 public boolean isShowOut() { 231 return showOut; 232 } 233 234 public void setShowOut(boolean showOut) { 235 this.showOut = showOut; 236 } 237 238 public boolean isShowAll() { 239 return showAll; 240 } 241 242 public void setShowAll(boolean showAll) { 243 this.showAll = showAll; 244 } 245 246 public boolean isShowException() { 247 return showException; 248 } 249 250 public void setShowException(boolean showException) { 251 this.showException = showException; 252 } 253 254 public boolean isShowStackTrace() { 255 return showStackTrace; 256 } 257 258 public void setShowStackTrace(boolean showStackTrace) { 259 this.showStackTrace = showStackTrace; 260 } 261 262 public boolean isShowCaughtException() { 263 return showCaughtException; 264 } 265 266 public void setShowCaughtException(boolean showCaughtException) { 267 this.showCaughtException = showCaughtException; 268 } 269 270 public boolean isMultiline() { 271 return multiline; 272 } 273 274 public int getMaxChars() { 275 return maxChars; 276 } 277 278 public void setMaxChars(int maxChars) { 279 this.maxChars = maxChars; 280 } 281 282 /** 283 * If enabled then each information is outputted on a newline. 284 */ 285 public void setMultiline(boolean multiline) { 286 this.multiline = multiline; 287 } 288 289 public boolean isShowFuture() { 290 return showFuture; 291 } 292 293 /** 294 * If enabled Camel will on Future objects wait for it to complete to obtain the payload to be logged. 295 * <p/> 296 * Is default disabled. 297 */ 298 public void setShowFuture(boolean showFuture) { 299 this.showFuture = showFuture; 300 } 301 302 public boolean isShowExchangePattern() { 303 return showExchangePattern; 304 } 305 306 public void setShowExchangePattern(boolean showExchangePattern) { 307 this.showExchangePattern = showExchangePattern; 308 } 309 310 public boolean isShowStreams() { 311 return showStreams; 312 } 313 314 /** 315 * If enabled Camel will output stream objects 316 * <p/> 317 * Is default disabled. 318 */ 319 public void setShowStreams(boolean showStreams) { 320 this.showStreams = showStreams; 321 } 322 323 public boolean isShowFiles() { 324 return showFiles; 325 } 326 327 /** 328 * If enabled Camel will output files 329 * <p/> 330 * Is default disabled. 331 */ 332 public void setShowFiles(boolean showFiles) { 333 this.showFiles = showFiles; 334 } 335 336 // Implementation methods 337 //------------------------------------------------------------------------- 338 protected String getBodyAsString(Message message) { 339 if (message.getBody() instanceof Future) { 340 if (!isShowFuture()) { 341 // just use a to string of the future object 342 return message.getBody().toString(); 343 } 344 } 345 346 return MessageHelper.extractBodyForLogging(message, "", isShowStreams(), isShowFiles(), -1); 347 } 348 349 protected String getBodyTypeAsString(Message message) { 350 String answer = ObjectHelper.classCanonicalName(message.getBody()); 351 if (answer != null && answer.startsWith("java.lang.")) { 352 return answer.substring(10); 353 } 354 return answer; 355 } 356 357 }