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