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 }