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.NoTypeConversionAvailableException; 022 import org.apache.camel.converter.stream.StreamCache; 023 import org.apache.camel.model.ProcessorType; 024 import org.apache.camel.spi.UnitOfWork; 025 import org.apache.camel.util.ObjectHelper; 026 027 /** 028 * @version $Revision: 13240 $ 029 */ 030 public class TraceFormatter { 031 private int breadCrumbLength; 032 private int nodeLength; 033 private boolean showBreadCrumb = true; 034 private boolean showNode = true; 035 private boolean showExchangeId; 036 private boolean showShortExchangeId; 037 private boolean showExchangePattern = true; 038 private boolean showProperties = true; 039 private boolean showHeaders = true; 040 private boolean showBody = true; 041 private boolean showBodyType = true; 042 private boolean showOutBody; 043 private boolean showOutBodyType; 044 private boolean showException = true; 045 046 public Object format(TraceInterceptor interceptor, Exchange exchange) { 047 Message in = exchange.getIn(); 048 049 // false because we don't want to introduce side effects 050 Message out = exchange.getOut(false); 051 052 Throwable exception = exchange.getException(); 053 StringBuilder sb = new StringBuilder(); 054 sb.append(getExchangeAndNode(interceptor, exchange)); 055 056 if (showExchangePattern) { 057 sb.append(", Pattern:").append(exchange.getPattern()).append(" "); 058 } 059 // only show properties if we have any 060 if (showProperties && !exchange.getProperties().isEmpty()) { 061 sb.append(", Properties:").append(exchange.getProperties()).append(" "); 062 } 063 // only show headers if we have any 064 if (showHeaders && !in.getHeaders().isEmpty()) { 065 sb.append(", Headers:").append(in.getHeaders()).append(" "); 066 } 067 if (showBodyType) { 068 sb.append(", BodyType:").append(getBodyTypeAsString(in)).append(" "); 069 } 070 if (showBody) { 071 sb.append(", Body:").append(getBodyAsString(in)).append(" "); 072 } 073 if (showOutBodyType && out != null) { 074 sb.append(", OutBodyType:").append(getBodyTypeAsString(out)).append(" "); 075 } 076 if (showOutBody && out != null) { 077 sb.append(", OutBody:").append(getBodyAsString(out)).append(" "); 078 } 079 if (showException && exception != null) { 080 sb.append(", Exception:").append(exception); 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 isShowProperties() { 143 return showProperties; 144 } 145 146 public void setShowProperties(boolean showProperties) { 147 this.showProperties = showProperties; 148 } 149 150 public boolean isShowNode() { 151 return showNode; 152 } 153 154 public void setShowNode(boolean showNode) { 155 this.showNode = showNode; 156 } 157 158 public boolean isShowExchangePattern() { 159 return showExchangePattern; 160 } 161 162 public void setShowExchangePattern(boolean showExchangePattern) { 163 this.showExchangePattern = showExchangePattern; 164 } 165 166 public boolean isShowException() { 167 return showException; 168 } 169 170 public void setShowException(boolean showException) { 171 this.showException = showException; 172 } 173 174 public int getBreadCrumbLength() { 175 return breadCrumbLength; 176 } 177 178 public void setBreadCrumbLength(int breadCrumbLength) { 179 this.breadCrumbLength = breadCrumbLength; 180 } 181 182 public boolean isShowShortExchangeId() { 183 return showShortExchangeId; 184 } 185 186 public void setShowShortExchangeId(boolean showShortExchangeId) { 187 this.showShortExchangeId = showShortExchangeId; 188 } 189 190 public int getNodeLength() { 191 return nodeLength; 192 } 193 194 public void setNodeLength(int nodeLength) { 195 this.nodeLength = nodeLength; 196 } 197 198 // Implementation methods 199 //------------------------------------------------------------------------- 200 protected Object getBreadCrumbID(Exchange exchange) { 201 UnitOfWork unitOfWork = exchange.getUnitOfWork(); 202 if (unitOfWork != null) { 203 return unitOfWork.getId(); 204 } else { 205 return exchange.getExchangeId(); 206 } 207 } 208 209 protected Object getBodyAsString(Message in) { 210 if (in == null) { 211 return null; 212 } 213 214 StreamCache newBody = null; 215 try { 216 newBody = in.getBody(StreamCache.class); 217 if (newBody != null) { 218 in.setBody(newBody); 219 } 220 } catch (NoTypeConversionAvailableException ex) { 221 // ignore, in not of StreamCache type 222 } 223 224 Object answer = null; 225 try { 226 answer = in.getBody(String.class); 227 } catch (NoTypeConversionAvailableException ex) { 228 answer = in.getBody(); 229 } 230 231 if (newBody != null) { 232 // Reset the InputStreamCache 233 newBody.reset(); 234 } 235 return answer; 236 } 237 238 protected Object getBodyTypeAsString(Message message) { 239 if (message == null) { 240 return null; 241 } 242 String answer = ObjectHelper.classCanonicalName(message.getBody()); 243 if (answer != null && answer.startsWith("java.lang.")) { 244 return answer.substring(10); 245 } 246 return answer; 247 } 248 249 protected String getNodeMessage(TraceInterceptor interceptor) { 250 String message = interceptor.getNode().getShortName() + "(" + interceptor.getNode().getLabel() + ")"; 251 if (nodeLength > 0) { 252 return String.format("%1$-" + nodeLength + "." + nodeLength + "s", message); 253 } else { 254 return message; 255 } 256 } 257 258 /** 259 * Returns the exchange id and node, ordered based on whether this was a trace of 260 * an exchange coming out of or into a processing step. For example, 261 * <br/><tt>transform(body) -> ID-mojo/39713-1225468755256/2-0</tt> 262 * <br/>or 263 * <br/><tt>ID-mojo/39713-1225468755256/2-0 -> transform(body)</tt> 264 */ 265 protected String getExchangeAndNode(TraceInterceptor interceptor, Exchange exchange) { 266 String id = ""; 267 String node = ""; 268 String result; 269 270 if (!showBreadCrumb && !showExchangeId && !showShortExchangeId && !showNode) { 271 return ""; 272 } 273 274 if (showBreadCrumb) { 275 id = getBreadCrumbID(exchange).toString(); 276 } else if (showExchangeId || showShortExchangeId) { 277 id = getBreadCrumbID(exchange).toString(); 278 if (showShortExchangeId) { 279 // skip hostname for short exchange id 280 id = id.substring(id.indexOf("/") + 1); 281 } 282 } 283 284 if (showNode) { 285 node = getNodeMessage(interceptor); 286 } 287 288 if (interceptor.shouldTraceOutExchanges() && exchange.getOut(false) != null) { 289 result = node.trim() + " -> " + id.trim(); 290 } else { 291 result = id.trim() + " -> " + node.trim(); 292 } 293 294 if (breadCrumbLength > 0) { 295 // we want to ensure text coming after this is aligned for readability 296 return String.format("%1$-" + breadCrumbLength + "." + breadCrumbLength + "s", result).trim(); 297 } else { 298 return result.trim(); 299 } 300 301 } 302 }