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.processor.interceptor; 018 019 import org.apache.camel.Exchange; 020 import org.apache.camel.Message; 021 import org.apache.camel.Processor; 022 import org.apache.camel.RouteNode; 023 import org.apache.camel.model.ProcessorDefinition; 024 import org.apache.camel.processor.Traceable; 025 import org.apache.camel.spi.TraceableUnitOfWork; 026 import org.apache.camel.spi.UnitOfWork; 027 import org.apache.camel.util.MessageHelper; 028 029 /** 030 * @version $Revision: 795369 $ 031 */ 032 public class DefaultTraceFormatter implements TraceFormatter { 033 private int breadCrumbLength; 034 private int nodeLength; 035 private boolean showBreadCrumb = true; 036 private boolean showNode = true; 037 private boolean showExchangeId; 038 private boolean showShortExchangeId; 039 private boolean showExchangePattern = true; 040 private boolean showProperties; 041 private boolean showHeaders = true; 042 private boolean showBody = true; 043 private boolean showBodyType = true; 044 private boolean showOutHeaders; 045 private boolean showOutBody; 046 private boolean showOutBodyType; 047 private boolean showException = true; 048 private int maxChars; 049 050 public Object format(final TraceInterceptor interceptor, final ProcessorDefinition node, final Exchange exchange) { 051 Message in = exchange.getIn(); 052 Message out = null; 053 if (exchange.hasOut()) { 054 out = exchange.getOut(); 055 } 056 057 StringBuilder sb = new StringBuilder(); 058 sb.append(extractBreadCrumb(interceptor, node, exchange)); 059 060 if (showExchangePattern) { 061 sb.append(", Pattern:").append(exchange.getPattern()); 062 } 063 // only show properties if we have any 064 if (showProperties && !exchange.getProperties().isEmpty()) { 065 sb.append(", Properties:").append(exchange.getProperties()); 066 } 067 // only show headers if we have any 068 if (showHeaders && !in.getHeaders().isEmpty()) { 069 sb.append(", Headers:").append(in.getHeaders()); 070 } 071 if (showBodyType) { 072 sb.append(", BodyType:").append(MessageHelper.getBodyTypeName(in)); 073 } 074 if (showBody) { 075 sb.append(", Body:").append(MessageHelper.extractBodyAsString(in)); 076 } 077 if (showOutHeaders && out != null) { 078 sb.append(", OutHeaders:").append(out.getHeaders()); 079 } 080 if (showOutBodyType && out != null) { 081 sb.append(", OutBodyType:").append(MessageHelper.getBodyTypeName(out)); 082 } 083 if (showOutBody && out != null) { 084 sb.append(", OutBody:").append(MessageHelper.extractBodyAsString(out)); 085 } 086 if (showException && exchange.getException() != null) { 087 sb.append(", Exception:").append(exchange.getException()); 088 } 089 090 if (maxChars > 0) { 091 String s = sb.toString(); 092 if (s.length() > maxChars) { 093 s = s.substring(0, maxChars) + "..."; 094 } 095 return s; 096 } else { 097 return sb.toString(); 098 } 099 } 100 101 public boolean isShowBody() { 102 return showBody; 103 } 104 105 public void setShowBody(boolean showBody) { 106 this.showBody = showBody; 107 } 108 109 public boolean isShowBodyType() { 110 return showBodyType; 111 } 112 113 public void setShowBodyType(boolean showBodyType) { 114 this.showBodyType = showBodyType; 115 } 116 117 public void setShowOutBody(boolean showOutBody) { 118 this.showOutBody = showOutBody; 119 } 120 121 public boolean isShowOutBody() { 122 return showOutBody; 123 } 124 125 public void setShowOutBodyType(boolean showOutBodyType) { 126 this.showOutBodyType = showOutBodyType; 127 } 128 129 public boolean isShowOutBodyType() { 130 return showOutBodyType; 131 } 132 133 public boolean isShowBreadCrumb() { 134 return showBreadCrumb; 135 } 136 137 public void setShowBreadCrumb(boolean showBreadCrumb) { 138 this.showBreadCrumb = showBreadCrumb; 139 } 140 141 public boolean isShowExchangeId() { 142 return showExchangeId; 143 } 144 145 public void setShowExchangeId(boolean showExchangeId) { 146 this.showExchangeId = showExchangeId; 147 } 148 149 public boolean isShowHeaders() { 150 return showHeaders; 151 } 152 153 public void setShowHeaders(boolean showHeaders) { 154 this.showHeaders = showHeaders; 155 } 156 157 public boolean isShowOutHeaders() { 158 return showOutHeaders; 159 } 160 161 public void setShowOutHeaders(boolean showOutHeaders) { 162 this.showOutHeaders = showOutHeaders; 163 } 164 165 public boolean isShowProperties() { 166 return showProperties; 167 } 168 169 public void setShowProperties(boolean showProperties) { 170 this.showProperties = showProperties; 171 } 172 173 public boolean isShowNode() { 174 return showNode; 175 } 176 177 public void setShowNode(boolean showNode) { 178 this.showNode = showNode; 179 } 180 181 public boolean isShowExchangePattern() { 182 return showExchangePattern; 183 } 184 185 public void setShowExchangePattern(boolean showExchangePattern) { 186 this.showExchangePattern = showExchangePattern; 187 } 188 189 public boolean isShowException() { 190 return showException; 191 } 192 193 public void setShowException(boolean showException) { 194 this.showException = showException; 195 } 196 197 public int getBreadCrumbLength() { 198 return breadCrumbLength; 199 } 200 201 public void setBreadCrumbLength(int breadCrumbLength) { 202 this.breadCrumbLength = breadCrumbLength; 203 } 204 205 public boolean isShowShortExchangeId() { 206 return showShortExchangeId; 207 } 208 209 public void setShowShortExchangeId(boolean showShortExchangeId) { 210 this.showShortExchangeId = showShortExchangeId; 211 } 212 213 public int getNodeLength() { 214 return nodeLength; 215 } 216 217 public void setNodeLength(int nodeLength) { 218 this.nodeLength = nodeLength; 219 } 220 221 public int getMaxChars() { 222 return maxChars; 223 } 224 225 public void setMaxChars(int maxChars) { 226 this.maxChars = maxChars; 227 } 228 229 // Implementation methods 230 //------------------------------------------------------------------------- 231 protected Object getBreadCrumbID(Exchange exchange) { 232 return exchange.getExchangeId(); 233 } 234 235 protected String getNodeMessage(RouteNode entry, Exchange exchange) { 236 String message = entry.getLabel(exchange); 237 if (nodeLength > 0) { 238 return String.format("%1$-" + nodeLength + "." + nodeLength + "s", message); 239 } else { 240 return message; 241 } 242 } 243 244 /** 245 * Creates the breadcrumb based on whether this was a trace of 246 * an exchange coming out of or into a processing step. For example, 247 * <br/><tt>transform(body) -> ID-mojo/39713-1225468755256/2-0</tt> 248 * <br/>or 249 * <br/><tt>ID-mojo/39713-1225468755256/2-0 -> transform(body)</tt> 250 */ 251 protected String extractBreadCrumb(TraceInterceptor interceptor, ProcessorDefinition currentNode, Exchange exchange) { 252 String id = ""; 253 String result; 254 255 if (!showBreadCrumb && !showExchangeId && !showShortExchangeId && !showNode) { 256 return ""; 257 } 258 259 // compute breadcrumb id 260 if (showBreadCrumb) { 261 id = getBreadCrumbID(exchange).toString(); 262 } else if (showExchangeId || showShortExchangeId) { 263 id = getBreadCrumbID(exchange).toString(); 264 if (showShortExchangeId) { 265 // skip hostname for short exchange id 266 id = id.substring(id.indexOf('/') + 1); 267 } 268 } 269 270 // compute from and to 271 String from = ""; 272 String to = ""; 273 if (showNode && exchange.getUnitOfWork() instanceof TraceableUnitOfWork) { 274 TraceableUnitOfWork tuow = (TraceableUnitOfWork) exchange.getUnitOfWork(); 275 276 RouteNode traceFrom = tuow.getSecondLastNode(); 277 if (traceFrom != null) { 278 from = getNodeMessage(traceFrom, exchange); 279 } else if (exchange.getFromEndpoint() != null) { 280 from = "from(" + exchange.getFromEndpoint().getEndpointUri() + ")"; 281 } 282 283 RouteNode traceTo = tuow.getLastNode(); 284 if (traceTo != null) { 285 to = getNodeMessage(traceTo, exchange); 286 } 287 } 288 289 // assemble result with and without the to/from 290 if (showNode) { 291 result = id.trim() + " >>> " + from + " --> " + to.trim(); 292 if (interceptor.shouldTraceOutExchanges() && exchange.hasOut()) { 293 result += " (OUT) "; 294 } 295 } else { 296 result = id; 297 } 298 299 if (breadCrumbLength > 0) { 300 // we want to ensure text coming after this is aligned for readability 301 return String.format("%1$-" + breadCrumbLength + "." + breadCrumbLength + "s", result.trim()); 302 } else { 303 return result.trim(); 304 } 305 } 306 307 }