Tracer ExampleIntroductionThis example demonstrates the Tracer. Tracer is a tracing feature build in camel core to log snapshots of Exchanges while they are routed. This allows you to see:
When used Camel will by default log the snapshot at INFO level. This example demonstrates how to persist trace snapshots using JPA into a database. This allows you to store this information and query them from a SQL prompt, giving you full power to analyze the data. RequirementsThis requires Camel 2.0, the camel-jpa component and configuration of the target database. Data ModelCamel uses the org.apache.camel.processor.interceptor.JpaTraceEventMessage JPA @Entity as data model. The class has the following properties in the JPA model:
The table name for persisting trace events is: CAMEL_MESSAGETRACED Configuration of the databaseThe Tracer uses standard JPA configuration for setting the database. In the META-INF/persistence.xml file we setup the service unit and the database configuration as: <persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0"> <persistence-unit name="tracer" transaction-type="RESOURCE_LOCAL"> <class>org.apache.camel.processor.interceptor.jpa.JpaTraceEventMessage</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/> <property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver"/> <property name="hibernate.connection.username" value="sa"/> <property name="hibernate.connection.password" value=""/> <property name="hibernate.connection.url" value="jdbc:hsqldb:mem:camel_tracer"/> <property name="hibernate.hbm2ddl.auto" value="create"/> <!-- debugging flags --> <!-- <property name="hibernate.show_sql" value="true"/> <property name="hibernate.format_sql" value="true"/> --> </properties> </persistence-unit> </persistence> What is important is to add the JpaTraceEventMessage as a class in the persistence.xml file to register our data model: <class>org.apache.camel.processor.interceptor.JpaTraceEventMessage</class> In this example we use Hibernate JPA and a HSQLDB as database. Running the exampleThe README.txt states how to run the example from either ANT or Maven. Here we show running with Maven: mvn camel:run When the application starts it start:
Select the console where the application should prompt you to enter some words. Try entering: Camel You can also enter multiple quotes separate with space, and the response should be the best quote based on the list of words given. You can enter: Camel Beer and it should be smart enough to find a quote for the beer Seeing the trace eventsWhen the program was started a GUI application was started as well. Its a SQL prompt for the database. So try entering: select * from camel_messagetraced And it should return the list of trace events in the SQL. We enter this sql: select id, shortExchangeId, previousNode, toNode, body from camel_messagetraced and get the output as the picture below: RoutingThe diagram below illustrates the route diagram generated using Visualisation. We receive an Exchange from the in stream, then its split using the splitWords method. Then the quote method is invoked before its aggregated and finally sent to the stream out to be printed in the console. Trace the routingIf we look at the 6 rows from the traced SQL (the first picture) and with the route diagram in mind we can get a better understand how the Exchange was routed. 1. The Exchange does not have a previousNode so its the first step where its consumed from the input stream and that its going to the splitter. Configuration of JPA tracing in CamelIn Camel you need to configure it to use JPA for tracing. We do this as by adding a tracer in the META-INF/camel-context.mxl file: <!-- use camel jpa trace so we can see all the traced exchanges in a database --> <bean id="camelTracer" class="org.apache.camel.processor.interceptor.Tracer"> <!-- turn on jpa tracing, otherwise the TraceEventMessage is a non JPA Entity class --> <property name="useJpa" value="true"/> <!-- the destination to send the traced messages --> <property name="destination" ref="traced"/> <!-- we turn ordinary trace logging off so we only see the traced messages in the database, but you can have both if you like --> <property name="logLevel" value="OFF"/> </bean> To properly configure JPA for tracing we must complete these two steps: In this example we set the desintation that refers to a endpoint we define in the camel context: <endpoint id="traced" uri="jpa://org.apache.camel.processor.interceptor.JpaTraceEventMessage?persistenceUnit=tracer"/>
Here its important that the endpoint is configure with the {org.apache.camel.processor.interceptor.JpaTraceEventMessage}} as entity name and the persistenceUnit as an option. In out example we use tracer. Then the following is standard Spring JPA configuration: <!-- this is ordinary JPA spring configuration --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"> <bean class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> </property> </bean> <!-- this is ordinary JPA spring configuration --> <bean id="jpaTemplate" class="org.springframework.orm.jpa.JpaTemplate"> <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <!-- this is ordinary JPA spring configuration --> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean"> <!-- we have named our presistence unit tracer in the META-INF/persistence.xml file --> <property name="persistenceUnitName" value="tracer"/> </bean> However we must set the persistenceUnitName to the same unit name we defined in persistence.xml, such as tracer as we are using in this example. And if you are wondering how the Camel route is defined then its here: <route> <!-- in stream to allow you to enter some text in the console --> <from uri="stream:in?initialPromptDelay=4000&promptDelay=2000&promptMessage=Enter some words:"/> <!-- split the text using parallel execution --> <split parallelProcessing="true"> <!-- use methodCall expression to split the words, using a java bean to do it --> <method bean="quoteService" method="splitWords"/> <!-- for each split message invoke the quote server to get a quote of the word --> <to uri="bean:quoteService?method=quote"/> <!-- now we need to find the best quote, so we aggregate all the splitted words we use our own strategy how to aggregate --> <aggregate strategyRef="myAggregateStrategy"> <!-- correlate everything using constant true, as they are all from the same source --> <correlationExpression> <constant>true</constant> </correlationExpression> <!-- complete after 1 sec on inactivity --> <completionTimeout> <constant>1000</constant> </completionTimeout> <!-- send the result to stream out so we can see the response in the console --> <to uri="stream:out"/> </aggregate> </split> </route> See also |