Download PDF
Download page Customize the .NET MAUI Instrumentation.
Customize the .NET MAUI Instrumentation
Once your application is instrumented with the MAUI Agent, you can make further customizations to the agent instrumentation using the MAUI SDK. The SDK has additional classes to allow you to extend the kinds of application data you can collect and report to AppDynamics. See the sections below for customization instructions.
Customize Automatic Instrumentation
You can customize automatic instrumentation of the following:
- Automatic Network Request Instrumentation
- Automatic Page Tracking Instrumentation
- Automatic UI Tracking Instrumentation
Before you Begin
Make sure you have the AppDynamics.Agent.AutoInstrument.Fody
package added to your project. See Set Up Automatic Network Request Instrumentation.
Customize Automatic Network Request Instrumentation
When automatic network request instrumentation is enabled, the weaver will automatically attach instrumentation code over HttpClient or Refit usages.
You can further customize the automatic instrumentation at the project level or class level (see sections below). For example, you could:
Enable the automatic instrumentation at a project level from the
FodyWeavers.xml
file, but exclude some files at the class level using theDisableNetworkInstrumentation
attribute.Disable the automatic instrumentation at a project level from the
FodyWeavers.xml
file, but include some files at the class level using theEnableNetworkInstrumentation
attribute.
If you are using semi-automatic network request tracking via the HttpRequestTrackerHandler
, the network request will not be reported twice.
Enable/Disable at the Project Level
You can enable or disable automatic instrumentation at the project level using the NetworkInstrumentationEnabled
flag in the FodyWeavers.xml
file.
For example, to enable automatic instrumentation, set NetworkInstrumentationEnabled
to "true"
:
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
... Existing weavers ...
<AppDynamics.Agent.AutoInstrument NetworkInstrumentationEnabled="true"/>
</Weavers>
Enable/Disable at the Class Level
You can enable or disable automatic instrumentation at the class level by using one of the following attributes per class:
[EnableNetworkInstrumentation]
[EnableNetworkInstrumentation] public class MyClass { ... }
C#[DisableNetworkInstrumentation]
[DisableNetworkInstrumentation] public class MyClass { ... }
C#
Recommendations
If you are using manual network request tracking, you will see duplicate entries for the same network request. To avoid this, you can either remove the manual instrumentation or use the
DisableNetworkInstrumentation
attribute on that class.- If your HTTP requests are handled in a different project, you should add both the
AppDynamics.Agent
andAppDynamics.Agent.AutoInstrument.Fody
to that project as well for instrumentation to work. - If you are using a
HttpClient
instance generated in another library, you should only create and use the instance within the same project for instrumentation to work. Automatic instrumentation works by targeting new HttpClient instances within the project.
Customize Automatic Page Tracking Instrumentation
When automatic page tracking instrumentation is enabled, the weaver will search the project for all instances of Microsoft.Maui.Controls.Page in the project and inject the instrumentation code.
Enable/Disable at the Project Level
You can enable or disable automatic Page Tracking instrumentation at the project level using the PageTrackingInstrumentationEnabled
flag in the FodyWeavers.xml
file:
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
... Existing weavers ...
<AppDynamics.Agent.AutoInstrument PageTrackingInstrumentationEnabled="true"/>
</Weavers>
Enable/Disable at the Class Level
You can enable or disable automatic instrumentation at the class level by using one of the following attributes per class:
[EnablePageTracking]
[EnablePageTracking] public class MyPage : ContentPage { ... }
C#[DisableUITRacking]
[DisablePageTracking] public class MyPage : ContentPage { ... }
C#
Automatic UI Tracking Instrumentation
When automatic UI tracking instrumentation is enabled, the weaver will search the project for all instances of Button
, Entry
and ListView
in the project and inject the instrumentation code.
Enable/Disable at the Project Level
You can enable or disable automatic instrumentation at the project level using the UITrackingInstrumentationEnabled
flag in the FodyWeavers.xml
file.
For example:
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
... Existing weavers ...
<AppDynamics.Agent.AutoInstrument UITrackingInstrumentationEnabled="true"/>
</Weavers>
Enable/Disable at the Class Level
You can enable or disable automatic instrumentation at the class level by using one of the following attributes per class:
[EnableUITracking]
[EnableUITracking] public class MyPage : ContentPage { ... }
C#[DisableUITRacking]
[DisableUITracking] public class MyPage : ContentPage { ... }
C#
Automatic UI Tracking and XAML
Automatic UI Tracking works with both XAML and code-behind UI elements. But even though code-behind UIs are automatically instrumented, there's a required extra step to auto-instrument XAML. Add the following configuration to your .csproj
file:
<PropertyGroup>
<FodyDependsOnTargets>
XamlC
</FodyDependsOnTargets>
</PropertyGroup>
Automatic UI Tracking only works with pre-compiled XAML, so you will need to use XamlCompilationOptions.Compile
:
[XamlCompilation(XamlCompilationOptions.Compile)]
See XAML Compilation for more information.
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();
}
}
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");
}
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);
Add Tracking to HTTP Requests
Semi-automatic HTTP Tracking
The HttpMessageHandler
handles all the tracking and error handling. It can also include other inner handlers if you are already using a custom HttpMessageHandler
for other purposes, such as for logging.
To add semi-automatic tracking, instantiate a HttpClient
and pass the HttpRequestTrackerHandler
:
var client = new HttpClient(new HttpRequestTrackerHandler());
Then, all the requests sent using the client will be already instrumented:
response = await client.GetAsync(uri);
If you already have HttpMessageHandler
passed to the HttpClient
(for example, adding a logging handler), you must instantiate HttpRequestTrackerHandler
and pass the existing handler to the constructor:
var loggingHandler = new MyLoggingHandler();
var client = new HttpClient(new HttpRequestTrackerHandler(loggingHandler));
Manual HTTP Tracking
You can manually report a network request using the AppDynamics.Agent.HttpRequestTracker
class.
The example below uses 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;
}
Attach a Custom User Data Property to a Network Request
You can attach a custom user data property to a specific network request by adding user data to HttpRequestTracker
.
public HttpRequestTracker withUserData(String key, String value)
public HttpRequestTracker withUserLong(String key, Long value)
public HttpRequestTracker withUserBoolean(String key, Boolean value)
public HttpRequestTracker withUserDouble(String key, Double value)
public HttpRequestTracker withUserDate(String key, Date value)
Example
public byte[] sendRequest(URL url) throws HttpException {
HttpRequestTracker tracker = Instrumentation.beginHttpRequest(url);
try {
// implementation omitted
tracker.withResponseCode(theResponseCode)
.withResponseHeaderFields(theResponseHeaderFields)
.withUserData("key", "value")
.withUserLong("number", 100)
.withUserBoolean("boolean", true)
.withUserDouble("double", 1.1234)
.withUserDate("date", 1609488000)
.reportDone();
return responseBody;
} catch (UnderlyingException e) {
tracker.withException(e)
.reportDone();
throw new HttpException(e);
}
}
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)
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);
If you would like to see the breadcrumb in crash reports and sessions:
using AppDynamics.Agent;
...
Instrumentation.LeaveBreadcrumb("GetUserInfo", BreadcrumbVisibility.CrashesAndSessions);
Change the App Key
You can use the .NET MAUI Agent API to dynamically change the EUM app key. You receive the EUM App Key when creating a mobile app in the Controller UI. See Set Up and Access Mobile RUM for information about getting the EUM App Key.
The API to change app keys is available through the Instrumentation
class.
Instrumentation.ChangeAppKey("NEW-APP-KEY");
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();
- 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();
- 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);
}
Report Aggregate Exceptions as Crashes
You can configure the .NET MAUI 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 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);
...
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:
var config = AgentConfiguration.Create(<EUM_APP_KEY>);
config.CrashReportingEnabled = false;
Instrumentation.InitWithConfiguration(config);
Add a Crash Reporting Callback
You may want to make crash report information (that the Agent collects) available to other parts of your code, such as to Google Analytics. To enable passing on summary crash information, you can set up a crash report runtime callback:
To get a callback when the Agent detects and then reports a crash, subscribe to the following event that is a part of the IAgentConfiguration interface:
event EventHandler<IEnumerable<CrashReportSummary>> OnCrash;
C#The
OnCrash
event is raised during the next initialization of the Agent after a crash has occurred. This event is raised on your app's UI thread, so any work should be done on a separate work thread.The Agent sends a collection of crash report summaries instead of an individual callback in the event that there is more than one crash, producing multiple crash report summaries. Each
CrashReportSummary
has the following properties:ExceptionName
: useful for quick identification of the crashExceptionReason
: useful for quick identification of the crashExceptionId
: useful to look up the crash in the Controller UI
If you are sending the information to another analytics tool, such as Google Analytics, we recommend to include all three properties:
public class CrashReportSummary { public string ExceptionId { get; } public string ExceptionName { get; } public string ExceptionReason { get; } }
C#
Example
For example, to print the crash information to the console, you could subscribe to the OnCrash
event like this:
IAgentConfiguration config = AgentConfiguration.Create(appKey);
config.OnCrash += (sender, crashReportSummaries) =>
{
foreach (var crashReportSummary in crashReportSummaries) {
Console.WriteLine($"Crash Detected: {crashReportSummary.ExceptionName}: {crashReportSummary.ExceptionReason} ({crashReportSummary.ExceptionId})");
}
};
Instrumentation.InitWithConfiguration(config);
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()
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 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);
}
}
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.
Class | Method/Property | Description |
---|---|---|
Instrument | Method:
C#
| Use this to start and name your session frame. |
ISessionFrame | Property:
C#
| Rename the session frame name. |
ISessionFrame | Method:
C#
| End the session frame. |
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();
}
}
}
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)
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);
}
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 IAgentConfiguration.
You can set LoggingLevel
to one of the levels listed in the table below.
Level | Description |
---|---|
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);
Transform URLs for Network Requests
Implement the Network Request Callback
The callback that modifies or ignore specific URLs should be assigned to the Func
delegate below.
The callback method OnNetworkRequest
is synchronous, so we recommend that you return from the function quickly.
public Func<IHttpRequestTracker, bool> OnNetworkRequest { get; set; }
Transforming URLs
To transform URLs, the OnNetworkRequest
method should:
Identify specific URLs using techniques such as regex or pattern matching.
This first step is optional because you can choose to transform the URLs of all network requests.
- Modify the URL property of the
IHttpRequestTracker
object. - Assign a valid URL to the
url
property. Modifying other properties of theIHttpRequestTracker
object will be ignored. - Return
true
.
For example:
public static bool NetworkRequestCallback(IHttpRequestTracker tracker)
{
var maskUrl = new Uri("http://networkrequest-mask.com/");
tracker.Uri = maskUrl;
return true;
}
Transforming Sensitive URLs
You may want to identify and transform URLs that contain sensitive information.
For example:
public static bool NetworkRequestCallback(IHttpRequestTracker tracker)
{
var urlString = tracker.Uri.ToString();
if (urlString.Contains("accountInfo"))
{
tracker.Uri = new Uri("http://customer-account.com/");
}
return true;
}
Ignoring URLs
If the onNetworkReques
t method returns false
, the beacon is dropped. Generally, the process for ignoring beacons is:
- Identify specific URLs using techniques such as regex or pattern matching.
- Return
false
.
To ignore specific URLs, you would identify network requests that you didn't want to monitor and return false
to ignore the network request.
For example:
public static bool NetworkRequestCallback(IHttpRequestTracker tracker)
{
if (tracker.Uri.ToString().Contains("avatar"))
{
//ignore calls for avatars
return false;
}
return true;
}
To ignore all network requests, implement the following:
public static bool NetworkRequestCallback(IHttpRequestTracker tracker)
{
return false;
}
Register a Network Request Callback
To register a network request callback:
Define your own method to handle the callback:
public static bool NetworkRequestCallback(IHttpRequestTracker tracker) { return true; }
C#Pass it during the
AgentConfiguration
initialization phase:IAgentConfiguration config = AgentConfiguration.Create(appKey); config.OnNetworkRequest += NetworkRequestCallback; //Register the Callback Instrumentation.InitWithConfiguration(config);
C#Or you can use an anonymous function:
IAgentConfiguration config = AgentConfiguration.Create(appKey); config.OnNetworkRequest += (IHttpRequestTracker tracker) => { return true; }; Instrumentation.InitWithConfiguration(config);
C#
Configure and Take Screenshots
By default, mobile screenshots are enabled on the agent-side but disabled on the Controller-side. These screenshots appear in the Controller in the Sessions Details dialog. To programmatically take manual screenshots, you must enable screenshots in the Controller UI and add the Screenshot API below.
Instrumentation.TakeScreenshot();Disable Screenshots
The takeScreenshot()
function limits screenshots to a maximum of 1 screenshot per 10 seconds.
Disable Screenshots
You can disable screenshots from the Controller UI or with the Agent. To disable screenshots with the Agent, set the property ScreenshotsEnabled
of the IAgentConfiguration
object to false
:
IAgentConfiguration config = AgentConfiguration.Create(appKey); config.ScreenshotsEnabled = false; Instrumentation.InitWithConfiguration(config);
Block and Unblock Screenshots
You can also use the Agent to block screenshots from being taken during the execution of a code block. This just temporarily blocks screenshots from being taken until you unblock screenshots. This enables you to stop taking screenshots in situations where users are entering personal data, such as on login and account screens.
The Instrumentation class provides the methods blockScreenshots()
and unblockScreenshots()
to block and unblock screenshots.
If screenshots are disabled through the property ScreenshotsEnabled
of the IAgentConfiguration
object or through the Controller UI, these methods have no effect. You can also check the Instrumentation.ScreenshotsBlocked
property to check if screenshots are being blocked.
public void LoginUser()
{
if (!Instrumentation.ScreenshotsBlocked)
{
Instrumentation.BlockScreenshots();
}
LoginCredentials credentials = UserLogin.GetCredentials();
if (credentials.Authorized)
{
RedirectToProfile(credentials.user);
Instrumentation.UnblockScreenshots();
}
}
WebView Instrumentation (JavaScript Agent Injection)
WebView Instrumentation automatically injects our Javascript Agent into your WebViews, so that WebView navigation can also be instrumented. By default, Ajax calls are disabled, however, both WebView instrumentation, and Ajax instrumentation can be configured using the properties JsAgentEnabled
and JsAgentAjaxEnabled
:
Example
var config = AppDynamics.Agent.AgentConfiguration.Create("<#Your App Key#>");
config.JsAgentEnabled = true;
config.JsAgentAjaxEnabled = false;
AppDynamics.Agent.Instrumentation.InitWithConfiguration(config);
MAUI Specific Instrumentation
You can instrument MAUI elements using AppDynamics.Agent.Maui. To add the NuGet package, see Monitor .NET MAUI Applications.
Page Tracking
Note: This can be automatically instrumented. Check the Automatic Page Tracking section.
Using the MAUI agent, you can track page usage and see the how your users interact with the app in the session timeline.
To track pages, you must call TrackPage
from the constructor on each page you want to monitor.
public partial class MyPage : ContentPage
{
public MyPage()
{
InitializeComponent();
AppDynamics.Agent.Maui.PageTracker.TrackPage(this);
}
}
Track UI Elements
Note: This can be automatically instrumented. Check the Automatic UI Tracking section.
You can track user interactions with these Ul elements:
- Buttons
- Entries
- ListViews
To instrument a UI element:
Attach a property to your views:
appd:UiInstrumentation.IsInstrumented="True"
C#Include the namespace:
xmlns:appd="clr-namespace:AppDynamics.Agent.Maui;assembly=AppDynamics.Agent.Maui"
C#
Example
Example of a xaml
file with instrumented UI elements:
<ContentPage
xmlns:appd="clr-namespace:AppDynamics.Agent.Maui;assembly=AppDynamics.Agent.Maui" >
<StackLayout>
<Button
appd:UiInstrumentation.IsInstrumented="True"
Clicked="OnButtonClicked" />
<Entry
appd:UiInstrumentation.IsInstrumented="True" />
<ListView
appd:UiInstrumentation.IsInstrumented="True">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item l</x:String>
<x:String>Item 2</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</ContentPage>
You can also instrument properties from code behind (i.e. in the xaml.cs file):
using AppDynamics.Agent.Maui;
...
var button = new Button();
button.SetValue(UiInstrumentation.IsInstrumentedProperty, true);
The IsInstrumented
property will track the following events:
- Button - Button clicked
- ListView - Item selected
- Entry - Entry focused and entry unfocused
MAUI SDK Documentation
For the complete SDK API documentation, see the latest MAUI SDK documentation.