Manage Exit Calls

When an application makes a call to another component, a detected backend or another application server, the agent reports metrics on those calls.

Define an exit call by enclosing the code that constitutes the exit call between appd_exitcall_begin() and appd_exitcall_end() calls. appd_exitcall_begin() returns a handle to use in subsequent routines that affect that exit call. An exit call occurs in the context of a business transaction.

You can optionally store the exit call handle in the global handle registry with a guid for easy retrieval later with appd_exitcall_store(). Retrieve the handle from the global handle registry with appd_exitcall_get().

Pass the business transaction handle and the destination backend to appd_exitcall_end().

You can optionally add details to an exit call as any arbitrary string. The details are reported in the exit call details in the transaction snapshots in the Controller UI:

Exit call details

You can also add errors to an exit call using appd_exitcall_add_error(). Use the enum for the error levels. You can also add an error message.

Simple Exit Call Example

// start the exit call to backendOne
appd_exitcall_handle ecHandle = appd_exitcall_begin(btHandle, backendOne);
...
// optionally store the handle in the global registry
appd_exitcall_store(ecHandle, my_ec_guid);
...
// retrieve a stored handle from the global registry
appd_exitcall_handle myEcHandle = appd_exitcall_get(my_ec_guid);
// set the exit call details
rc = appd_exitcall_set_details(ecHandle, "backend ONE");
if (rc) {
std:cerr << "Error: exitcall details1";
return -1;
}
// add an error to the exit call
appd_exitcall_add_error(ecHandle, APPD_LEVEL_ERROR, "exitcall1 error!", true);
// end the exit call
appd_exitcall_end(ecHandle)

Correlate with Other Business Transactions

A correlation header contains the information that enables the agents to continue the flow of a business transaction across multiple tiers.

An SDK can correlate with other SDKs as well as other Cisco AppDynamics agents such as Java, .NET or PHP, that perform automatic correlation for certain types of entry and exit points.

Correlate with an Upstream Tier

When your instrumented process receives a continuing transaction from an upstream agent that supports automatic correlation:

  1. Using a third-party http_get_header() function, extract the header named APPD_CORRELATION_HEADER_NAME from the incoming HTTP payload.
  2. Pass the header to appd_bt_begin().

    For example:

    const char* hdr = http_get_header(req, APPD_CORRELATION_HEADER_NAME);
    appd_bt_handle bt = appd_bt_begin("fraud detection", hdr);

If the header retrieved by the http_get_header() function is valid, the business transaction started by the appd_bt_begin() call will be a continuation of the business transaction started by the upstream service.

Correlate with a Downstream Tier

The downstream agent is watching for a correlation header named singularityheader in the HTTP payload.

If your SDK agent is making an exit call to a downstream agent that supports automatic correlation:

  1. Set the name of the correlation header using APPD_CORRELATION_HEADER_NAME .
  2. Begin the exit call.
  3. Retrieve the correlation header from the exit call using the appd_exitcall_get_correlation_header() function.
  4. Using third-party HTTP functions, prepare an HTTP POST request.
  5. Inject a header named APPD_CORRELATION_HEADER_NAME with the value of the correlation header retrieved in step 3 into the outgoing payload of the HTTP request.
  6. Make the request.

    For example:

    const char* const APPD_CORRELATION_HEADER_NAME = "singularityheader";
    appd_exitcall_handle inventory = appd_exitcall_begin(bt, "inventory");
    const char* hdr = appd_exitcall_get_correlation_header(inventory);
    http_request req;
    http_init(&req, HTTP_POST, "https: //inventory/holds/%s", sku);
    http_set_header(&req, APPD_CORRELATION_HEADER_NAME, hdr);
    http_perform(&req);
    ...

cURL Downstream Correlation Example

The following example uses the cURL library to correlate with a downstream transaction.

#include <curl/curl.h>
. . .
. . .
// get the correlation header into the response
class LibcurlURLGet
{
public:
LibcurlURLGet(const std::string& url) : url(url), curlHandle(NULL) {}
std::string GetResponse(const char* correlationHeader)
{
CURLcode res;
Response response;
curlHandle = curl_easy_init();
if (curlHandle)
{
curl_easy_setopt(curlHandle, CURLOPT_URL, url.c_str());
curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, WriteDataCallback);
curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, &response);
if(correlationHeader && strlen(correlationHeader))
{
// start new added code
std::string singularityHeader(APPD_CORRELATION_HEADER_NAME);
singularityHeader.append(": ");
singularityHeader.append(correlationHeader);
// end new added code
curl_slist* slistNewHeaders = 0;
slistNewHeaders = curl_slist_append(slistNewHeaders, correlationHeader);
curl_easy_setopt(curlHandle, CURLOPT_HTTPHEADER, slistNewHeaders);
}
res = curl_easy_perform(curlHandle);
if(res != CURLE_OK)
{
}
}
curl_easy_cleanup(curlHandle);
return response.GetResponseString();
}
private:
class Response
{
public:
std::string GetResponseString()
{
return sResponse;
}
void AppendResponse(void* ptr, size_t sizeBytes)
{
sResponse.append((char*)ptr, sizeBytes);
}
private:
std::string sResponse;
};
static size_t WriteDataCallback(void* ptr, size_t size, size_t nmemb, Response* response)
{
response->AppendResponse(ptr, size * nmemb);
return size * nmemb;
}
std::string url;
CURL* curlHandle;
};
...
// start an exit call from the current transaction
appd_exitcall_handle ecHandle1 = appd_exitcall_begin(btHandle1, tier2);
...
// before exiting get the correlation header
const char* corrHeader1 = appd_exitcall_get_correlation_header(ecHandle1);
// put the correlation in the HTTP response
std::string response = urlGet.GetResponse(corrHeader1);
...
// start the next business transaction to correlate with the previous one
appd_bt_handle btHandle = appd_bt_begin("Verify", response)