In this blog, I will explain the possible approach to take, extend the runtime statistics in the APIM to DAS. Custom event publishing is important when you want to publish a custom event which is not provided apim by default. Also, it will help to handle more advanced business requirements like message body based analytics which is also not proved by the APIM by default.
Class mediator[1] is another approach to extend the APIM runtime statistics as an event. You can create a java class with DAS data publisher which will publisher the event when Class mediator gets invoke. Here the sample java class for the class mediator. Before start implement makes sure to import all the required java dependencies to the project. For that please check the sample section for the source code.
package com.rukspot.sample.eventpublisher; import org.apache.synapse.MessageContext; import org.apache.synapse.mediators.AbstractMediator; import org.apache.synapse.rest.RESTConstants; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityUtils; import org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.databridge.agent.DataPublisher; public class SimpleClassMediator extends AbstractMediator { public boolean mediate(MessageContext mc) { String context = (String) mc.getProperty(RESTConstants.REST_API_CONTEXT); String apiPublisher = (String) mc.getProperty(APIMgtGatewayConstants.API_PUBLISHER); String apiVersion = (String) mc.getProperty(RESTConstants.SYNAPSE_REST_API); String api = APIUtil.getAPINamefromRESTAPI(apiVersion); AuthenticationContext authContext = APISecurityUtils.getAuthenticationContext(mc); String username = ""; String applicationName = ""; if (authContext != null) { username = authContext.getUsername(); applicationName = authContext.getApplicationName(); } System.out.println(api); try { DataPublisher publisher = EventPublisher.getPublisher(); String id = "org.wso2.apimgt.statistics.custom:1.0.0"; Object[] payload= new Object[]{api,applicationName,username}; publisher.publish(id, null, null, payload); } catch (Exception e) { System.out.println("error Sending event " + e.getMessage()); } return true; } }
Another way is to implement the data publisher in a synapse handler[2]. It is similar to the class mediator but it is implemented as a handler and place in the handler section in the API synapse. Here the sample handler class.
package com.rukspot.sample.eventpublisher; import org.apache.synapse.MessageContext; import org.apache.synapse.rest.AbstractHandler; import org.apache.synapse.rest.RESTConstants; import org.wso2.carbon.apimgt.gateway.APIMgtGatewayConstants; import org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityUtils; import org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext; import org.wso2.carbon.apimgt.impl.utils.APIUtil; import org.wso2.carbon.databridge.agent.DataPublisher; public class SimpleEventPublisherHandler extends AbstractHandler { public boolean handleRequest(MessageContext mc) { String context = (String) mc.getProperty(RESTConstants.REST_API_CONTEXT); String apiPublisher = (String) mc.getProperty(APIMgtGatewayConstants.API_PUBLISHER); String apiVersion = (String) mc.getProperty(RESTConstants.SYNAPSE_REST_API); String api = APIUtil.getAPINamefromRESTAPI(apiVersion); AuthenticationContext authContext = APISecurityUtils.getAuthenticationContext(mc); String username = ""; String applicationName = ""; if (authContext != null) { username = authContext.getUsername(); applicationName = authContext.getApplicationName(); } System.out.println(api); try { DataPublisher publisher = EventPublisher.getPublisher(); String id = "org.wso2.apimgt.statistics.custom:1.0.0"; Object[] payload= new Object[]{api,applicationName,username}; publisher.publish(id, null, null, payload); } catch (Exception e) { System.out.println("error Sending event " + e.getMessage()); } return true; } public boolean handleResponse(MessageContext messageContext) { return true; } }
<?xml version="1.0" encoding="UTF-8"?> <eventSink> <receiverUrl>tcp://localhost:7612</receiverUrl> <authenticatorUrl/> <username>admin</username> <password>admin</password> </eventSink>
<?xml version="1.0" encoding="UTF-8"?> <api xmlns="http://ws.apache.org/ns/synapse" name="admin--sample" context="/sample/1.0.0" version="1.0.0" version-type="context"> <resource methods="GET" url-mapping="/one" faultSequence="fault"> <inSequence> <property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/> <filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION"> <then> <publishEvent> <eventSink>testSink</eventSink> <streamName>test</streamName> <streamVersion>1.0.0</streamVersion> <attributes> <meta/> <correlation/> <payload> <attribute name="atr1" type="STRING" defaultValue="" value="testValue"/> <attribute name="atr2" type="STRING" defaultValue="" value="Test Region"/> </payload> <arbitrary/> </attributes> </publishEvent> <send> <endpoint name="admin--sample_APIproductionEndpoint_0"> <http uri-template="http://localhost:8080/simple-service-webapp/webapi/myresource"/> <property name="ENDPOINT_ADDRESS" value="http://localhost:8080/simple-service-webapp/webapi/myresource"/> </endpoint> </send> </then> <else> <sequence key="_sandbox_key_error_"/> </else> </filter> </inSequence> <outSequence> <class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/> <send/> </outSequence> </resource> <resource methods="GET" url-mapping="/two" faultSequence="fault"> <inSequence> <property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/> <filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION"> <then> <send> <endpoint name="admin--sample_APIproductionEndpoint_1"> <http uri-template="http://localhost:8080/simple-service-webapp/webapi/myresource"/> <property name="ENDPOINT_ADDRESS" value="http://localhost:8080/simple-service-webapp/webapi/myresource"/> </endpoint> </send> </then> <else> <sequence key="_sandbox_key_error_"/> </else> </filter> </inSequence> <outSequence> <class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/> <send/> </outSequence> </resource> <handlers> <handler class="org.wso2.carbon.apimgt.gateway.handlers.common.APIMgtLatencyStatsHandler"/> <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"> <property name="apiImplementationType" value="ENDPOINT"/> </handler> <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/> <handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.ThrottleHandler"> <property name="productionMaxCount" value="2"/> </handler> <handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/> <handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler"> <property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/> </handler> <handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/> </handlers> </api>
<bam xmlns="http://ws.apache.org/ns/synapse"> <serverProfile name="test-bam-profile"> <streamConfig name="org.wso2.apimgt.statistics.custom" version="1.0.0"></streamConfig> </serverProfile> </bam>>
<?xml version="1.0" encoding="UTF-8"?> <api xmlns="http://ws.apache.org/ns/synapse" name="admin--sample" context="/sample/1.0.0" version="1.0.0" version-type="context"> <resource methods="GET" url-mapping="/*" faultSequence="fault"> <inSequence> <filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION"> <then> <property name="api.ut.backendRequestTime" expression="get-property('SYSTEM_TIME')"/> <bam xmlns="http://ws.apache.org/ns/synapse"> <serverProfile name="test-bam-profile"> <streamConfig name="org.wso2.apimgt.statistics.custom" version="1.0.0"></streamConfig> </serverProfile> </bam> <send> <endpoint name="admin--sample_APIproductionEndpoint_0"> <http uri-template="http://localhost:8080/simple-service-webapp/webapi/myresource"/> </endpoint> </send> </then> <else> <sequence key="_sandbox_key_error_"/> </else> </filter> </inSequence> <outSequence> <class name="org.wso2.carbon.apimgt.usage.publisher.APIMgtResponseHandler"/> <send/> </outSequence> </resource> <handlers> <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.CORSRequestHandler"> <property name="apiImplementationType" value="ENDPOINT"/> </handler> <handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/> <handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.APIThrottleHandler"> <property name="id" value="A"/> <property name="policyKeyResource" value="gov:/apimgt/applicationdata/res-tiers.xml"/> <property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/> <property name="policyKeyApplication" value="gov:/apimgt/applicationdata/app-tiers.xml"/> </handler> <handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/> <handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler"> <property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/> </handler> <handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/> </handlers> </api>
Here you can find the above-mentioned sample. Class mediator and Handler implementation can be found on the jar inside the zip. Download the sample from here. Please find the readme for more about the configuration.
Add Comment
Comments (0)