The following sections show you how to use the Xamarin SDK to customize your instrumentation.

Because the agent stores data about events in a local buffer before reporting the information, you are recommended to use the APIs with discretion.

Track Calls

You can instrument methods to see how often the instrumented a method is invoked and how long it takes to run. To do this, add a call at the beginning and end of the method you'd like to instrument.

In the example below, the code executed in the constructor for the class ShoppingCart will be tracked and reported. In your own code, start tracking calls by specifying the class and method in BeginCall and then complete the tracking and report the data by calling ReportCallEnded.

using AppDynamics.Agent;
...
public class ShoppingCart {
    public ShoppingCart() {
        
        // Code to create the shopping cart 
    }
    void CheckOut(int custId, int transactionId) {
      var tracker = Instrumentation.BeginCall("ShoppingCart", "CheckOut", custId, transactionId);
       // The code placed here will be tracked and reported.
       tracker.ReportCallEnded();
    }
}
C#

Timing Events

Sometimes you want to time an event in your application that spans multiple methods. You can do this by calling StartTimerWithName when the event starts, and then StopTimerWithName when it ends. For example, to track the time a user spends viewing a screen, the instrumentation might look something like the following:

using AppDynamics.Agent;
...
async private void StartCapturePreview_Click(object sender, RoutedEventArgs e) {
    capturePreview.Source = captureManager;
    Instrumentation.StartTimerWithName("CapturePreview");
    await captureManager.StartPreviewAsync();
}
async private void StopCapturePreview_Click(object sender, RoutedEventArgs e) {
    await captureManager.StopPreviewAsync();
    Instrumentation.StopTimerWithName("CapturePreview");
} 
C#

Report Metrics

To report other types of data, you can use a metric. The metric name should only contain alphanumeric characters and spaces. Illegal characters are replaced by their ASCII hex value. The metric value must be a long integer.

The snippet below shows how you might report a metric.

using AppDynamics.Agent;
...
Instrumentation.ReportMetricWithName("Database Rows", 5123);
C#

HTTP Requests

You can report a Network Request using the AppDynamics.Agent.HTTPRequestTracker class.

The following is an example of using HTTPRequestTracker with the System.Net.Http.HttpClient class. The tracker object synchronously captures and reports the network request as well as any network errors.

using AppDynamics.Agent;
...
public async Task<string> Fetch(Uri uri) {
  var client = new HttpClient();
  // Create AppDynamics Tracker
  var tracker = HTTPRequestTracker.Create(uri);
  // Add AppDynamics Server Correlation Headers
  foreach (var header in ServerCorrelationHeaders.Generate) {
      // Each header could have multiple values
      foreach (var value in header.Value) {
          client.DefaultRequestHeaders.Add(header.Key, value);
      }
  }
  HttpResponseMessage response = null;
  try {
      response = await client.GetAsync(uri);
  } catch (Exception ex) {
      // Capture any network errors.
      tracker.Exception = ex;
      tracker.ReportDone();
      throw ex; //you decide to throw it or not
  }
  if (!response.Equals(null)) {
      // Capture request information such as the 
      // status code, status message, and headers.
      tracker.ResponseCode = (int)response.StatusCode;
      tracker.StatusLine = response.ReasonPhrase;
      tracker.ResponseHeaderFields = response.Headers;
      tracker.ReportDone();
      return await response.Content.ReadAsStringAsync();
   }
   return null;
}
C#

Leave Breadcrumbs

You can leave breadcrumbs to mark interesting events. For example, if your application crashes, the breadcrumbs you left with be displayed in the crash report and could provide context. You can also configure the breadcrumb to appear in sessions.

The following is the method signature for leaving breadcrumbs:

static void AppDynamics.Agent.Instrumentation.LeaveBreadcrumb(string breadcrumb, BreadcrumbVisibility mode)
C#

You use the mode to set the visibility of the breadcrumb. The visibility defines where you will see the breadcrumb in the Controller UI. The value of mode can be one of the following:

  • BreadcrumbVisibility.CrashesOnly – The breadcrumb will only appear in crash snapshots.
  • BreadcrumbVisibility.CrashesAndSessions  – The breadcrumb will appear in crash snapshots and sessions.

Thus, you would use the method below to set breadcrumbs that are only reported in crash reports:

using AppDynamics.Agent;
...
Instrumentation.LeaveBreadcrumb("GetUserInfo", BreadcrumbVisibility.CrashesOnly);
C#

If you would like to see the breadcrumb in crash reports and sessions: 

