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 */ 017package org.apache.camel.processor.interceptor; 018 019import org.apache.camel.Exchange; 020import org.apache.camel.Message; 021import org.apache.camel.RouteNode; 022import org.apache.camel.model.ProcessorDefinition; 023import org.apache.camel.model.ProcessorDefinitionHelper; 024import org.apache.camel.model.RouteDefinition; 025import org.apache.camel.spi.TracedRouteNodes; 026import org.apache.camel.util.MessageHelper; 027 028/** 029 * @version 030 */ 031@Deprecated 032public class DefaultTraceFormatter implements TraceFormatter { 033 034 protected static final String LS = System.lineSeparator(); 035 private static final String SEPARATOR = "###REPLACE_ME###"; 036 037 private int breadCrumbLength; 038 private int nodeLength; 039 private boolean showBreadCrumb = true; 040 private boolean showNode = true; 041 private boolean showExchangeId; 042 private boolean showShortExchangeId; 043 private boolean showExchangePattern = true; 044 private boolean showProperties; 045 private boolean showHeaders = true; 046 private boolean showBody = true; 047 private boolean showBodyType = true; 048 private boolean showOutHeaders; 049 private boolean showOutBody; 050 private boolean showOutBodyType; 051 private boolean showException = true; 052 private boolean showRouteId = true; 053 private boolean multiline; 054 055 private int maxChars = 10000; 056 057 public Object format(final TraceInterceptor interceptor, final ProcessorDefinition<?> node, final Exchange exchange) { 058 Message in = exchange.getIn(); 059 Message out = null; 060 if (exchange.hasOut()) { 061 out = exchange.getOut(); 062 } 063 064 StringBuilder sb = new StringBuilder(); 065 if (multiline) { 066 sb.append(SEPARATOR); 067 } 068 sb.append(extractBreadCrumb(interceptor, node, exchange)); 069 070 if (showExchangePattern) { 071 if (multiline) { 072 sb.append(SEPARATOR); 073 } 074 sb.append(", Pattern:").append(exchange.getPattern()); 075 } 076 // only show properties if we have any 077 if (showProperties && !exchange.getProperties().isEmpty()) { 078 if (multiline) { 079 sb.append(SEPARATOR); 080 } 081 sb.append(", Properties:").append(exchange.getProperties()); 082 } 083 // only show headers if we have any 084 if (showHeaders && !in.getHeaders().isEmpty()) { 085 if (multiline) { 086 sb.append(SEPARATOR); 087 } 088 sb.append(", Headers:").append(in.getHeaders()); 089 } 090 if (showBodyType) { 091 if (multiline) { 092 sb.append(SEPARATOR); 093 } 094 sb.append(", BodyType:").append(MessageHelper.getBodyTypeName(in)); 095 } 096 if (showBody) { 097 if (multiline) { 098 sb.append(SEPARATOR); 099 } 100 sb.append(", Body:").append(MessageHelper.extractBodyForLogging(in, "")); 101 } 102 if (showOutHeaders && out != null) { 103 if (multiline) { 104 sb.append(SEPARATOR); 105 } 106 sb.append(", OutHeaders:").append(out.getHeaders()); 107 } 108 if (showOutBodyType && out != null) { 109 if (multiline) { 110 sb.append(SEPARATOR); 111 } 112 sb.append(", OutBodyType:").append(MessageHelper.getBodyTypeName(out)); 113 } 114 if (showOutBody && out != null) { 115 if (multiline) { 116 sb.append(SEPARATOR); 117 } 118 sb.append(", OutBody:").append(MessageHelper.extractBodyForLogging(out, "")); 119 } 120 if (showException && exchange.getException() != null) { 121 if (multiline) { 122 sb.append(SEPARATOR); 123 } 124 sb.append(", Exception:").append(exchange.getException()); 125 } 126 127 // replace ugly <<<, with <<< 128 sb = new StringBuilder(sb.toString().replaceFirst("<<<,", "<<<")); 129 130 if (maxChars > 0) { 131 StringBuilder answer = new StringBuilder(); 132 for (String s : sb.toString().split(SEPARATOR)) { 133 if (s != null) { 134 if (s.length() > maxChars) { 135 s = s.substring(0, maxChars); 136 answer.append(s).append("..."); 137 } else { 138 answer.append(s); 139 } 140 if (multiline) { 141 answer.append(LS); 142 } 143 } 144 } 145 146 // switch string buffer 147 sb = answer; 148 } 149 150 return sb.toString(); 151 } 152 153 public boolean isShowBody() { 154 return showBody; 155 } 156 157 public void setShowBody(boolean showBody) { 158 this.showBody = showBody; 159 } 160 161 public boolean isShowBodyType() { 162 return showBodyType; 163 } 164 165 public void setShowBodyType(boolean showBodyType) { 166 this.showBodyType = showBodyType; 167 } 168 169 public void setShowOutBody(boolean showOutBody) { 170 this.showOutBody = showOutBody; 171 } 172 173 public boolean isShowOutBody() { 174 return showOutBody; 175 } 176 177 public void setShowOutBodyType(boolean showOutBodyType) { 178 this.showOutBodyType = showOutBodyType; 179 } 180 181 public boolean isShowOutBodyType() { 182 return showOutBodyType; 183 } 184 185 public boolean isShowBreadCrumb() { 186 return showBreadCrumb; 187 } 188 189 public void setShowBreadCrumb(boolean showBreadCrumb) { 190 this.showBreadCrumb = showBreadCrumb; 191 } 192 193 public boolean isShowExchangeId() { 194 return showExchangeId; 195 } 196 197 public void setShowExchangeId(boolean showExchangeId) { 198 this.showExchangeId = showExchangeId; 199 } 200 201 public boolean isShowHeaders() { 202 return showHeaders; 203 } 204 205 public void setShowHeaders(boolean showHeaders) { 206 this.showHeaders = showHeaders; 207 } 208 209 public boolean isShowOutHeaders() { 210 return showOutHeaders; 211 } 212 213 public void setShowOutHeaders(boolean showOutHeaders) { 214 this.showOutHeaders = showOutHeaders; 215 } 216 217 public boolean isShowProperties() { 218 return showProperties; 219 } 220 221 public void setShowProperties(boolean showProperties) { 222 this.showProperties = showProperties; 223 } 224 225 public boolean isShowNode() { 226 return showNode; 227 } 228 229 public void setShowNode(boolean showNode) { 230 this.showNode = showNode; 231 } 232 233 public boolean isShowExchangePattern() { 234 return showExchangePattern; 235 } 236 237 public void setShowExchangePattern(boolean showExchangePattern) { 238 this.showExchangePattern = showExchangePattern; 239 } 240 241 public boolean isShowException() { 242 return showException; 243 } 244 245 public void setShowException(boolean showException) { 246 this.showException = showException; 247 } 248 249 public boolean isShowRouteId() { 250 return showRouteId; 251 } 252 253 public void setShowRouteId(boolean showRouteId) { 254 this.showRouteId = showRouteId; 255 } 256 257 public boolean isMultiline() { 258 return multiline; 259 } 260 261 public void setMultiline(boolean multiline) { 262 this.multiline = multiline; 263 } 264 265 public int getBreadCrumbLength() { 266 return breadCrumbLength; 267 } 268 269 public void setBreadCrumbLength(int breadCrumbLength) { 270 this.breadCrumbLength = breadCrumbLength; 271 } 272 273 public boolean isShowShortExchangeId() { 274 return showShortExchangeId; 275 } 276 277 public void setShowShortExchangeId(boolean showShortExchangeId) { 278 this.showShortExchangeId = showShortExchangeId; 279 } 280 281 public int getNodeLength() { 282 return nodeLength; 283 } 284 285 public void setNodeLength(int nodeLength) { 286 this.nodeLength = nodeLength; 287 } 288 289 public int getMaxChars() { 290 return maxChars; 291 } 292 293 public void setMaxChars(int maxChars) { 294 this.maxChars = maxChars; 295 } 296 297 // Implementation methods 298 //------------------------------------------------------------------------- 299 300 protected String extractRoute(ProcessorDefinition<?> node) { 301 RouteDefinition route = ProcessorDefinitionHelper.getRoute(node); 302 if (route != null) { 303 return route.getId(); 304 } else { 305 return null; 306 } 307 } 308 309 protected Object getBreadCrumbID(Exchange exchange) { 310 return exchange.getExchangeId(); 311 } 312 313 protected String getNodeMessage(RouteNode entry, Exchange exchange) { 314 String message = entry.getLabel(exchange); 315 if (nodeLength > 0) { 316 return String.format("%1$-" + nodeLength + "." + nodeLength + "s", message); 317 } else { 318 return message; 319 } 320 } 321 322 /** 323 * Creates the breadcrumb based on whether this was a trace of 324 * an exchange coming out of or into a processing step. For example, 325 * <br/><tt>transform(body) -> ID-mojo/39713-1225468755256/2-0</tt> 326 * <br/>or 327 * <br/><tt>ID-mojo/39713-1225468755256/2-0 -> transform(body)</tt> 328 */ 329 protected String extractBreadCrumb(TraceInterceptor interceptor, ProcessorDefinition<?> currentNode, Exchange exchange) { 330 String id = ""; 331 String result; 332 333 if (!showBreadCrumb && !showExchangeId && !showShortExchangeId && !showNode) { 334 return ""; 335 } 336 337 // compute breadcrumb id 338 if (showBreadCrumb) { 339 id = getBreadCrumbID(exchange).toString(); 340 } else if (showExchangeId || showShortExchangeId) { 341 id = getBreadCrumbID(exchange).toString(); 342 if (showShortExchangeId) { 343 // only output last part of id 344 id = id.substring(id.lastIndexOf('-') + 1); 345 } 346 } 347 348 // compute from, to and route 349 String from = ""; 350 String to = ""; 351 String route = ""; 352 if (showNode || showRouteId) { 353 if (exchange.getUnitOfWork() != null) { 354 TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes(); 355 if (traced != null) { 356 RouteNode traceFrom = traced.getSecondLastNode(); 357 if (traceFrom != null) { 358 from = getNodeMessage(traceFrom, exchange); 359 } else if (exchange.getFromEndpoint() != null) { 360 from = "from(" + exchange.getFromEndpoint().getEndpointUri() + ")"; 361 } 362 363 RouteNode traceTo = traced.getLastNode(); 364 if (traceTo != null) { 365 to = getNodeMessage(traceTo, exchange); 366 // if its an abstract dummy holder then we have to get the 2nd last so we can get the real node that has 367 // information which route it belongs to 368 if (traceTo.isAbstract() && traceTo.getProcessorDefinition() == null) { 369 traceTo = traced.getSecondLastNode(); 370 } 371 if (traceTo != null) { 372 route = extractRoute(traceTo.getProcessorDefinition()); 373 } 374 } 375 } 376 } 377 } 378 379 // assemble result with and without the to/from 380 if (showNode) { 381 if (showRouteId && route != null) { 382 result = id.trim() + " >>> (" + route + ") " + from + " --> " + to.trim() + " <<< "; 383 } else { 384 result = id.trim() + " >>> " + from + " --> " + to.trim() + " <<< "; 385 } 386 387 if (interceptor.shouldTraceOutExchanges() && exchange.hasOut()) { 388 result += " (OUT) "; 389 } 390 } else { 391 result = id; 392 } 393 394 if (breadCrumbLength > 0) { 395 // we want to ensure text coming after this is aligned for readability 396 return String.format("%1$-" + breadCrumbLength + "." + breadCrumbLength + "s", result.trim()); 397 } else { 398 return result.trim(); 399 } 400 } 401 402}