/* * 2012-5 Red Hat Inc. and/or its affiliates and other contributors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.overlord.rtgov.integration.btm; import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.logging.Level; import java.util.logging.Logger; import org.hawkular.btm.api.model.btxn.BusinessTransaction; import org.hawkular.btm.api.model.btxn.Consumer; import org.hawkular.btm.api.model.btxn.ContainerNode; import org.hawkular.btm.api.model.btxn.Content; import org.hawkular.btm.api.model.btxn.CorrelationIdentifier; import org.hawkular.btm.api.model.btxn.InteractionNode; import org.hawkular.btm.api.model.btxn.Node; import org.hawkular.btm.api.model.btxn.Producer; import org.overlord.rtgov.activity.model.ActivityType; import org.overlord.rtgov.activity.model.ActivityUnit; import org.overlord.rtgov.activity.model.Context; import org.overlord.rtgov.activity.model.Context.Type; import org.overlord.rtgov.activity.model.Origin; import org.overlord.rtgov.activity.model.soa.RequestReceived; import org.overlord.rtgov.activity.model.soa.RequestSent; import org.overlord.rtgov.activity.model.soa.ResponseReceived; import org.overlord.rtgov.activity.model.soa.ResponseSent; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; /** * * @author gbrown * */ public class BTMFragmentToActivityUnitConverter { private static final String BTM_SERVICE_TYPE = "btm_serviceType"; private static final String BTM_SERVICE_OPERATION = "btm_serviceOperation"; private static AtomicInteger counter=new AtomicInteger(); private static ObjectMapper mapper=new ObjectMapper(); private static final Logger LOG=Logger.getLogger(BTMFragmentToActivityUnitConverter.class.getName()); /** * Convert the business transactions to activity units. * * @param btxns The business txns * @return The activity units */ public List<ActivityUnit> convert(List<BusinessTransaction> btxns) { List<ActivityUnit> ret=new ArrayList<ActivityUnit>(); if (LOG.isLoggable(Level.FINEST)) { try { LOG.finest("Convert business transactions: btxns="+mapper.writeValueAsString(btxns)); } catch (JsonProcessingException e) { e.printStackTrace(); } } for (BusinessTransaction btxn : btxns) { ActivityUnit au=new ActivityUnit(); au.setId(btxn.getId()); processNodes(btxn, btxn.getNodes(), au); if (!au.getActivityTypes().isEmpty()) { Origin origin = new Origin(); origin.setHost(btxn.getHostName()); au.setOrigin(origin); ret.add(au); } } if (LOG.isLoggable(Level.FINEST)) { try { LOG.finest("To activity units: ret="+mapper.writeValueAsString(ret)); } catch (JsonProcessingException e) { e.printStackTrace(); } } return ret; } protected void processNodes(BusinessTransaction btxn, List<Node> nodes, ActivityUnit au) { for (int i=0; i < nodes.size(); i++) { processNode(btxn, nodes.get(i), au); } } protected void processNode(BusinessTransaction btxn, Node node, ActivityUnit au) { int index=counter.getAndIncrement(); String reqId=btxn.getId()+"_req"+index; String respId=btxn.getId()+"_resp"+index; // Create pre activity event if ((node instanceof Consumer || node instanceof Producer) && node.getDetails().containsKey(BTM_SERVICE_TYPE)) { processRequest((InteractionNode)node, reqId, au, btxn); } if (node instanceof ContainerNode) { processNodes(btxn, ((ContainerNode)node).getNodes(), au); } // Create post activity event if ((node instanceof Consumer || node instanceof Producer) && node.getDetails().containsKey(BTM_SERVICE_TYPE)) { processResponse((InteractionNode)node, reqId, respId, au, btxn); } } protected void processRequest(InteractionNode service, String reqId, ActivityUnit au, BusinessTransaction btxn) { String intf=service.getDetails().get("interface"); if (intf == null) { intf = service.getUri(); } long startTime=btxn.getStartTime(); long topNodeBaseTime=btxn.getNodes().get(0).getBaseTime(); long diffms=TimeUnit.MILLISECONDS.convert(service.getBaseTime() - topNodeBaseTime, TimeUnit.NANOSECONDS); if (service instanceof Producer) { RequestSent rs=new RequestSent(); rs.setServiceType(service.getDetails().get(BTM_SERVICE_TYPE)); rs.setOperation(service.getDetails().get(BTM_SERVICE_OPERATION)); rs.setTimestamp(startTime + diffms); rs.setInterface(intf); convertCorrelationInformation(service, rs, reqId); if (service.getIn() != null) { if (service.getIn().getHeaders() != null && !service.getIn().getHeaders().isEmpty()) { convertHeaders(service, rs); } if (!service.getIn().getContent().isEmpty()) { Content c=service.getIn().getContent().values().iterator().next(); rs.setContent(c.getValue()); if (c.getType() != null) { rs.setMessageType(c.getType()); } } } if (service instanceof Producer) { rs.getProperties().put("gateway", ((Producer)service).getEndpointType()); } rs.getProperties().putAll(btxn.getProperties()); rs.setUnitId(au.getId()); rs.setUnitIndex(au.getActivityTypes().size()); au.getActivityTypes().add(rs); } if (service instanceof Consumer) { RequestReceived rr=new RequestReceived(); rr.setServiceType(service.getDetails().get(BTM_SERVICE_TYPE)); rr.setOperation(service.getDetails().get(BTM_SERVICE_OPERATION)); rr.setTimestamp(startTime + diffms); rr.setInterface(intf); convertCorrelationInformation(service, rr, reqId); if (service.getIn() != null) { if (service.getIn().getHeaders() != null && !service.getIn().getHeaders().isEmpty()) { convertHeaders(service, rr); } if (!service.getIn().getContent().isEmpty()) { Content c=service.getIn().getContent().values().iterator().next(); rr.setContent(c.getValue()); if (c.getType() != null) { rr.setMessageType(c.getType()); } } } if (service instanceof Consumer) { rr.getProperties().put("gateway", ((Consumer)service).getEndpointType()); } rr.getProperties().putAll(btxn.getProperties()); rr.setUnitId(au.getId()); rr.setUnitIndex(au.getActivityTypes().size()); au.getActivityTypes().add(rr); } } protected void processResponse(InteractionNode service, String reqId, String respId, ActivityUnit au, BusinessTransaction btxn) { String intf=service.getDetails().get("interface"); if (intf == null) { intf = service.getUri(); } long startTime=btxn.getStartTime(); long topNodeBaseTime=btxn.getNodes().get(0).getBaseTime(); long diffms=TimeUnit.MILLISECONDS.convert((service.getBaseTime() + service.getDuration() - topNodeBaseTime), TimeUnit.NANOSECONDS); if (service instanceof Consumer) { ResponseSent rs=new ResponseSent(); rs.setServiceType(service.getDetails().get(BTM_SERVICE_TYPE)); rs.setOperation(service.getDetails().get(BTM_SERVICE_OPERATION)); rs.setTimestamp(startTime + diffms); rs.setInterface(intf); rs.setReplyToId(reqId); convertCorrelationInformation(service, rs, respId); if (service.getOut() != null) { if (service.getOut().getHeaders() != null && !service.getOut().getHeaders().isEmpty()) { convertHeaders(service, rs); } if (!service.getOut().getContent().isEmpty()) { Content c=service.getOut().getContent().values().iterator().next(); rs.setContent(c.getValue()); if (c.getType() != null) { rs.setMessageType(c.getType()); } } } if (service instanceof Consumer) { rs.getProperties().put("gateway", ((Consumer)service).getEndpointType()); } rs.getProperties().putAll(btxn.getProperties()); rs.setUnitId(au.getId()); rs.setUnitIndex(au.getActivityTypes().size()); if (service.getFault() != null) { rs.setFault(service.getFault()); if (service.getFaultDescription() != null) { rs.setContent(service.getFaultDescription()); } } au.getActivityTypes().add(rs); } if (service instanceof Producer) { ResponseReceived rr=new ResponseReceived(); rr.setServiceType(service.getDetails().get(BTM_SERVICE_TYPE)); rr.setOperation(service.getDetails().get(BTM_SERVICE_OPERATION)); rr.setTimestamp(startTime + diffms); rr.setInterface(intf); rr.setReplyToId(reqId); convertCorrelationInformation(service, rr, respId); if (service.getOut() != null) { if (service.getOut().getHeaders() != null && !service.getOut().getHeaders().isEmpty()) { convertHeaders(service, rr); } if (!service.getOut().getContent().isEmpty()) { Content c=service.getOut().getContent().values().iterator().next(); rr.setContent(c.getValue()); if (c.getType() != null) { rr.setMessageType(c.getType()); } } } if (service instanceof Producer) { rr.getProperties().put("gateway", ((Producer)service).getEndpointType()); } rr.getProperties().putAll(btxn.getProperties()); rr.setUnitId(au.getId()); rr.setUnitIndex(au.getActivityTypes().size()); if (service.getFault() != null) { rr.setFault(service.getFault()); if (service.getFaultDescription() != null) { rr.setContent(service.getFaultDescription()); } } au.getActivityTypes().add(rr); } } /** * This method converts the BTM correlation ids into activity context information. * * @param node The node * @param activity The activity * @param mesgId The message id */ protected void convertCorrelationInformation(Node node, ActivityType activity, String mesgId) { activity.getContext().add(new Context(Type.Message, mesgId)); for (CorrelationIdentifier ci : node.getCorrelationIds()) { Context c=new Context(); switch (ci.getScope()) { case Global: c.setType(Type.Conversation); break; case Interaction: c.setType(Type.Message); break; case Local: c.setType(Type.Endpoint); break; default: break; } c.setValue(ci.getValue()); activity.getContext().add(c); } } protected void convertHeaders(InteractionNode service, ActivityType activity) { for (String key : service.getIn().getHeaders().keySet()) { activity.getProperties().put(key, service.getIn().getHeaders().get(key)); activity.getProperties().put("_header_format_"+key, "text"); } } }