On this page:

Your Rating:
Results:
PatheticBadOKGoodOutstanding!
0 rates
Manual tracer instrumentation consists of the following steps:

  1. Instantiate the Tracer
  2. Create a Transaction
  3. Start and Stop a Transaction
  4. Create External Exit Calls

Instantiate the Tracer

To instantiate the tracer, call the AppDynamics.getTracer(context) method. Place the method at the beginning of your function's entry point method.

The code snippet demonstrates how to instantiate the tracer: 

@Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
 
		//Instantiate the tracer.
  		Tracer tracer = AppDynamics.getTracer(context);
 
		//Your AWS Lambda function code begins here.
		int letter = 0;
        while((letter = input.read()) >= 0) {
            output.write(Character.toUpperCase(letter));
		}
    }

Create a Transaction

Next, you need to create transactions. A transaction is a monitored segment in a larger business transaction. Creating a transaction involves locating the correlation header, which the serverless tracer uses to pass contextual information downstream.  

Transactions either:

  • Start a new business transaction, or
  • Continue an existing business transaction 

Start a New Business Transaction 

A transaction that originates in the current function does not have an inbound correlation header. To create a business transaction, use the createTransaction() method and provide an empty correlation header. 

Continue an Existing Business Transaction

To continue an existing business transaction, you need to locate an inbound correlation header. You can locate a correlation header automatically or manually. 

If the tracer cannot find the correlation header, the tracer creates a new business transaction.

Continue a Business Transaction by Locating the Correlation Header Automatically

Use the createTransaction(inputStream, context) method to create a transaction that locates the correlation header automatically. This method searches your code's object schema for a key called singularityheader in the inputStream object. The correlation header finds the singularityheader key, then continues the business transaction.

The tracer reads the inputStream object, which is configured to be read once. If your application needs to read the inputStream object, you must use a converter method to allow both the tracer and your application to read the stream. 

The code snippet shows an example of how to create a transaction and automatically locate the correlation header:

public class <LambdaChops> implements RequestStreamHandler {
    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
  	Tracer tracer = AppDynamics.getTracer(context);
	
	//Use a converter method if you need to read your inputStream more than once. The tracer reads your inputStream once.
  	inputStream = InputStreamConverter.convertToMarkSupportedInputStream(input);
 
	//Create a transaction. 
	Transaction transaction = tracer.createTransaction(input, context);

	//Your AWS Lambda function code begins here. 
        int letter = 0;
        while((letter = input.read()) >= 0) {
            output.write(Character.toUpperCase(letter));
        }
    }
}
Create a Transaction by Locating the Correlation Header Manually

To create a transaction that locates the correlation header using custom logic, you need to manually parse a correlationHeader string. Next, call the createTransaction()method and provide the correlationHeader object. This process gives you full control over the parsing of your function's input payload. 

The code snippet shows an example of how to obtain the correlation header string and create a transaction:

public class <LambdaChops> implements RequestHandler {
    @Override
	public O handleRequest(InputStream input, OutputStream output, Context context) {
	Tracer tracer = AppDynamics.getTracer(context);
     
	//Manually parse the correlation string.
     String inputAsString = IOUtils.toString(inputStream, Charset.forName("UTF-8"));
     JsonParser parser = new JsonParser();
     JsonObject inputObject = parser.parse(inputAsString).getAsJsonObject();
 
	String correlationHeader = "";
	if (inputObject.has(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY)) {
    	correlationHeader = inputObject.get(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY).getAsString();
	} else {
    	// Try reading from HTTP headers
    	if (inputObject.has("headers")) {
        	JsonObject httpHeaders = inputObject.getAsJsonObject("headers");
        	if (httpHeaders.has(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY)) {
            	correlationHeader = httpHeaders.get(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY).getAsString();
        }	
    }
}
 
	// Create transaction object using the correlation header. If the correlationHeader string is empty, the transaction you create uses the default transaction name.
	Transaction transaction = tracer.createTransaction(correlationHeader);
 
	//Your AWS Lambda function code starts here
	...
 
}

Start and Stop a Transaction

After creating a transaction, you need to set transaction boundaries. Use the transaction.start() and transaction.stop() methods to place boundaries around any section of code that you want the tracer to monitor. As a best practice, you can report all events, even if your function crashes, by running your entire function within a try block, and then stopping the transaction within a finally block.  

The Serverless Tracer makes HTTPS requests to report metrics to the Controller. AppDynamics performs the HTTPS requests asynchronously to avoid blocking your function's execution. To ensure the asynchronous tasks complete, call AppDynamics.cleanup() as part of your function’s execution. If you do not call this method, your AWS Lambda functions may not appear on your Controller's flow map.


This code sample demonstrates how to start and stop a transaction that monitors an entire function:

@Override
 public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
  Tracer tracer = AppDynamics.getTracer(context);
  Transaction transaction = tracer.createTransaction(input, context);
 
