Knowledge Base

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I leverage a payload property when the Read Method is part of the transaction?

Use Case Description

Company A has a Global Distribution System (GDS) which has a custom protocol called Protocol A (a request/reply style protocol). Their subsidiary, a travel website, would like to monitor their application with AppDyamics Pro. Java Agents will be installed on the GDS and the travel site Web Servers. They would like to the correlation across these systems.

 

Each message sent from client and server is wrapped in a CompanyAMessge instance. Company A has agreed to add a correlation key member to this class for correlation.

 

Correlation Example

This example covers the following scenarios:

  • producer type - the correlation method and exit point are the same.
  • consumer type - the correlation header read is inside the continuing transaction (nested case).

In this example the readData() method is measured as part of the continuing transaction.

 

Producer Payload

public class FlightStatusMessage implements Serializable {
    private Map<String,String> requests = new ConcurrentHashMap<String, String>();
    private Map responses = new ConcurrentHashMap();
    private String correlationKey = null;
    private String airline;

 

Producer Code

Call is issued as usual to request the flight status information.

private void handleUSAirways(String airline, HttpServletRequest request) throws IOException {
        Map<String, String> flights = new HashMap<String, String>();
        int flightCount = Integer.parseInt(request.getParameter("flightCount"));
        for (int i = 1; i <= flightCount; i++) {
            String flightNo = airline + request.getParameter("flight" + i);
            flights.put(flightNo, flightNo);
        }

        if (flights.size() > 0) {
            FlightStatusMessage message = new FlightStatusMessage(flights);
            message.setAirline("US");
            FlightStatusMessage response = queryForStatusWithPayload(message);
            request.setAttribute("results", response.getResponses());
        }


    }

 

Producer XML Configuration

<!--
 This creates a custom exit and does outgoing correlation downstream.
 On the consuming side the header is read and a transaction is begun at the same point.
 -->
<activities>
    <producer>
        <!--
         This is where a custom exit point is defined
         -->
        <instrumentation>
            <class-name>com.appdynamics.samples.FlightSearch</class-name>
            <method-name>queryForStatusWithPayload</method-name>
            <match-type>MATCHES_CLASS</match-type>
        </instrumentation>
        <!--
         The following identifier config is used to name the custom exit point.
         This is similar to how we name custom exit points from the Controller Console
         -->
        <identifiers>
            <identifier name="USAirwaysSearch">                
                <data-gatherer-type>INVOKED</data-gatherer-type>
                <getter-chain>this</getter-chain>
                <user-defined-name>USAirwaysSearch</user-defined-name>
                <transformer-type>USER_DEFINED_NAME</transformer-type>
            </identifier>
        </identifiers>
        <!--
         The following correlationn element is where and how to add the correlation metadata
         -->
        <correlation>
            <!--
             This is where we apply instrumentation to get hold of the outgoing payload
             -->
            <instrumentation>
                <class-name>com.appdynamics.samples.FlightSearch</class-name>
                <method-name>queryForStatusWithPayload</method-name>
                <match-type>MATCHES_CLASS</match-type>
            </instrumentation>
            <!--
             This is how we grab the payload at the instrumentation point defined above
             -->
            <payload-pointer>
                <data-gatherer-type>POSITION</data-gatherer-type>
                <position>0</position>
                <getter-chain>this</getter-chain>
                <transformer-type>GETTER_METHODS</transformer-type>
            </payload-pointer>
            <!--
             This is how we add the correlation metadata to the payload
             -->
            <payload-operation>
                <access-type>method</access-type>
                <access-method>setCorrelationKey</access-method>
                <param-types>java.lang.String</param-types>
            </payload-operation>
        </correlation>
    </producer>
</activities>

 

Consumer code snippet

public void run() {
       Object payload = readRequest(client);
       Object response = null;
       if (payload instanceof FlightStatusMessage) {

           FlightStatusMessage messagePayload = (FlightStatusMessage)payload;
           if ("BA".equals(messagePayload.getAirline())) {
           messagePayload.setResponses(processMessage(messagePayload));
           response = messagePayload;
           } else if ("US".equals(messagePayload.getAirline())) {
               messagePayload = readData(payload);
               messagePayload.setResponses(processMessage(messagePayload));
               response = messagePayload;
           }
       } else if (payload instanceof Map) {
           response = processRequest((HashMap)payload);
       }
       logger.info("request processed");
       writeRepsonse(client, response);
       logger.info("response written");
    }

 

Consumer XML Configuration

<!--
 This creates a custom exit and does outgoing correlation downstream.
 On the consuming side the header is read and a transaction is begin at the same point.
 -->
<activities>
    <!--
     The activity-demarcator="true" specifies that the instrumentation element defines the boundary of the continuing transaction and that the correlation header is read inside of this method.
       Note: that the transaction begins only if a correlation header is read
     -->
    <consumer activity-demarcator="true">
        <!--
         This is the boundary of the continuing transaction and also encloses the point where correlation metadata is read
         -->
        <instrumentation>
            <class-name>com.appdynamics.samples.FlightSearchHandler</class-name>
            <method-name>run</method-name>
            <match-type>MATCHES_CLASS</match-type>
        </instrumentation>
        <correlation>
            <!--
             This is where instrumentation to get payload bearing correlation metadata.
             This instrumentation point is inside of transaction boundary specified above
             -->
            <instrumentation>
                <class-name>com.appdynamics.samples.FlightSearchHandler</class-name>
                <method-name>readData</method-name>
                <match-type>MATCHES_CLASS</match-type>
            </instrumentation>
            <!--
             How to get payload ?
             -->
            <payload-pointer>
                <data-gatherer-type>RETURN</data-gatherer-type>
                <getter-chain>this</getter-chain>
                <transformer-type>GETTER_METHODS</transformer-type>
            </payload-pointer>

            <!--
             How to extract correlation metadata from payload
             -->
            <payload-operation>
                <access-type>method</access-type>
                <access-method>getCorrelationKey</access-method>
            </payload-operation>
        </correlation>
    </consumer>
</activities>
Version history
Revision #:
2 of 2
Last update:
‎12-21-2018 04:37 PM
Updated by:
 
Labels (1)
Contributors


Found this article helpful? Click the Thumbs Up button.
Have an additional comment? Post it below.
0 Kudos
Comments

is there any documentation that would help me understand what these properties are for and how to use them? 

activity-demarcator="true"
identify-transaction="true"
pojo-entry="true"

 

Do you have a tool we can use that would help me create custom correlation activity?