using AppDynamics.Agent;
...
Instrumentation.LeaveBreadcrumb("GetUserInfo", BreadcrumbVisibility.CrashesAndSessions);
C#

Disable the Agent to Stop Sending User Data to the Collector

You can disable the agent to stop sending all data to the collector while the agent is initialized and running. For example, you can disable the agent if your app has an option for users to opt-out of monitoring for privacy reasons.

shutdownAgent

The shutdownAgent call stops outgoing data to the collector, and does not persist data on the device.

using AppDynamics.Agent; 
...
Instrumentation.shutdownAgent();
C#


  • The call only stops the traffic out of the agent.
  • Once the agent has been initialized, the call cannot be removed, and a license will have been consumed.
  • If you want to make this state permanent for a device, add code in UserDefaults to save the state and use that flag to conditionally initialize the agent in your code.

restartAgent

To re-enable the agent and reverse shutdownAgent, use restartAgent.

using AppDynamics.Agent; 
...
Instrumentation.restartAgent();
C#


  • This call will respect the server side calls that can remotely shutdown the agent in a similar way. 
  • The call is only in effect while the app is running.
  • The call will be ignored if the agent has been remotely disabled.
  • If the call is removed from memory and the app restarts, or the device is rebooted, the agent will be initialized as

Report Errors and Exceptions

You can report exceptions using the method reportError from the Instrumentation class. Reported exceptions will appear in session details.

You can also set one of the severity levels below for an issue. With the severity level, you can filter errors in the Code Issues Dashboard or Code Issues Analyze.

  • ErrorSeverityLevel.INFO
  • ErrorSeverityLevel.WARNING
  • ErrorSeverityLevel.CRITICAL

The example below uses the API to report possible exceptions and sets the severity level to ErrorSeverityLevel.CRITICAL (critical) when writing to a file


using AppDynamics.Agent;
...
try {
    // possible exception //
}
catch (Exception e){
    Instrumentation.ReportError(exception, ErrorSeverityLevel.CRITICAL);
}
XML

Report Aggregate Exceptions as Crashes

You can configure the Xamarin Agent to report aggregate exceptions (handled and unhandled) as crashes by setting the boolean property EnableAggregateExceptionHandling to true. When the property is set to false, only unhandled exceptions are reported. The default value is false.

The following code example configures the Xamarin Agent to report aggregate exceptions (handled and unhandled) as crashes.

using AppDynamics.Agent;
...
var config = AppDynamics.Agent.AgentConfiguration.Create(<EUM_APP_KEY>);
AppDynamics.Agent.Instrumentation.EnableAggregateExceptionHandling = true;
AppDynamics.Agent.Instrumentation.InitWithConfiguration(config);
...
C#

Disable Crash Reporting

Crash reporting is enabled by default, but you can manually disable crash reporting through the instrumentation configuration. If you are using other crash reporting tools, you might disable crash reporting to minimize conflicts and optimize the crash report results. 

You can disable crash reporting by configuring the instrumentation with the crashReportingEnabled property as shown in the following:

import { Instrumentation } from '@appdynamics/xamarin-agent';

Instrumentation.start({
        appKey: <#EUM_APP_KEY#>,
        crashReportingEnabled: false
})

Programmatically Control Sessions 

By default, a mobile session ends after a period of user inactivity. For example, when a user opens your application, the session begins and only ends after the user stops using the app for a set period of time. When the user begins to use the application again, a new session begins. 

Instead of having a period of inactivity to define the duration of a session, however, you can use the following API to programmatically control when sessions begin and end:


static void AppDynamics.Agent.Instrumentation.StartNextSession()
C#

When you call the method StartNextSession, the current session ends and a new session begins. The API enables you to define and frame your sessions so that they align more closely with business goals and expected user flows. For example, you could use the API to define a session that tracks a purchase of a product or registers a new user. 

Excessive use of this API will cause sessions to be throttled (excessive use is > 10 calls per minute per Xamarin Agent, but is subject to change). When not using the API, sessions will fall back to the default of ending after a period of user inactivity.  

Example of a Programmatically Controlled Session

In the example below, the current session ends and a new one begins when an item is bought.

using AppDynamics.Agent;
...
public async Task BuySaleItemAsync(SaleItem item)
{
    try 
    {
        bool buySucceeded = await this.MobileService.InvokeApiAsync<SaleItem, bool>("buy", item);
        if (buySucceeded)
        {
            await UserDialogs.Instance.AlertAsync("Thanks for buying this item");
            Instrumentation.StartNextSession();
        }
    }
    catch (Exception e)
    {
        Debug.WriteLine(@"Unexpected error {0}", e.Message);
    }
}
C#

