This page provides instructions and an overview of the GO SDK, which provides routines for creating and managing Business Transactions, Transaction Snapshots, backends, and exit calls in AppDynamics. 

Before You Begin

Before instrumenting your applications with the Go SDK, you will need the current version of the Go SDK. See Go Language Agent and Download AppDynamics Software to install the SDK.  

Import the AppDynamics Package to the Application

After downloading the SDK, you are ready to add AppDynamics instrumentation to your Go application. The first step is to import the AppDynamics package:

import appd "appdynamics"
CODE

Initialize the Controller Configuration

Controller information settings permit the SDK to connect to the Controller. Some settings are required for all applications while others are required only for certain types of application environments. For example, if the SDK needs to connect to the Controller via an internal proxy in your network, set up the connection settings for the proxy. See Go SDK Reference for a complete list of settings and which ones are required.

Assign values to the required settings in your application. For example, to set the Controller connection information:

cfg := appd.Config{}
 
cfg.AppName = "exampleapp"
cfg.TierName = "orderproc"
cfg.NodeName = "orderproc01"
cfg.Controller.Host = "my-appd-controller.example.org"
cfg.Controller.Port = 8090
cfg.Controller.UseSSL = false
cfg.Controller.Account = "customer1"
cfg.Controller.AccessKey = "secret"
cfg.InitTimeoutMs = 1000  // Wait up to 1s for initialization to finish
CPP


Notice the InitTimeoutMs field. Once you initialize the configuration, you pass the configuration object to the call to initialize the agent via 
InitSDK(). The InitTimeoutMs field can have these values:

  • When set to 0, the default, the InitSDK() function operates as an asynchronous action, so that the initialization call does not block your program. 
  • Setting the value to -1 instructs the program to wait indefinitely until the controller configuration is received by the agent, that is, the InitSDK() method returns control. This is useful when you want to capture short-running Business Transactions that occur at application startup and you do not mind the delay of waiting for the Controller to send the configuration. 
  • Alternatively, set it to a specific number of milliseconds to wait. 

If you use a multi-tenant Controller (SaaS or on-premises multi-tenant), you need to create the context for the multi-tenant environments using the AddAppContextToConfig() method. You can then pass the context as a parameter to methods for performing particular operations, such as starting a Business Transaction or adding custom metrics. See Go SDK Reference for AddAppContextToConfig() and related methods.

Initialize the Agent

Initialize the agent by passing the configuration structure to InitSDK() in your main function.

If InitSDK() returns nil, the agent is initialized successfully. If an error returns, it is likely because the agent could not reach the Controller.

For example, to initialize the SDK: 

if err := appd.InitSDK(&cfg); err != nil {
	fmt.Printf("Error initializing the AppDynamics SDK\n")
} else {
	fmt.Printf("Initialized AppDynamics SDK successfully\n")
}
CPP

Create Business Transactions

Define a Business Transaction by enclosing the code that constitutes the request you want to monitor between StartBT() and EndBT()calls. StartBT() 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 Go SDK Reference for GetExitcallCorrelationHeader(). If the transaction does not need to correlate with another transaction, pass an empty string 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 StoreBT(). Retrieve the handle from the global handle registry using GetBT().

For example, to set a Business Transaction:

// start the "Checkout" transaction
btHandle := appd.StartBT("Checkout", "")

// Optionally store the handle in the global registry
appd.StoreBT(btHandle, my_bt_guid)
... 

// Retrieve a stored handle from the global registry
myBtHandle = appd.GetBT(my_bt_guid)

// end the transaction
appd.EndBT(btHandle)
CPP

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 EndBT(), the agent stops reporting metrics for the business transaction.

Add Business Transaction Errors

Use AddBTError() 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 constants classifying the error level as APPD_LEVEL_NOTICEAPPD_LEVEL_WARNING or APPD_LEVEL_ERROR.

Manage Business Transaction Snapshots

The agent automatically creates Transaction Snapshots when monitoring a Business Transaction. Transaction snapshots are useful for troubleshooting poor performance because they describe instances of the business transaction at certain points in time. 

