50.8.1Transaction Logging Processors

 

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.

50.8.1.1Automatic Transaction Logging

By default, Smile CDR automatically creates transaction logs for all Camel routes when transaction logging is globally enabled. This automatic logging captures:

  • Camel Exchange Events: Route start, completion, and failure events with the CAMEL_EXCHANGE step type
  • Processor Execution: Individual processor steps during route execution
  • Performance Metrics: Timing information for route and processor execution
  • Error Handling: Failure conditions and exception details

Transaction 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.

50.8.1.2Global Transaction Log Configuration

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:

  • When true (default): All routes automatically create transaction logs without requiring explicit smile:camel/txLogStart processors
  • When false: Transaction logging must be explicitly enabled for individual routes using the smile:camel/txLogStart processor

50.8.1.3Route-Level Transaction Log Control

Transaction 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!

50.8.1.4Manual Transaction Log Control

For custom transaction logging control, you have several options:

  1. Explicit Start: Add a 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 steps

Hl7V2 intermediate route processors will add log steps if the intermediate_logging_enabled property is set to true.

50.8.2Start Transaction Log Processor

 
  • Example URI: smile:camel/txLogStart
  • Description: Manually starts transaction logging for the route.

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:

  • The global setting enable_transaction_log_on_all_routes is set to false
  • You want to start transaction logging at a specific point in the route rather than at the beginning

50.8.3Add Transaction Log Step Processor

 
  • Example URI: smile:camel/txLogAddStep
  • Description: Request step logging for previous route node. Used mainly for custom processor route-triggered logging, as smile processors generate log steps automatically.

50.8.3.1Transaction Logging Parameters

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.

50.8.3.2Transaction Logging Example Route combining smile and custom processors

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>

50.8.3.3Transaction Logging Example Custom Processors

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);
	}
}

50.8.4Adding Module-Specific Transaction Log Helpers

 

50.8.4.1Autowiring Module-Specific Transaction Log Helpers

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;

50.8.4.2Autowiring Generic and Module-Specific Transaction Log Helpers

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;

50.8.4.3Autowiring Multiple Module-Specific Transaction Log Helpers From the Same Module Type

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;