+++
title = "Manual Instrumentation"
chapter = false
weight = 3
+++
## Add Custom Code for Manual Instrumentation
Monitoring for AWS Lambda functions written in Java is accomplished by using a tracer SDK. To implement this, we will be leveraging a combination of deployment configuration and adding custom code to our Lambda functions. We have taken care of the deployment configuration in the previous section, and now it's time to add the custom code to handle the instrumentation.
If you completed the previous section for Automatic Instrumentation (which you should have), then skip the **Add Tracer Dependency** section and go to the **Add Instrumentation Code** section.
### Add Tracer Dependency
The first thing we need to do is to add the tracer SDK as a dependency to our Java project. In the Cloud9 workspace, expand the *appd_aws_lambda_lab* folder, then expand the *java* subfolder. Next, open up the file **pom.xml** -- this file contains project information (including dependencies used by the Lambda functions, which we will be updating).

We're going to insert the following XML at the beginning of the XML block. This will add the AppDynamics Java Lambda tracer when it is time to compile the Lambda function. Locate the XML comment labeled `` and add the following:
``` xml
com.appdynamics
lambda-tracer
20.03.1391
```
The dependencies XML section should look like the following:
``` xml
com.appdynamics
lambda-tracer
20.03.1391
com.amazonaws
aws-lambda-java-log4j2
1.1.0
com.amazonaws
aws-java-sdk-secretsmanager
com.amazonaws
aws-java-sdk-lambda
com.amazonaws
aws-lambda-java-events
1.3.0
com.amazonaws
aws-java-sdk-dynamodb
org.apache.logging.log4j
log4j-core
2.8.2
org.apache.logging.log4j
log4j-api
2.8.2
com.github.javafaker
javafaker
1.0.2
```
Save your changes and close *pom.xml*.
### Add Instrumentation Code
Next, expand the *src* folder, then expand the following folders: *main*, *java*, *com*, *appdynamics*, *lambda*. The next file we will be updating is **FrontEndHandler.java**.
AWS Lambda functions in Java require code changes to handle instrumentation. When writing Lambda functions in Java, they will inherit from one of two interfaces -- *RequestHandler* or *RequestStreamHandler*. If the function class inherits from *RequestStreamHandler*, then we can take advantage of more automated instrumentation provided by the tracer SDK. In this case, this Lambda function inherits from *RequestHandler*, so we will have to use manual instrumentation.
{{% notice note %}}
Automatic tracer instrumentation only works with functions that inherit from *RequestStreamHandler*. It uses default configurations to manage the transaction, handle correlation, and report errors. See [the documentation](https://docs.appdynamics.com/latest/en/application-monitoring/install-app-server-agents/serverless-apm-for-aws-lambda/java-serverless-tracer) for more information on when automatic instrumentation can be leveraged.
{{% /notice %}}
Throughout this section, it is recommended to save **FrontEndHandler.java** periodically. When we make changes, we are going to approach changes in an atomic manner -- any resources that we open or begin (such as exit calls and transactions) will then be immediately closed or completed in the next step. The first thing we need to do is to import the appropriate tracer resources into the class. Locate the comment labeled `//TODO: import AppDynamics tracer classes` and add the following import statements:
``` java
import com.appdynamics.serverless.tracers.aws.api.AppDynamics;
import com.appdynamics.serverless.tracers.aws.api.Tracer;
import com.appdynamics.serverless.tracers.aws.api.Transaction;
import com.appdynamics.serverless.tracers.dependencies.com.google.gson.Gson;
import com.appdynamics.serverless.tracers.aws.api.ExitCall;
```
The beginning section of **FrontEndHandler.java** should now look like this:
``` java
package com.appdynamics.lambda;
//TODO: import AppDynamics tracer classes
import com.appdynamics.serverless.tracers.aws.api.AppDynamics;
import com.appdynamics.serverless.tracers.aws.api.Tracer;
import com.appdynamics.serverless.tracers.aws.api.Transaction;
import com.appdynamics.serverless.tracers.dependencies.com.google.gson.Gson;
import com.appdynamics.serverless.tracers.aws.api.ExitCall;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.amazonaws.services.lambda.AWSLambda;
import com.amazonaws.services.lambda.AWSLambdaClientBuilder;
import com.amazonaws.services.lambda.model.InvokeRequest;
import com.amazonaws.services.lambda.model.InvokeResult;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.appdynamics.lambda.dal.CommerceOrder;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.javafaker.Faker;
```
Next, we will add code for the AppDynamics tracer and transaction as well as an exit call to the other Lambda function. Within **FrontEndHandler.java**, locate the comment labeled `TODO: Add variables for the tracer and transaction` and declare the following variables beneath that comment:
``` java
Tracer tracer = null;
Transaction txn = null;
String correlationHeader = "";
```
These variables will contain the AppDynamics tracer, transaction, and correlation header. Next, locate the comment labeled `TODO: Add in code to build tracer.`. Underneath that comment, we're going to add the following block of code:
``` java
tracer = AppDynamics.getTracer(context);
if (input.containsKey(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY)) {
correlationHeader = input.get(Tracer.APPDYNAMICS_TRANSACTION_CORRELATION_HEADER_KEY).toString();
} else {
ObjectMapper m = new ObjectMapper();
Map headers = m.convertValue(input.get("headers"),new TypeReference