Start and End Session Frames

You can use the ISessionFrame API to create session frames that will appear in the session activity. Session frames provide context for what the user is doing during a session. With the API, you can improve the names of user screens and chronicle user flows within a business context. 

Use Cases

The following are common use cases for the ISessionFrame API:

  • One screen performs multiple functions and you want more granular tracking of the individual functions.
  • A user flow spans multiple screens or user interactions. For example, you could use the API to create the session frames "Login", "Product Selection", and "Purchase" to chronicle the user flow for purchases.
  • You want to capture dynamic information based on user interactions to name session frames, such as an order ID.

ISessionFrame API

The table below lists the two methods and one property you can use with session frames. In short, you start a session frame with StartSessionFrame and then use the returned ISessionFrame object to rename and end the session frame. 

ClassMethod/PropertyDescription
Instrument

Method:

static ISessionFrame StartSessionFrame(string sessionFrameName)
C#

Use this to start and name your session frame.
Naming session frames enables you to easily identify and track the frames in the Sessions Details dialog.

ISessionFrame

Property:

string Name
C#

Rename the session frame name.
You assign the updated session frame name with this property from the ISessionFrame object returned from StartSessionFrame.

ISessionFrame

Method:

static void End()
C#

End the session frame.
You call this method from the ISessionFrame object returned from StartSessionFrame.

Session Frame Example

In the following example, the ISessionFrame API is used to track user activity during the checkout process.

using AppDynamics.Agent;
...
 
namespace ShoppingApp {
    public partial class ShoppingCart : ContentPage {
        private ISessionFrame sessionFrame;
        private string orderId;
        ...
        void checkoutCartButtonClicked(object sender, EventArgs e) {
            // The checkout starts when the user clicks the checkout button.
            // This may be after they have updated quantities of items in their cart, etc.
            sessionFrame = Instrumentation.StartSessionFrame("Checkout");
        }
        void confirmOrderButtonClicked(object sender, EventArgs e) {
            // Once they have confirmed payment info and shipping information, and they
            // are clicking the "Confirm" button to start the backend process of checking out,
            // we may know more information about the order itself, such as an order ID.
            sessionFrame.Name = $"Checkout: Order ID {this.orderId}";
        }
        void processOrderCompleted(object sender, EventArgs e) {
            // Once the order is processed, the user is done "checking out" so we end
            // the session frame.
            sessionFrame.End();
        }
        void checkoutCancelled(object sender, EventArgs e) {
            // If they cancel or go back, you'll want to end the session frame also, or else
            // it will be left open and appear to have never ended.
            sessionFrame.End();
        }
    }
}
CPP

Add User Data

You can set a key/value pair of strings to record important events or information. Below is the method signature for setting user data:


static void AppDynamics.Agent.Instrumentation.SetUserData(string key, string value)
C#

For example, you might want to log the user ID when the method for logging in the user is called:

using AppDynamics.Agent;
...
void LogInUser(UserCredentials) {
   // Log in user
   ...
   // Set user data with the user name.
   Instrumentation.SetUserData("user_id", UserCredentials.ID);
}
C#

This information is available in Network Request Analyze and is added to any crash snapshots that may be taken. Keys and values are limited to 2048 characters each.

You can also set user data with values of other types (long, boolean, double, DateTime) using the following methods:

To remove user data, use the following methods:

Set the Logging Level (Optional)

You can set the logging level with the configuration LoggingLevel as part of the class AgentConfiguration.

You can set LoggingLevel to one of the levels listed in the table below.

LevelDescription
Off Agent will emit no messages at all.
Error Only show errors and initial banner.
This is the default.
Warn Warning level messages and above.
Info Information level messages and above
May be useful to the developer.
Debug Debug level messages and above.
Useful for support personnel and developers.
Verbose 

Verbose level messages and above.

Use verbose logging only for troubleshooting. Be sure to disable for production.

All All messages.

For example:

var config = AppDynamics.Agent.AgentConfiguration.Create("<#Your App Key#>");
config.LoggingLevel = AppDynamics.Agent.LoggingLevel.All;
AppDynamics.Agent.Instrumentation.InitWithConfiguration(config); 
C#

Xamarin SDK Documentation

For the complete SDK API documentation, see the latest Xamarin SDK documentation or the previous versions listed below: