diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props
index 0d410cfca..e11014508 100644
--- a/src/Directory.Packages.props
+++ b/src/Directory.Packages.props
@@ -10,7 +10,7 @@
-
+
diff --git a/src/Splat.ApplicationInsights/ApplicationInsightsFeatureUsageTrackingSession.cs b/src/Splat.ApplicationInsights/ApplicationInsightsFeatureUsageTrackingSession.cs
index a0338423b..446248c38 100644
--- a/src/Splat.ApplicationInsights/ApplicationInsightsFeatureUsageTrackingSession.cs
+++ b/src/Splat.ApplicationInsights/ApplicationInsightsFeatureUsageTrackingSession.cs
@@ -20,13 +20,16 @@ namespace Splat.ApplicationInsights;
/// should be used on a single thread.
public sealed class ApplicationInsightsFeatureUsageTrackingSession : IFeatureUsageTrackingSession
{
+ ///
+ /// The Application Insights telemetry client used to send events and exceptions.
+ ///
private readonly TelemetryClient _telemetryClient;
///
/// Initializes a new instance of the class.
///
- /// The name of the feature.
- /// The Application Insights telemetry client instance to use.
+ /// The name of the feature being tracked.
+ /// The Application Insights telemetry client instance to use for sending telemetry data.
public ApplicationInsightsFeatureUsageTrackingSession(
string featureName,
TelemetryClient telemetryClient)
@@ -34,6 +37,13 @@ public ApplicationInsightsFeatureUsageTrackingSession(
{
}
+ ///
+ /// Initializes a new instance of the class
+ /// with a parent reference for sub-feature tracking.
+ ///
+ /// The name of the feature being tracked.
+ /// The unique identifier of the parent feature session, or if this is a top-level session.
+ /// The Application Insights telemetry client instance to use for sending telemetry data.
internal ApplicationInsightsFeatureUsageTrackingSession(
string featureName,
Guid parentReference,
@@ -75,6 +85,10 @@ public void OnException(Exception exception)
_telemetryClient.TrackException(telemetry);
}
+ ///
+ /// Tracks a feature usage event with the specified event name to Application Insights.
+ ///
+ /// The name of the event to track (e.g., "Feature Usage Start" or "Feature Usage End").
private void TrackEvent(string eventName)
{
var eventTelemetry = new EventTelemetry(eventName);
@@ -83,6 +97,11 @@ private void TrackEvent(string eventName)
_telemetryClient.TrackEvent(eventTelemetry);
}
+ ///
+ /// Populates the standard feature tracking properties on a telemetry item.
+ ///
+ /// The type of telemetry item that supports custom properties.
+ /// The telemetry item to populate with feature name, reference, and optional parent reference properties.
private void PrepareEventData(TTelemetry eventTelemetry)
where TTelemetry : ISupportProperties
{
diff --git a/src/Splat.ApplicationInsights/ApplicationInsightsViewTracking.cs b/src/Splat.ApplicationInsights/ApplicationInsightsViewTracking.cs
index e4676648d..2c44cb117 100644
--- a/src/Splat.ApplicationInsights/ApplicationInsightsViewTracking.cs
+++ b/src/Splat.ApplicationInsights/ApplicationInsightsViewTracking.cs
@@ -1,10 +1,9 @@
-// Copyright (c) 2026 ReactiveUI. All rights reserved.
+// Copyright (c) 2026 ReactiveUI. All rights reserved.
// Licensed to ReactiveUI under one or more agreements.
// ReactiveUI licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
using Microsoft.ApplicationInsights;
-using Microsoft.ApplicationInsights.DataContracts;
using Splat.ApplicationPerformanceMonitoring;
@@ -15,7 +14,8 @@ namespace Splat;
///
/// This class is typically used to integrate view navigation tracking into applications that utilize
/// Application Insights for telemetry. It implements the IViewTracking interface to standardize view tracking across
-/// different telemetry providers.
+/// different telemetry providers. In Application Insights v3, page views are tracked as custom events since the
+/// PageViewTelemetry type has been removed.
/// The Application Insights telemetry client used to send page view tracking data. Cannot be null.
public sealed class ApplicationInsightsViewTracking(TelemetryClient telemetryClient) : IViewTracking
{
@@ -23,17 +23,29 @@ public sealed class ApplicationInsightsViewTracking(TelemetryClient telemetryCli
/// Track a view navigation using just a name.
///
/// Name of the view.
- public void OnViewNavigation(string name) => telemetryClient.TrackPageView(name);
+ public void OnViewNavigation(string name) => OnViewNavigation(
+ name,
+ new Dictionary());
///
- /// Track a View Navigation with Extended Data.
+ /// Track a view navigation using name and extended properties.
///
- /// Telemetry data.
- public void OnViewNavigation(PageViewTelemetry telemetry)
+ ///
+ /// See https://github.com/microsoft/ApplicationInsights-dotnet/tree/main/BASE#tracking-page-views for details on underlying usage.
+ ///
+ /// Name of the view.
+ /// Set of extended properties to send with the event. NOTE: if you set PageName in the collection, it will be overridden using .
+ public void OnViewNavigation(
+ string name,
+ IDictionary extendedProperties)
{
- _ = GetPageViewTelemetry();
- telemetryClient.TrackPageView(telemetry);
- }
+ // need to look at whether the standard properties of the Javascript SDK are supported in the .NET SDK (or rather the Azure Monitor when it rewrites the payload), but for now we'll just leave as minimal and allow injection by caller.
+ // reference: https://github.com/microsoft/ApplicationInsights-JS/blob/b6de144e27629b2d50e05ceb3885ee51b4fa0e2b/API-reference.md
+ extendedProperties ??= new Dictionary();
+ extendedProperties["PageName"] = name;
- internal static PageViewTelemetry GetPageViewTelemetry() => new();
+ telemetryClient.TrackEvent(
+ "PageView",
+ extendedProperties);
+ }
}
diff --git a/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsFeatureUsageTrackingSessionTests.cs b/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsFeatureUsageTrackingSessionTests.cs
index c12896712..0ea9297f7 100644
--- a/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsFeatureUsageTrackingSessionTests.cs
+++ b/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsFeatureUsageTrackingSessionTests.cs
@@ -25,6 +25,7 @@ protected override ApplicationInsightsFeatureUsageTrackingSession GetFeatureUsag
var telemetryConfiguration = new TelemetryConfiguration
{
DisableTelemetry = true,
+ ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000",
};
var telemetryClient = new TelemetryClient(telemetryConfiguration);
@@ -42,6 +43,7 @@ protected override ApplicationInsightsFeatureUsageTrackingSession GetFeatureUsag
var telemetryConfiguration = new TelemetryConfiguration
{
DisableTelemetry = true,
+ ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000",
};
var telemetryClient = new TelemetryClient(telemetryConfiguration);
diff --git a/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsViewTrackingTests.cs b/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsViewTrackingTests.cs
index 5f309050f..4da568abd 100644
--- a/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsViewTrackingTests.cs
+++ b/src/tests/Splat.ApplicationInsights.Tests/ApplicationInsightsViewTrackingTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2026 ReactiveUI. All rights reserved.
+// Copyright (c) 2026 ReactiveUI. All rights reserved.
// Licensed to ReactiveUI under one or more agreements.
// ReactiveUI licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.
@@ -9,7 +9,7 @@
namespace Splat.Tests.ApplicationPerformanceMonitoring;
///
-/// Unit Tests for Application Insights Feature Usage Tracking.
+/// Unit Tests for Application Insights View Tracking.
///
public static class ApplicationInsightsViewTrackingTests
{
@@ -23,6 +23,87 @@ protected override ApplicationInsightsViewTracking GetViewTracking()
var telemetryConfiguration = new TelemetryConfiguration
{
DisableTelemetry = true,
+ ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000",
+ };
+ var telemetryClient = new TelemetryClient(telemetryConfiguration);
+
+ return new(telemetryClient);
+ }
+ }
+
+ ///
+ /// Tests for the method.
+ ///
+ public sealed class OnViewNavigationMethod
+ {
+ ///
+ /// Verifies that tracking a page view with a valid name does not throw.
+ ///
+ /// A representing the asynchronous operation.
+ [Test]
+ public async Task TracksPageView()
+ {
+ var viewTracking = CreateViewTracking();
+
+ viewTracking.OnViewNavigation("HomePage");
+
+ await Assert.That(viewTracking).IsNotNull();
+ }
+
+ ///
+ /// Verifies that tracking multiple consecutive page views does not throw.
+ ///
+ /// A representing the asynchronous operation.
+ [Test]
+ public async Task TracksMultiplePageViews()
+ {
+ var viewTracking = CreateViewTracking();
+
+ viewTracking.OnViewNavigation("HomePage");
+ viewTracking.OnViewNavigation("SettingsPage");
+ viewTracking.OnViewNavigation("ProfilePage");
+
+ await Assert.That(viewTracking).IsNotNull();
+ }
+
+ ///
+ /// Verifies that tracking a page view with an empty name does not throw.
+ ///
+ /// A representing the asynchronous operation.
+ [Test]
+ public async Task TracksEmptyViewName()
+ {
+ var viewTracking = CreateViewTracking();
+
+ viewTracking.OnViewNavigation(string.Empty);
+
+ await Assert.That(viewTracking).IsNotNull();
+ }
+
+ ///
+ /// Verifies that tracking a page view with a name containing special characters does not throw.
+ ///
+ /// A representing the asynchronous operation.
+ [Test]
+ public async Task TracksViewNameWithSpecialCharacters()
+ {
+ var viewTracking = CreateViewTracking();
+
+ viewTracking.OnViewNavigation("Views/Home Page (Main)");
+
+ await Assert.That(viewTracking).IsNotNull();
+ }
+
+ ///
+ /// Creates an instance configured for testing.
+ ///
+ /// A new instance with telemetry disabled.
+ private static ApplicationInsightsViewTracking CreateViewTracking()
+ {
+ var telemetryConfiguration = new TelemetryConfiguration
+ {
+ DisableTelemetry = true,
+ ConnectionString = "InstrumentationKey=00000000-0000-0000-0000-000000000000",
};
var telemetryClient = new TelemetryClient(telemetryConfiguration);