use of org.apache.camel.spi.TracedRouteNodes in project camel by apache.
the class MulticastProcessor method doProcessParallel.
private void doProcessParallel(final ProcessorExchangePair pair) throws Exception {
final Exchange exchange = pair.getExchange();
Processor processor = pair.getProcessor();
Producer producer = pair.getProducer();
TracedRouteNodes traced = exchange.getUnitOfWork() != null ? exchange.getUnitOfWork().getTracedRouteNodes() : null;
// compute time taken if sending to another endpoint
StopWatch watch = null;
if (producer != null) {
watch = new StopWatch();
}
try {
// prepare tracing starting from a new block
if (traced != null) {
traced.pushBlock();
}
if (producer != null) {
EventHelper.notifyExchangeSending(exchange.getContext(), exchange, producer.getEndpoint());
}
// let the prepared process it, remember to begin the exchange pair
AsyncProcessor async = AsyncProcessorConverterHelper.convert(processor);
pair.begin();
// we invoke it synchronously as parallel async routing is too hard
AsyncProcessorHelper.process(async, exchange);
} finally {
pair.done();
// pop the block so by next round we have the same staring point and thus the tracing looks accurate
if (traced != null) {
traced.popBlock();
}
if (producer != null) {
long timeTaken = watch.stop();
Endpoint endpoint = producer.getEndpoint();
// emit event that the exchange was sent to the endpoint
// this is okay to do here in the finally block, as the processing is not using the async routing engine
//( we invoke it synchronously as parallel async routing is too hard)
EventHelper.notifyExchangeSent(exchange.getContext(), exchange, endpoint, timeTaken);
}
}
}
use of org.apache.camel.spi.TracedRouteNodes in project camel by apache.
the class DefaultTraceFormatter method extractBreadCrumb.
/**
* Creates the breadcrumb based on whether this was a trace of
* an exchange coming out of or into a processing step. For example,
* <br/><tt>transform(body) -> ID-mojo/39713-1225468755256/2-0</tt>
* <br/>or
* <br/><tt>ID-mojo/39713-1225468755256/2-0 -> transform(body)</tt>
*/
protected String extractBreadCrumb(TraceInterceptor interceptor, ProcessorDefinition<?> currentNode, Exchange exchange) {
String id = "";
String result;
if (!showBreadCrumb && !showExchangeId && !showShortExchangeId && !showNode) {
return "";
}
// compute breadcrumb id
if (showBreadCrumb) {
id = getBreadCrumbID(exchange).toString();
} else if (showExchangeId || showShortExchangeId) {
id = getBreadCrumbID(exchange).toString();
if (showShortExchangeId) {
// only output last part of id
id = id.substring(id.lastIndexOf('-') + 1);
}
}
// compute from, to and route
String from = "";
String to = "";
String route = "";
if (showNode || showRouteId) {
if (exchange.getUnitOfWork() != null) {
TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
RouteNode traceFrom = traced.getSecondLastNode();
if (traceFrom != null) {
from = getNodeMessage(traceFrom, exchange);
} else if (exchange.getFromEndpoint() != null) {
from = "from(" + exchange.getFromEndpoint().getEndpointUri() + ")";
}
RouteNode traceTo = traced.getLastNode();
if (traceTo != null) {
to = getNodeMessage(traceTo, exchange);
// information which route it belongs to
if (traceTo.isAbstract() && traceTo.getProcessorDefinition() == null) {
traceTo = traced.getSecondLastNode();
}
if (traceTo != null) {
route = extractRoute(traceTo.getProcessorDefinition());
}
}
}
}
// assemble result with and without the to/from
if (showNode) {
if (showRouteId && route != null) {
result = id.trim() + " >>> (" + route + ") " + from + " --> " + to.trim() + " <<< ";
} else {
result = id.trim() + " >>> " + from + " --> " + to.trim() + " <<< ";
}
if (interceptor.shouldTraceOutExchanges() && exchange.hasOut()) {
result += " (OUT) ";
}
} else {
result = id;
}
if (breadCrumbLength > 0) {
// we want to ensure text coming after this is aligned for readability
return String.format("%1$-" + breadCrumbLength + "." + breadCrumbLength + "s", result.trim());
} else {
return result.trim();
}
}
use of org.apache.camel.spi.TracedRouteNodes in project camel by apache.
the class MulticastProcessor method doProcessSequential.
private boolean doProcessSequential(final Exchange original, final AtomicExchange result, final Iterable<ProcessorExchangePair> pairs, final Iterator<ProcessorExchangePair> it, final ProcessorExchangePair pair, final AsyncCallback callback, final AtomicInteger total) {
boolean sync = true;
final Exchange exchange = pair.getExchange();
Processor processor = pair.getProcessor();
final Producer producer = pair.getProducer();
TracedRouteNodes traced = exchange.getUnitOfWork() != null ? exchange.getUnitOfWork().getTracedRouteNodes() : null;
// compute time taken if sending to another endpoint
final StopWatch watch = producer != null ? new StopWatch() : null;
try {
// prepare tracing starting from a new block
if (traced != null) {
traced.pushBlock();
}
if (producer != null) {
EventHelper.notifyExchangeSending(exchange.getContext(), exchange, producer.getEndpoint());
}
// let the prepared process it, remember to begin the exchange pair
AsyncProcessor async = AsyncProcessorConverterHelper.convert(processor);
pair.begin();
sync = async.process(exchange, new AsyncCallback() {
public void done(boolean doneSync) {
// we are done with the exchange pair
pair.done();
// okay we are done, so notify the exchange was sent
if (producer != null) {
long timeTaken = watch.stop();
Endpoint endpoint = producer.getEndpoint();
// emit event that the exchange was sent to the endpoint
EventHelper.notifyExchangeSent(exchange.getContext(), exchange, endpoint, timeTaken);
}
// we only have to handle async completion of the routing slip
if (doneSync) {
return;
}
// continue processing the multicast asynchronously
Exchange subExchange = exchange;
// Decide whether to continue with the multicast or not; similar logic to the Pipeline
// remember to test for stop on exception and aggregate before copying back results
boolean continueProcessing = PipelineHelper.continueProcessing(subExchange, "Sequential processing failed for number " + total.get(), LOG);
if (stopOnException && !continueProcessing) {
if (subExchange.getException() != null) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, subExchange.getException()));
} else {
// we want to stop on exception, and the exception was handled by the error handler
// this is similar to what the pipeline does, so we should do the same to not surprise end users
// so we should set the failed exchange as the result and be done
result.set(subExchange);
}
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
try {
if (parallelAggregate) {
doAggregateInternal(getAggregationStrategy(subExchange), result, subExchange);
} else {
doAggregate(getAggregationStrategy(subExchange), result, subExchange);
}
} catch (Throwable e) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, e));
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
total.incrementAndGet();
// maybe there are more processors to multicast
while (it.hasNext()) {
// prepare and run the next
ProcessorExchangePair pair = it.next();
subExchange = pair.getExchange();
updateNewExchange(subExchange, total.get(), pairs, it);
boolean sync = doProcessSequential(original, result, pairs, it, pair, callback, total);
if (!sync) {
LOG.trace("Processing exchangeId: {} is continued being processed asynchronously", original.getExchangeId());
return;
}
// Decide whether to continue with the multicast or not; similar logic to the Pipeline
// remember to test for stop on exception and aggregate before copying back results
continueProcessing = PipelineHelper.continueProcessing(subExchange, "Sequential processing failed for number " + total.get(), LOG);
if (stopOnException && !continueProcessing) {
if (subExchange.getException() != null) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, subExchange.getException()));
} else {
// we want to stop on exception, and the exception was handled by the error handler
// this is similar to what the pipeline does, so we should do the same to not surprise end users
// so we should set the failed exchange as the result and be done
result.set(subExchange);
}
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
// must catch any exceptions from aggregation
try {
if (parallelAggregate) {
doAggregateInternal(getAggregationStrategy(subExchange), result, subExchange);
} else {
doAggregate(getAggregationStrategy(subExchange), result, subExchange);
}
} catch (Throwable e) {
// wrap in exception to explain where it failed
subExchange.setException(new CamelExchangeException("Sequential processing failed for number " + total, subExchange, e));
// and do the done work
doDone(original, subExchange, pairs, callback, false, true);
return;
}
total.incrementAndGet();
}
// do the done work
subExchange = result.get() != null ? result.get() : null;
doDone(original, subExchange, pairs, callback, false, true);
}
});
} finally {
// pop the block so by next round we have the same staring point and thus the tracing looks accurate
if (traced != null) {
traced.popBlock();
}
}
return sync;
}
use of org.apache.camel.spi.TracedRouteNodes in project camel by apache.
the class TraceInterceptor method process.
@Override
public boolean process(final Exchange exchange, final AsyncCallback callback) {
// do not trace if tracing is disabled
if (!tracer.isEnabled() || (routeContext != null && !routeContext.isTracing())) {
return processor.process(exchange, callback);
}
// logging TraceEvents to avoid infinite looping
if (exchange.getProperty(Exchange.TRACE_EVENT, false, Boolean.class)) {
// but we must still process to allow routing of TraceEvents to eg a JPA endpoint
return processor.process(exchange, callback);
}
final boolean shouldLog = shouldLogNode(node) && shouldLogExchange(exchange);
// whether we should trace it or not, some nodes should be skipped as they are abstract
// intermediate steps for instance related to on completion
boolean trace = true;
boolean sync = true;
// okay this is a regular exchange being routed we might need to log and trace
try {
// before
if (shouldLog) {
// traced holds the information about the current traced route path
if (exchange.getUnitOfWork() != null) {
TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
if (node instanceof OnCompletionDefinition || node instanceof OnExceptionDefinition) {
// skip any of these as its just a marker definition
trace = false;
} else if (ProcessorDefinitionHelper.isFirstChildOfType(OnCompletionDefinition.class, node)) {
// special for on completion tracing
traceOnCompletion(traced, exchange);
} else if (ProcessorDefinitionHelper.isFirstChildOfType(OnExceptionDefinition.class, node)) {
// special for on exception
traceOnException(traced, exchange);
} else if (ProcessorDefinitionHelper.isFirstChildOfType(CatchDefinition.class, node)) {
// special for do catch
traceDoCatch(traced, exchange);
} else if (ProcessorDefinitionHelper.isFirstChildOfType(FinallyDefinition.class, node)) {
// special for do finally
traceDoFinally(traced, exchange);
} else if (ProcessorDefinitionHelper.isFirstChildOfType(AggregateDefinition.class, node)) {
// special for aggregate
traceAggregate(traced, exchange);
} else {
// regular so just add it
traced.addTraced(new DefaultRouteNode(node, super.getProcessor()));
}
} else {
LOG.trace("Cannot trace as this Exchange does not have an UnitOfWork: {}", exchange);
}
}
// log and trace the processor
Object state = null;
if (shouldLog && trace) {
logExchange(exchange);
// either call the in or generic trace method depending on OUT has been enabled or not
if (tracer.isTraceOutExchanges()) {
state = traceExchangeIn(exchange);
} else {
traceExchange(exchange);
}
}
final Object traceState = state;
// special for interceptor where we need to keep booking how far we have routed in the intercepted processors
if (node.getParent() instanceof InterceptDefinition && exchange.getUnitOfWork() != null) {
TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
traceIntercept((InterceptDefinition) node.getParent(), traced, exchange);
}
// process the exchange
sync = processor.process(exchange, new AsyncCallback() {
@Override
public void done(boolean doneSync) {
try {
// after (trace out)
if (shouldLog && tracer.isTraceOutExchanges()) {
logExchange(exchange);
traceExchangeOut(exchange, traceState);
}
} catch (Throwable e) {
// some exception occurred in trace logic
if (shouldLogException(exchange)) {
logException(exchange, e);
}
exchange.setException(e);
} finally {
// ensure callback is always invoked
callback.done(doneSync);
}
}
});
} catch (Throwable e) {
// some exception occurred in trace logic
if (shouldLogException(exchange)) {
logException(exchange, e);
}
exchange.setException(e);
}
return sync;
}
use of org.apache.camel.spi.TracedRouteNodes in project camel by apache.
the class DefaultTraceEventMessage method extractFromNode.
private static String extractFromNode(Exchange exchange) {
if (exchange.getUnitOfWork() != null) {
TracedRouteNodes traced = exchange.getUnitOfWork().getTracedRouteNodes();
RouteNode last = traced.getSecondLastNode();
return last != null ? last.getLabel(exchange) : null;
}
return null;
}
Aggregations