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.Predicate;
021    import org.apache.camel.Processor;
022    import org.apache.camel.model.ProcessorType;
023    import org.apache.camel.processor.DelegateProcessor;
024    import org.apache.camel.processor.Logger;
025    import org.apache.camel.processor.LoggingLevel;
026    import org.apache.commons.logging.Log;
027    import org.apache.commons.logging.LogFactory;
028    
029    /**
030     * An interceptor for debugging and tracing routes
031     *
032     * @version $Revision: 45325 $
033     */
034    public class TraceInterceptor extends DelegateProcessor implements ExchangeFormatter {
035        private final ProcessorType node;
036        private Predicate<Exchange> traceFilter;
037        private boolean traceExceptions = true;
038        private Logger logger = new Logger(LogFactory.getLog(TraceInterceptor.class), this);
039        private TraceFormatter formatter;
040        private Tracer tracer;
041    
042        public TraceInterceptor(ProcessorType node, Processor target, TraceFormatter formatter, Tracer tracer) {
043            super(target);
044            this.tracer = tracer;
045            this.node = node;
046            this.formatter = formatter;
047        }
048    
049        public TraceInterceptor(ProcessorType node, Processor target, TraceFormatter formatter) {
050            this(node, target, formatter, null);
051        }
052    
053        public TraceInterceptor(ProcessorType node, Processor target, Tracer tracer) {
054            this(node, target, null, tracer);
055        }
056    
057        @Override
058        public String toString() {
059            return "TraceInterceptor[" + node + "]";
060        }
061    
062        public void process(Exchange exchange) throws Exception {
063            try {
064                if (shouldLogExchange(exchange)) {
065                    logExchange(exchange);
066                }
067                super.proceed(exchange);
068            } catch (Exception e) {
069                logException(exchange, e);
070                throw e;
071            } catch (Error e) {
072                logException(exchange, e);
073                throw e;
074            }
075        }
076    
077        public Object format(Exchange exchange) {
078            TraceFormatter traceFormatter = null;
079            if (formatter != null) {
080                traceFormatter = formatter;
081            } else {
082                assert tracer != null;
083                traceFormatter = tracer.getFormatter();
084            }
085            return traceFormatter.format(this, exchange);
086        }
087    
088        // Properties
089        //-------------------------------------------------------------------------
090        public ProcessorType getNode() {
091            return node;
092        }
093    
094        public Predicate getTraceFilter() {
095            return traceFilter;
096        }
097    
098        public void setTraceFilter(Predicate traceFilter) {
099            this.traceFilter = traceFilter;
100        }
101    
102        public boolean isTraceExceptions() {
103            return traceExceptions;
104        }
105    
106        public void setTraceExceptions(boolean traceExceptions) {
107            this.traceExceptions = traceExceptions;
108        }
109    
110        public Logger getLogger() {
111            return logger;
112        }
113    
114        public TraceFormatter getFormatter() {
115            return formatter;
116        }
117    
118        public void setFormatter(TraceFormatter formatter) {
119            this.formatter = formatter;
120        }
121    
122        public LoggingLevel getLevel() {
123            return getLogger().getLevel();
124        }
125    
126        public Log getLog() {
127            return getLogger().getLog();
128        }
129    
130        public void setLog(Log log) {
131            getLogger().setLog(log);
132        }
133    
134        public void setLevel(LoggingLevel level) {
135            getLogger().setLevel(level);
136        }
137    
138        // Implementation methods
139        //-------------------------------------------------------------------------
140        protected void logExchange(Exchange exchange) {
141            logger.process(exchange);
142        }
143    
144        protected void logException(Exchange exchange, Throwable throwable) {
145            logger.process(exchange, throwable);
146        }
147    
148    
149        /**
150         * Returns true if the given exchange should be logged in the trace list
151         */
152        protected boolean shouldLogExchange(Exchange exchange) {
153            return (tracer == null || tracer.isEnabled())
154                && (traceFilter == null || traceFilter.matches(exchange));
155        }
156    
157    }