is possible to collected Camel route metrics at user level/user specific - apache-camel

We are building file processing system (web application + stateful) using camel, jms and rest. Multiple user can upload files. There is requirement to show min, max, mean time taken, average no of hits and etc specific to user. This almost inline with route metrics provided by camel. Is there way to collect this route metrics at user level? or should we extended metrics components and its registry to meet our needs.
Added below changes to code to collect metrics.
<!--added to bean context -->
<bean id="policy" class="org.apache.camel.component.metrics.routepolicy.MetricsRoutePolicy"/>
<!-- below changes done to route -->
<route id="prefRate" routePolicyRef="policy">
<from uri="cxfrs://bean://prefRateService?bindingStyle=SimpleConsumer"/>
<log message="Processing username:${headers.username}"/>
<setHeader headerName="HEADER_METRIC_NAME">
<simple>${headers.username}</simple>
</setHeader>
<to uri="log:body?level=INFO"/>
<to uri="bean:fxPrefRateProcessor" />
<to uri="metrics:meter:prefRateCounter"/>
</route>

You can overwrite the name of a metric in the route by setting the MetricsConstants.HEADER_METRIC_NAME header. To get a unique metric per user, just include the unique user name in the metric name. You could do something like this:
.setHeader(MetricsConstants.HEADER_METRIC_NAME, simple("your.metric.name.for.user.${body.user}"))
.to("metrics:meter:your.metric.name");
This would give you per-user metrics. There's some documentation on the apache site that covers the metrics component and how to set variables/values

Related

Camel - How to log select query in camel route using java dsl, when using MYBATIS component?

I want to log the select query before calling database for better readability of log for reference. I am using mybatis component. I want to know, if there is any inbuilt camel header or mybatis component header can be used log the query.
**CAMEL ROUTE**
from("timer://pollTheDatabase?delay=50s")
.routeId("db-pooling-route")
.to("mybatis:queryToSelectData?statementType=SelectOne");
**MAPPER**
#Mapper
public interface DBMapper{
public void queryToSelectData();
}
**MAPPER XML**
<select id="queryToSelectData" resultMap="Result">
SELECT * FROM ACCOUNT AND ROWNUM =1
</select>
I have a very brief knowledge of the mybatis component, so my answer might not be exact! Camel does not give an inbuilt option to capture the mybatis query. You only have an option to get the statement name. However, could you please log the body just before sending the query and check?
If the body doesn't have the query string, this is how I would do it. In order to get the query string, you could implement a bean where you would need to import the mybatis mapper file and extract the information you require. You could then write it to the log from the bean itself, or you could add it to the Exchange properties.

URL with parameter containing a list of values in `toD` gets collapsed into a single value

I have a Camel route which calls a web service, and one of the parameters this service expects is a URL parameter containing a list of values, ie. p1 in myhost/myuri?p1=foo&p1=bar.
I am putting that in a toD URI, as the parameter values need to be dynamic, ie. <camel:toD uri="http4://myhost/myuri?p1=foo&p1=bar" > (omitted Camel parameters and variables for brevity's sake).
Camel is converting this to p1=%5Bfoo%2C+bar%5D (url-encoded p1=[foo, bar]), which is not accepted by the backend service. I have no control over this backend service and cannot expect its interface to change in the future.
Is there any way I can force Camel to call the backend service the way I want to, instead of it collecting the parameter with multiple values into an array-like format?
Another approach would be to use CamelHttpQuery header to along with to, not toD endpoint
<setHeader headerName="CamelHttpQuery"><simple>p1=foo&p1=bar</simple></setHeader>
<to uri="http4://myhost/myuri">

Request based routing by header parameter values in Rest DSL in camel

I want to route the messages to different routes based on the data coming in header parameters.
rest()
.tag("API")
.id("eventRest")
.post("/data").description("Post a new settlement data record")
.consumes("application/json")
.param().type(RestParamType.header).name("channelID").endParam().to("direct:customRoute")
Here If I've the different param then this one should bypass and continue the rest of the flow in my program.

Camel-SQL Component useIterator not working as expected

I am trying to use camel-sql component with the option of useIterator=true but the result still gets loaded in one single big list. I have 2 million records to be processed and getting the resultset in one list is not an option. Below is the route configuration:
<route id="sql_route">
<from uri="activemq:MW_SQL"/>
<to uri="sql:SELECT ID, MSGID_PROD FROM amq.activemq_msgs?useIterator=true"/>
<log message="This data is = ${body}"/>
</route>
From sourcecode it is clear that camel takes the whole resultset in list and then creates iterator of the same. Wrong design.
The option useIterator is only for the consumer, eg when you use sql in the <from>. The sql component on the producer side do not support a iterative based.
You can use the JDBC component instead that supports this by setting OutputType=StreamList: http://camel.apache.org/jdbc
I logged a ticket to add support for this in the future in the SQL component: https://issues.apache.org/jira/browse/CAMEL-9849

How to add component group to analytics sidekick?

In Adobe Experience Manager (AEM) (CQ 5.6.1) you can configure the variable mappings for a SiteCatalyst report suite. This configuration page is found at:
http://localhost:4502/cf#/etc/cloudservices/sitecatalyst/my-config/my-framework.html
To add a component to the configuration you drag the component from the sidekick to the page. The component will only appear in the sidekick if it has a configured "analytics" child node.
Typically a component will appear in the sidekick under the group name specified in its configured componentGroup attribute. However, the analytics sidekick seems to only support the following groups and any other componentGroup is lumped into "Other".
General
Commerce
Search&Promote
Social Plugins
Other
In other words, if I change my component's componentGroup to "Commerce", then my component will appear under "Commerce" but if I change my component's componentGroup to "Custom", it will appear under "Other".
How can a new custom group be added to the sidekick groups? The list of groups must be specified somewhere in the CRX, but I can't seem to track it down.
The sidekick will only show up to a certain number of named component groups (default to 4). Anything more than that gets lumped into a 5th "Other" group, ignoring the group defined in the componentGroup property. Check out this info: http://forums.adobe.com/message/5029192
If there is a need to change, you can overlay the script found in
"/libs/cq/ui/widgets/source/widgets/wcm/ComponentList.js" and modify
the constant value
CQ.wcm.ComponentList.MAX_GROUPS = 4;
CQ.wcm.ComponentList.MIN_COMPS = 3;
So most likely since there are already 4 analytics groups defined by the system, you can't add your own because all the available slots are already filled. You'd likely need to modify the defaults first to allow more groups--or potentially remove everything from one of the existing groups so that group no longer shows.
Just for clarification...did you configure the "Group" in the analytics node for the components you're trying to expose to the SiteCatalyst framework? Assuming you're defining the analytics node outside of CRXDE (in your IDE), here's an example of analytics.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="nt:unstructured"
cq:componentGroup="My Group"
cq:componentName="Button"
cq:trackevents="myEvent"
cq:trackvars="someVar,anotherVar"/>
You need to make sure you set cq:componentGroup here. The componentGroup property set on the component configuration itself won't do it for you.
It wasn't clear to me in your initial question if this is what you meant, when you said you configured the componentGroup.
One other thing to think about is that I've seen some funny behavior with this framework. When you try to expose analytics properties from components that have some complex inheritance to them, I've seen CQ fail to add them to the Sidekick. I haven't diagnosed the issue yet (or isolated steps to reproduce), but I think there are some fringe-case bugs there. You may want to consider if that's a possibility, as well.

Resources