Smile CDR provides comprehensive transaction logging capabilities for Apache Camel routes. Transaction logging automatically captures the execution flow, timing, and outcomes of route processing steps.
By default, Smile CDR automatically creates transaction logs for all Camel routes when transaction logging is globally enabled. This automatic logging captures:
CAMEL_EXCHANGE
step typeTransaction log and log steps are accumulated during route execution in a CamelExchangeRequestDetails
object which is stored in the exchange-request
Camel Exchange Property. After a route is terminated (either successfully or from an Exception) the transaction log steps inside the CamelExchangeRequestDetails
are automatically persisted.
The Camel module provides a global configuration option enable_transaction_log_on_all_routes
(default: true
) that controls whether transaction logging is enabled for all routes by default:
true
(default): All routes automatically create transaction logs without requiring explicit smile:camel/txLogStart
processorsfalse
: Transaction logging must be explicitly enabled for individual routes using the smile:camel/txLogStart
processorTransaction logging can be disabled for individual routes by adding a route property:
<route>
<routeProperty key="disableTransactionLog" value="true"/>
<from uri="direct:my-route" />
<!-- Transaction logging will be disabled for this entire route -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirProcessor" />
</route>
This route-level setting overrides the global enable_transaction_log_on_all_routes
configuration for that specific route.
IMPORTANT EDGE CASE: If you have enabled a broker transaction log on your server and you have created a Camel route that consumes from that broker topic, and enable_transaction_log_on_all_routes
is enabled, then it is critical to disable transaction logging on that route to avoid an infinite loop!
For custom transaction logging control, you have several options:
smile:camel/txLogStart
processor to manually start transaction logging (useful when global setting is disabled) 2. Add Steps: Use smile:camel/txLogAddStep
processor to add custom transaction log steps 3. Custom Processors: Autowire an ICamelProcessorTxLogHelper
bean to programmatically add transaction log stepsHl7V2 intermediate route processors will add log steps if the intermediate_logging_enabled property is set to true
.
smile:camel/txLogStart
Note: When the global configuration enable_transaction_log_on_all_routes
is set to true
(the default), this processor is not required as transaction logging is automatically enabled for all routes. In this case, using this processor will generate a warning log message.
This processor is primarily useful when:
enable_transaction_log_on_all_routes
is set to false
smile:camel/txLogAddStep
Logging Parameter | Used In | Function | Default Value |
---|---|---|---|
txLogStep | Smile processors | (false value) disable automatic logging for processor | true |
showMsgBody | Smile processors | (false value) avoid adding message body to log step | true |
rawMsg | Smile Hl7V2 processors | (false value) disable raw input message body to log step | true |
loggerUri | All processors | Used to override the processor uri identifier in the transaction log steps[^1] | NONE |
[^1]: If your route has more than one processor with the same URI, (which could be the case when using multiple smile:camel/txLogAddStep
processors), the automatic detection of the previous processor label could fail, which would result in a logging step with an empty URI. To avoid transaction log steps with empty URIs, the desired logging step URI can be specified using this parameter.
The following route produces one transaction log with six associated log steps as commented:
<route>
<from uri="direct:start" />
<!-- following processor doesn't log because no tx log initiated -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertScriptProcessor" />
<!-- initiate tx logging -->
<to uri="smile:camel/txLogStart" />
<!-- log step with raw input msg (step 0) + step for processed msg (step 1) -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertMapperBeanProcessor" />
<to uri="bean:customBeanProcessor1" />
<!-- tx log requested for previous step not including msg body (step 2) -->
<to uri="smile:camel/txLogAddStep?showMsgBody=false" />
<!-- automatic tx log (step 3) -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPreConvertInterceptorProcessor?txLogStep=false" />
<!-- "automatic" tx log, no body (step 4) -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirProcessor" />
<!-- custom processor with no tx log step requested -->
<to uri="bean:customBeanProcessor2" />
<!-- "automatic" tx log, no body (step 5) -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPostConvertScriptProcessor?showMsgBody=false" />
<!-- "automatic" tx log show body (step 6) -->
<to uri="smile:endpoint_hl7v2_in/hl7v2ToFhirPostConvertInterceptorProcessor" />
<to uri="mock:result" />
</route>
The following custom Camel processor adds an eagerly generated transaction log step if a transaction log was created earlier within the route:
/**
* Custom processor showing transaction log step addition
*/
public class SampleCustomProcessorAddingTxLogSteps implements Processor {
@Autowired
private ICamelProcessorTxLogHelper myTransactionLogHelper;
@Override
public void process(Exchange exchange) throws Exception {
// if transaction log was already started, adds provided step to it, otherwise do nothing
// steps are eagerly generated
myTransactionLogHelper.addStepsIfTxLogActive(exchange, buildTxLogSteps(exchange));
}
public List<TransactionLogStepJson> buildTxLogSteps(Exchange theExchange) {
TransactionLogStepJson step = new TransactionLogStepJson();
step.setInitialTimestamp(new Date());
step.setType(TransactionLogStepTypeEnum.PROCESSING);
step.setOutcome(TransactionLogOutcomeEnum.SUCCESS);
step.setBody(theExchange.getMessage().getBody(String.class));
step.setBodyType(TransactionLogBodyTypeEnum.JSON);
// a string you provide to identify your processor in the transaction log step
step.setRequestUrl(this.getClass().getSimpleName());
return List.of(step);
}
}
The following custom Camel processor adds a lazily generated transaction log step if a transaction log was created earlier within the route:
/**
* Custom processor showing lazily generated transaction log step addition
*/
public class SampleCustomProcessorAddingTxLogStepsLazily implements Processor, ITxLogStepsProvider {
@Autowired
private ICamelProcessorTxLogHelper myTransactionLogHelper;
@Override
public void process(Exchange exchange) throws Exception {
// if transaction log was already started, adds provided step to it, otherwise do nothing
myTransactionLogHelper.addStepsIfTxLogActive(exchange, this);
}
// this method is invoked lazily. Useful when steps generation involve heavy process
@Override
public List<TransactionLogStepJson> provideTxLogSteps(Exchange theExchange) {
TransactionLogStepJson step = new TransactionLogStepJson();
step.setInitialTimestamp(new Date());
step.setType(TransactionLogStepTypeEnum.PROCESSING);
step.setOutcome(TransactionLogOutcomeEnum.SUCCESS);
step.setBody(theExchange.getMessage().getBody(String.class));
step.setBodyType(TransactionLogBodyTypeEnum.JSON);
// a string you provide to identify your processor in the transaction log step
step.setRequestUrl(this.getClass().getSimpleName());
return List.of(step);
}
}
Smile currently supports the following module-specific transaction log helpers:
IHl7V2CamelProcessorTxLogHelper
(for logging Hl7v2ToFhirConversionResultJson
)ICdaCamelProcessorTxLogHelper
(for logging ICdaCamelConversionResultJson
)Module-specific transaction log helpers must be autowired using their respective types:
@Autowired
private IHl7V2CamelProcessorTxLogHelper myHl7V2CamelProcessorTxLogHelper;
@Autowired
private ICdaCamelProcessorTxLogHelper myCdaCamelProcessorTxLogHelper;
If the generic transaction log helper and module-specific transaction log helpers need to be autowired into the same @Configuration
class, implementers must use the IGenericCamelProcessorTxLogHelper
type
(instead of ICamelProcessorTxLogHelper
) so Spring can differentiate between transaction log helper types:
@Autowired
private IGenericCamelProcessorTxLogHelper myGenericCamelProcessorTxLogHelper;
@Autowired
private IHl7V2CamelProcessorTxLogHelper myHl7V2CamelProcessorTxLogHelper;
@Autowired
private ICdaCamelProcessorTxLogHelper myCdaCamelProcessorTxLogHelper;
In the rare case that implementers need to autowire in multiple module-specific transaction log helpers from the same module type, a qualifier must be used.
The qualifier convention is shown below:
[moduleId]_[txLogHelperName]
where moduleId
is the ID of the module, and txLogHelperName
is the name of the transaction log helper bean.
In the example below, two IHl7V2CamelProcessorTxLogHelper
instances are autowired:
// This instance has moduleId=endpoint_hl7v2_in_one and txLogHelperName=hl7v2CamelProcessorTransactionLogHelper
@Autowired
@Qualifier("endpoint_hl7v2_in_one_hl7v2CamelProcessorTransactionLogHelper")
private IHl7V2CamelProcessorTxLogHelper myHl7V2CamelProcessorTxLogHelperOne;
// This instance has moduleId=endpoint_hl7v2_in_two and txLogHelperName=hl7v2CamelProcessorTransactionLogHelper
@Autowired
@Qualifier("endpoint_hl7v2_in_two_hl7v2CamelProcessorTransactionLogHelper")
private IHl7V2CamelProcessorTxLogHelper myHl7V2CamelProcessorTxLogHelperTwo;