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