	//Start the transaction monitoring.
  	transaction.start();
  	try { 
   		int letter = 0;
        while((letter = input.read()) >= 0) {
            output.write(Character.toUpperCase(letter));
		}
 
	//Stop the transaction monitoring. Place in a finally block to monitor all events. 
	} finally {
   		transaction.stop();
		AppDynamics.cleanup();
  	}  
 }

Create External Exit Calls

The createExitCall method is used to obtain an exitCall object. Exit call objects record the time spent in external exit calls and allow for correlation of downstream activity. 

Exit Call Types and Identifying Properties

In the Controller, each exit call has a distinct type, determined by a set of identifying properties. 

The exitCall types and identifying properties are listed below: 

exitCall Type
Identifying Properties
HTTP

HOST

PORT

URL

QUERY STRING

JDBC

URL

HOST

PORT

DATABASE

VERSION

VENDOR

WEB SERVICE

SERVICE

URL

OPERATION

SOAP ACTION

VENDOR

CUSTOMAny user-defined set of properties

This code sample demonstrates how you might define identifying properties for exit calls:

String outgoingHeader = null;
String callType = null;
Map<String, String> identifyingProperties = new HashMap<>();
    
//Below properties are appropriate for an inter-AWS Lambda call
identifyingProperties.put("DESTINATION", functionName);
identifyingProperties.put("DESTINATION_TYPE", "LAMBDA");
callType="CUSTOM";
    
//Below properties are appropriate for an external HTTP call
identifyingProperties.put("HOST", url.getHost());     
identifyingProperties.put("PORT", String.valueOf(url.getPort()));
callType="HTTP";
 

Create an External Exit Call 

Call createExitCall() on your transaction object. 

The following code sample demonstrates how you might perform an external exit call:

public void makeExitCall(URL url){
 
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
 
String outgoingHeader = null;
String callType = null;
Map<String, String> identifyingProperties = new HashMap<>();
    
//Below properties are appropriate for an inter-AWS Lambda call
identifyingProperties.put("DESTINATION", functionName);
identifyingProperties.put("DESTINATION_TYPE", "LAMBDA");
callType="CUSTOM";
    
//Below properties are appropriate for an external HTTP call
identifyingProperties.put("HOST", url.getHost());     
identifyingProperties.put("PORT", String.valueOf(url.getPort()));
callType="HTTP";
 
//Define the createExitCall method to obtain an exitCall object.     
ExitCall exitCall = transaction.createExitCall(callType, identifyingProperties);
outgoingHeader =  exitCall.getCorrelationHeader();
exitCall.start();
    
try {
// Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY is the name of the header that should be set
   
    if (outgoingHeader != null) {
        conn.setRequestProperty(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY, outgoingHeader); // set the correlation header on an HttpURLConnection
    }
  
// Make the exit call here
  
} finally {
        exitCall.stop();
    }
}

Create Multiple External Exit Calls

If one AWS Lambda function makes multiple exit calls, each function should be identified by a unique exitCall object. To make multiple exit calls, create new exitCall objects for each distinct exit call. The exitCall objects are not reusable. 

The following code sample demonstrates how you might perform multiple external exit calls. 

public void makeExitCall(URL url){
 
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
 
String outgoingHeader = null;
String callType = null;
Map<String, String> identifyingProperties = new HashMap<>();
  
identifyingProperties.put("HOST", url.getHost());
identifyingProperties.put("PORT", String.valueOf(url.getPort()));
callType="HTTP"; // This should be the callType for both HTTP and HTTPS
  
//Define the createExitCall method to obtain an exitCall object for the first exitCall.  
//Give the exitCall a unique name.   
ExitCall exitCall1 = transaction.createExitCall(callType, identifyingProperties);
outgoingHeader =  exitCall1.getCorrelationHeader();
exitCall1.start();
  
try {
    // add the outgoing header to the payload and make the request, Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY is the name of the header that should be set
    // For example for HTTP, conn is of type HttpURLConnection
    if (outgoingHeader != null) {
        conn.setRequestProperty(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY, outgoingHeader);
    }
    //Make the first exit call
} finally {
    exitCall1.stop();
}
  
//Define the createExitCall method to obtain an exitCall object for the second exitCall.
//Give the exitCall a unique name.   
ExitCall exitCall2 = transaction.createExitCall(callType, identifyingProperties);
outgoingHeader =  exitCall2.getCorrelationHeader();
exitCall2.start();
  
try {
    // add the outgoing header to the payload and make the request, Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY is the name of the header that should be set
    // For example for HTTP, conn is of type HttpURLConnection
    if (outgoingHeader != null) {
        conn.setRequestProperty(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY, outgoingHeader);
    }
    //Make the second exit call
} finally {
    exitCall2.stop();
	}
}


Amazon Web Services, the AWS logo, AWS, and any other AWS Marks used in these materials are trademarks of Amazon.com, Inc. or its affiliates in the United States and/or other countries.

  • No labels