These are the tasks your application needs to perform to get instrumented:
After downloading the SDK, you're ready to add AppDynamics instrumentation to your C/C++ application. The first step is to include the AppDynamics header file at the top of your
main function file:
Controller information settings permit the agent to connect to the Controller. Some settings are required for all applications, while others are needed only for certain types of application environments. For example, if the agent needs to connect to the Controller via an internal proxy in your network, you need to set up the connection settings for the proxy.
See Agent Configuration Settings in C/C++ Agent SDK Reference for a complete list of the settings and information about which ones are required.
In your application, assign values to the required settings. For example, to set the Controller connection information:
appd_config struct with the controller settings. For example:
main function, call these initialization functions:
appd_sdk_init() returns zero, the agent is initialized successfully. Non-zero indicates failure, probably because the agent could not reach the Controller.
The following example illustrates how to initialize the SDK:
It can take several minutes after the agent is initailized before all the business transactions and metrics appear in the Controller.
Define a business transaction by enclosing the code that constitutes the request that you want to monitor between
appd_bt_begin() returns a handle to use in subsequent routines that affect that business transaction.
If you are creating a business transaction that correlates with an upstream business transaction, pass the correlation header of the upstream transaction so the new transaction that you are creating can correlate with it. See
appd_exitcall_get_correlation_header()in the C/C++ Agent SDK Reference. If the transaction does not need to correlate with another transaction, pass
NULL for the correlation header parameter.
You can optionally store the business transaction handle in the global handle registry with a guid for easy retrieval later using
appd_bt_store(). Retrieve the handle from the global handle registry
The following shows an example of setting a business transaction:
Between starting and ending the transaction, you can perform operations such as adding errors to the business transaction, defining the transaction snapshot attributes, adding backends and exit calls, and so on.
When the business transaction ends, via a call to
appd_bt_end(), the agent stops reporting metrics for the business transaction.
appd_bt_add_error() to report business transaction errors. If you set this function's
markBTAsError parameter, the transaction is reported as an error transaction when the error occurs.
The SDK provides an
enum to classify the error level as APPD_LEVEL_NOTICE, APPD_LEVEL_WARNING or APPD_LEVEL_ERROR.
When the agent is monitoring a business transaction, it automatically creates transaction snapshots, which describe instances of the business transaction at certain points in time. Transaction snapshots are extremely useful for troubleshooting poor performance because they contain a lot of detail.
You do not have to modify anything to create these snapshots, other than create the business transaction, but you can add calls to:
The agent is not always collecting snapshots, because that would be expensive. By default, it collects a snapshot every ten minutes, but this schedule is configurable. See Configure Snapshot Periodic Collection Frequency in Transaction Snapshots for information about the frequency.
You can determine if a snapshot is happening using
appd_bt_is_snapshotting(), which returns non-zero if the agent is collecting a snapshot. The main reason to do this is to avoid the wasted overhead for collecting user data for a snapshot or setting the snapshot URL if no snapshot is currently being collected.
You can optionally add data to transaction snapshots. For example, you might want to know which users are getting a lot of errors, or from which regions users are experiencing slow response times, or which methods are slow. In the AppDynamics UI, the data appears in the USER DATA tab of the transaction snapshot.
If a snapshot is occurring, use
appd_bt_add_user_data() passing a key and value for the data that you want the snapshot to collect.
A snapshot URL lets Controller users share a snapshot with others. You can set a URL for the current snapshot using
A backend is a database or a remote service such as a message queue, HTTP service or cache service that your application uses. A backend component is not itself monitored by the application agent, but the agent monitors calls to it from instrumented servers. You need to create backends in the instrumented environment so that the agent can discover them. This involves:
You must declare a backend using
appd_backend_declare() before the agent can detect it. After you declare a backend, you don't need to declare it again if the backend is used by other business transactions in a single SDK instance. A backend must be of one of the supported types listed under Exit Call Types in the Agent SDK for C and C++ Reference.
A backend also has identifying properties, which you set using
The following shows the backend properties in the Controller UI for an ActiveMQ:
After you declare and configure the backend, add it to the application so the agent can detect it.
The following listing shows an example of setting up a database backend.
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() 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 using
appd_exitcall_store(). Retrieve the handle from the global handle registry
Pass the business transaction handle and the destination backend to
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:
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.
A correlation header contains the information that enables the agents to continue the flow of a business transaction across multiple tiers.
An SDK agent can correlate with other SDK agents as well as other AppDynamics agents (such as Java, .NET, or PHP) that perform automatic correlation for certain types of entry and exit points.
When your instrumented process receives a continuing transaction from an upstream agent that supports automatic correlation:
Using a third-party
http_get_header() function, extract the header named
APPD_CORRELATION_HEADER_NAME from the incoming HTTP payload.
Pass the header to
appd_bt_begin(). For example:
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.
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:
APPD_CORRELATION_HEADER_NAMEwith the value of the correlation header retrieved in step 3 into the outgoing payload of the HTTP request.
Make the request. For example:
The following example uses the cURL library to correlate with a downstream transaction.
You can create custom metrics with the C/C++ SDK. Custom metrics supplement the built-in metrics you get with the C/C++ agent, such as the BT call count and response time.
To create custom metrics, you use two calls in the API:
You use the
appd_custom_metric_add() to declare a metric. The method signature is:
The following example illustrates a call that uses this method:
As shown, the method passes an application context for the metric, the name of the metric ("Total Memory Usage", in the example), and the path to the metric in the Metric Browser tree (Custom Metrics > Memory). The other parameters define how the metric is processed by the Controller.
With the metric declared, your code can then report data to the metric with the
appd_custom_metric_report() method, as follows:
The Controller applies some standard processing functions to custom metric values just as it does to built-in metrics. These functions define, for example, how the metric is rolled up over time. The manner in which the Controller should process a custom metric depends on the nature of that metric. For instance, for a metric representing the state of the machine, it may make sense to roll up the value to the last observed value for the metric. For a call rate metric, it may make sense to roll the metric up to an average value.
The following sections provide more information on the parameters you can use to define metric handling by the Controller.
time_rollup_type parameter tells the Controller how to roll up values for the metric over time. There are three ways in which the Controller can roll up metrics, as follows:
appd_cluster_rollup_type parameter tells the Controller how to aggregate metric values for the tier (a cluster of nodes).
A particular metric may not report data for a given minute. The
appd_hole_handling_type parameter tells the Controller how to set the metric's count for that time slice. The count is set to zero if the hole handling type is REGULAR_COUNTER, and set to one if RATE_COUNTER. In effect, REGULAR_COUNTER does not affect aggregation while RATE_COUNTER does.
For example, consider four time slices with the data 9, 3, 0, 12. Notice that the third time slice is zero filled, with no metric being reported for that time slice. The sum of the values is 9+3+0+12 = 24.
If the metric is REGULAR_COUNTER, the count for the third times slice would be zero, and therefore the overall count would be 1+1+0+1 = 3. If the metric is RATE_COUNTER the overall count would be 1+1+1+1 = 4. In the case of the REGULAR_COUNTER, the average would be 24/3 = 8, while for the RATE_COUNTER the average would be 24/4 = 6.
Built-in metrics that use the regular counter hole-handling type include Average Response Time, Average CPU Used, Number of Stalls. Built-in metrics that use the rate counter hole-handling type include BT Calls per minute and Error per minute.
For C++ applications, you can use the
ExitCall classes to simplify your instrumentation.
The advantage of using these classes is that you do not need to manually call
appd_exitcall_end(). When the BT or ExitCall object goes out of scope, the SDK calls its destructor and the business transaction or exit call automatically ends.
For example, the following code using these classes:
is the equivalent of this:
When the BT lifetime depends on the nondeterministic lifetimes of other objects, you can use a shared pointer to a BT to keep the BT alive for the lifetimes of its dependencies. In this case the BT ends when the last reference to it ends. For example:
For managing exit calls with complex lifetimes, consider using smart pointers
Just before the application exits, terminate the agent.