Other than creating the Business Transaction, you do not have to modify anything to create these snapshots, but you can add calls to:

  • Determine if a snapshot is being taken
  • Provide additional data in a snapshot
  • Set the URL for a snapshot

Determine if the Agent is Taking a Snapshot Now

Due to high cost, the agent does not constantly collect snapshots. By default, it collects a snapshot every ten minutes, but this schedule is configurable. See Configure Snapshot Periodic Collection Frequency.

You can determine if a snapshot is happening using IsBTSnapshotting(), which returns true if the agent is collecting a snapshot. This method avoids wasted overhead in collecting user data for a snapshot or setting the snapshot URL if no snapshots are being collected.

Add Business Transaction User Data

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 Controller UI, the data appears in the USER DATA tab of the transaction snapshot.

If a snapshot is occurring, use AddUserDataToBT() passing a key and value for the data that you want the snapshot to collect.

Add Snapshot URL

If a snapshot is occurring, you can set a URL for the current snapshot using SetBTURL().

Set Snapshot Example

func setSnapshotAttributes(bt appd.BtHandle, key, value string) {
	if appd.IsBTSnapshotting(bt) {
		appd.AddUserDataToBT(bt, key, value)
		appd.SetBTURL(bt, "user/login")
	}
}
CPP

Create Backends

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 registers them. Creating and adding the backend to the instrumented application involves:

  • Naming the backend
  • Setting its identifying properties
  • Optionally, configuring how the backend is presented in the Controller UI

Identifying Properties

A backend has identifying properties. These vary depending on the type of the backend and the types of information that you want to display. The Controller displays identifying properties in backend dashboards. You must set at least one identifying property for the type of any backend that you plan to add. 

The following shows the backend properties in the Controller UI for an Oracle database: 

Backend Properties

Resolve to a Tier

Backend Example

The following listing shows an example of setting up a database backend. 

backendName := "Cart Product Database"
backendType := "DB"
backendProperties := map[string]string {
	"DATABASE": "sqlite3",
}
resolveBackend := false
 
appd.AddBackend(backendName, backendType, backendProperties, resolveBackend)
CPP

Manage Exit Calls

When an application makes a call to another component, such as 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 StartExitCall() and EndExitcall() calls.  StartExitcall() 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 StoreExitcall(). Retrieve the handle from the global handle registry using GetExitcall().

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

Exit Calls

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

Simple Exit Call Example

// start the exit call to backendName
ecHandle := appd.StartExitcall(btHandle, backendName)

...

// optionally store the handle in the global registry
appd.StoreExitcall(ecHandle, my_ec_guid)

...
// retrieve a stored handle from the global registry
myEcHandle := appd.GetExitcall(my_ec_guid)
 
// set the exit call details
if err := appd.SetExitcallDetails(myEcHandle, "Exitcall Detail String"); err != nil {
	log.Print(err)
}

// add an error to the exit call
appd.AddExitcallError(myEcHandle, appd.APPD_LEVEL_ERROR, "exitcall error!", true)

// end the exit call
appd.EndExitcall(myEcHandle)
CPP

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 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. 

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 Header.Get() function, extract the header named APPD_CORRELATION_HEADER_NAME from the incoming HTTP payload.

  2. Pass the header to StartBT(). For example:

    hdr := req.Header.Get(appd.APPD_CORRELATION_HEADER_NAME)
    bt := appd.StartBT("Fraud Detection", hdr)
    CPP

If the header retrieved by the Header.Get() function is valid, the business transaction started by the StartBT() 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 GetExitcallCorrelationHeader() 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:

    inventoryEcHandle := appd.StartExitcall(btHandle, "Inventory DB")
    hdr := appd.GetExitcallCorrelationHeader(inventoryEcHandle)
     
    client := &http.Client{
    	CheckRedirect: redirectPolicyFunc,
    }
    
    req, err := http.NewRequest("POST", "https://inventory/holds/xyz", nil)
    // ...
    req.Header.Add(appd.APPD_CORRELATION_HEADER_NAME, hdr)
    resp, err := client.Do(req)
    // ...
    
    ...
    CPP

Terminate the Agent

Terminate the agent right before the application exits:

appd.TerminateSDK()
CPP