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: 2230 $ 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 return unitOfWork.getId(); 203 } 204 205 protected Object getBodyAsString(Message in) { 206 if (in == null) { 207 return null; 208 } 209 210 StreamCache newBody = null; 211 try { 212 newBody = in.getBody(StreamCache.class); 213 if (newBody != null) { 214 in.setBody(newBody); 215 } 216 } catch (NoTypeConversionAvailableException ex) { 217 // ignore, in not of StreamCache type 218 } 219 220 Object answer = null; 221 try { 222 answer = in.getBody(String.class); 223 } catch (NoTypeConversionAvailableException ex) { 224 answer = in.getBody(); 225 } 226 227 if (newBody != null) { 228 // Reset the InputStreamCache 229 newBody.reset(); 230 } 231 return answer; 232 } 233 234 protected Object getBodyTypeAsString(Message message) { 235 if (message == null) { 236 return null; 237 } 238 String answer = ObjectHelper.classCanonicalName(message.getBody()); 239 if (answer != null && answer.startsWith("java.lang.")) { 240 return answer.substring(10); 241 } 242 return answer; 243 } 244 245 protected String getNodeMessage(TraceInterceptor interceptor) { 246 String message = interceptor.getNode().getShortName() + "(" + interceptor.getNode().getLabel() + ")"; 247 if (nodeLength > 0) { 248 return String.format("%1$-" + nodeLength + "." + nodeLength + "s", message); 249 } else { 250 return message; 251 } 252 } 253 254 /** 255 * Returns the exchange id and node, ordered based on whether this was a trace of 256 * an exchange coming out of or into a processing step. For example, 257 * <br/><tt>transform(body) -> ID-mojo/39713-1225468755256/2-0</tt> 258 * <br/>or 259 * <br/><tt>ID-mojo/39713-1225468755256/2-0 -> transform(body)</tt> 260 */ 261 protected String getExchangeAndNode(TraceInterceptor interceptor, Exchange exchange) { 262 String id = ""; 263 String node = ""; 264 String result; 265 266 if (!showBreadCrumb && !showExchangeId && !showShortExchangeId && !showNode) { 267 return ""; 268 } 269 270 if (showBreadCrumb) { 271 id = getBreadCrumbID(exchange).toString(); 272 } else if (showExchangeId || showShortExchangeId) { 273 id = getBreadCrumbID(exchange).toString(); 274 if (showShortExchangeId) { 275 // skip hostname for short exchange id 276 id = id.substring(id.indexOf("/") + 1); 277 } 278 } 279 280 if (showNode) { 281 node = getNodeMessage(interceptor); 282 } 283 284 if (interceptor.shouldTraceOutExchanges() && exchange.getOut(false) != null) { 285 result = node.trim() + " -> " + id.trim(); 286 } else { 287 result = id.trim() + " -> " + node.trim(); 288 } 289 290 if (breadCrumbLength > 0) { 291 // we want to ensure text coming after this is aligned for readability 292 return String.format("%1$-" + breadCrumbLength + "." + breadCrumbLength + "s", result).trim(); 293 } else { 294 return result.trim(); 295 } 296 297 } 298 }