Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update TelemetryClient to enable tracking of dialog ('page') views #3440

Merged
merged 14 commits into from
Mar 4, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.Bot.Builder.ApplicationInsights
/// <summary>
/// A logging client for bot telemetry.
/// </summary>
public class BotTelemetryClient : IBotTelemetryClient
public class BotTelemetryClient : IBotTelemetryClient, IBotPageViewTelemetryClient
{
private readonly TelemetryClient _telemetryClient;

Expand Down Expand Up @@ -168,6 +168,35 @@ public virtual void TrackTrace(string message, Severity severityLevel, IDictiona
_telemetryClient.TrackTrace(telemetry);
}

/// <summary>
/// Logs a dialog entry / as an Application Insights page view.
/// </summary>
/// <param name="dialogName">The name of the dialog to log the entry / start for.</param>
/// <param name="properties">Named string values you can use to search and classify events.</param>
/// <param name="metrics">Measurements associated with this event.</param>
public virtual void TrackPageView(string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
var telemetry = new PageViewTelemetry(dialogName);

if (properties != null)
{
foreach (var pair in properties)
{
telemetry.Properties.Add(pair.Key, pair.Value);
}
}

if (metrics != null)
{
foreach (var pair in metrics)
{
telemetry.Metrics.Add(pair.Key, pair.Value);
}
}

_telemetryClient.TrackPageView(telemetry);
}

/// <summary>
/// Flushes the in-memory buffer and any metrics being pre-aggregated.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions libraries/Microsoft.Bot.Builder.Dialogs/ComponentDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext oute
return await EndComponentAsync(outerDc, turnResult.Result, cancellationToken).ConfigureAwait(false);
}

TelemetryClient.TrackPageView(Id);

// Just signal waiting
return Dialog.EndOfTurn;
}
Expand Down
1 change: 1 addition & 0 deletions libraries/Microsoft.Bot.Builder.Dialogs/WaterfallDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ public override async Task<DialogTurnResult> BeginDialogAsync(DialogContext dc,
{ "InstanceId", instanceId },
};
TelemetryClient.TrackEvent("WaterfallStart", properties);
TelemetryClient.TrackPageView(Id);

// Run first step
return await RunStepAsync(dc, 0, DialogReason.BeginCalled, null, cancellationToken).ConfigureAwait(false);
Expand Down
22 changes: 22 additions & 0 deletions libraries/Microsoft.Bot.Builder/IBotPageViewTelemetryClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;

namespace Microsoft.Bot.Builder
{
/// <summary>
/// Describes a logging client for bot telemetry.
/// </summary>
public interface IBotPageViewTelemetryClient
{
/// <summary>
/// Logs an Application Insights page view.
/// </summary>
/// <param name="dialogName">The name of the dialog to log the entry / start for.</param>
/// <param name="properties">Named string values you can use to search and classify events.</param>
/// <param name="metrics">Measurements associated with this event.</param>
void TrackPageView(string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null);
}
}
26 changes: 26 additions & 0 deletions libraries/Microsoft.Bot.Builder/IBotTelemetryClientExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;

namespace Microsoft.Bot.Builder
{
public static class IBotTelemetryClientExtensions
{
/// <summary>
/// Adds the ability to call TrackPageView on the TelemetryClient if it implements IBotPageViewTelemetryClient as well as IBotTelemetryClient.
/// </summary>
/// <param name="telemetryClient">The TelemetryClient that implements IBotTelemetryClient.</param>
/// <param name="dialogName">The name of the dialog to log the entry / start for.</param>
/// <param name="properties">Named string values you can use to search and classify events.</param>
/// <param name="metrics">Measurements associated with this event.</param>
public static void TrackPageView(this IBotTelemetryClient telemetryClient, string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
garypretty marked this conversation as resolved.
Show resolved Hide resolved
{
if (telemetryClient is IBotPageViewTelemetryClient pageViewClient)
{
pageViewClient.TrackPageView(dialogName, properties, metrics);
}
else
{
telemetryClient.TrackTrace("TelemetryClient cannot track PageView telemtry as it does not implement IBotPageViewTelemetryClient", Severity.Information, properties);
garypretty marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
}
6 changes: 5 additions & 1 deletion libraries/Microsoft.Bot.Builder/NullBotTelemetryClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

namespace Microsoft.Bot.Builder
{
public class NullBotTelemetryClient : IBotTelemetryClient
public class NullBotTelemetryClient : IBotTelemetryClient, IBotPageViewTelemetryClient
{
public static IBotTelemetryClient Instance { get; } = new NullBotTelemetryClient();

Expand All @@ -33,5 +33,9 @@ public void TrackException(Exception exception, IDictionary<string, string> prop
public void TrackTrace(string message, Severity severityLevel, IDictionary<string, string> properties)
{
}

public void TrackPageView(string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public void Initialize(ITelemetry telemetry)
if (items != null)
{
if ((telemetry is RequestTelemetry || telemetry is EventTelemetry
|| telemetry is TraceTelemetry || telemetry is DependencyTelemetry)
|| telemetry is TraceTelemetry || telemetry is DependencyTelemetry || telemetry is PageViewTelemetry)
&& items.ContainsKey(BotActivityKey))
{
if (items[BotActivityKey] is JObject body)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,16 @@ public void TrackTraceTest()
_mockTelemetryChannel.Verify(tc => tc.Send(It.Is<TraceTelemetry>(t => t.SeverityLevel == SeverityLevel.Critical)));
_mockTelemetryChannel.Verify(tc => tc.Send(It.Is<TraceTelemetry>(t => t.Properties["foo"] == "bar")));
}

[TestMethod]
public void TrackPageViewTest()
{
_botTelemetryClient.TrackPageView("test", new Dictionary<string, string>() { { "hello", "value" } }, new Dictionary<string, double>() { { "metric", 0.6 } });

_mockTelemetryChannel.Verify(tc => tc.Send(It.Is<PageViewTelemetry>(t => t.Name == "test")));
_mockTelemetryChannel.Verify(tc => tc.Send(It.Is<PageViewTelemetry>(t => t.Properties["hello"] == "value")));
_mockTelemetryChannel.Verify(tc => tc.Send(It.Is<PageViewTelemetry>(t => t.Metrics["metric"] == 0.6)));
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public override void TrackTrace(string message, Severity severityLevel, IDiction
base.TrackTrace(message, severityLevel, properties);
}

public override void TrackPageView(string name, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
base.TrackPageView(name, properties, metrics);
}

public override void Flush()
{
base.Flush();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Bot.Builder.Adapters;
using Microsoft.Bot.Builder.ApplicationInsights;
using Microsoft.Bot.Builder.Dialogs;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ public CancelledComponentDialog(Dialog waterfallDialog)
}
}

private class MyBotTelemetryClient : IBotTelemetryClient
private class MyBotTelemetryClient : IBotTelemetryClient, IBotPageViewTelemetryClient
{
public MyBotTelemetryClient()
{
Expand All @@ -496,6 +496,11 @@ public void TrackDependency(string dependencyTypeName, string target, string dep
throw new NotImplementedException();
}

public void TrackPageView(string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
throw new NotImplementedException();
}

public void TrackEvent(string eventName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
throw new NotImplementedException();
Expand Down
7 changes: 6 additions & 1 deletion tests/Microsoft.Bot.Builder.Dialogs.Tests/DialogSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ public async Task DialogSet_HeterogeneousLoggers()
await Task.CompletedTask;
}

private class MyBotTelemetryClient : IBotTelemetryClient
private class MyBotTelemetryClient : IBotTelemetryClient, IBotPageViewTelemetryClient
{
public MyBotTelemetryClient()
{
Expand All @@ -151,6 +151,11 @@ public void TrackDependency(string dependencyTypeName, string target, string dep
throw new NotImplementedException();
}

public void TrackPageView(string dialogName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
throw new NotImplementedException();
}

public void TrackEvent(string eventName, IDictionary<string, string> properties = null, IDictionary<string, double> metrics = null)
{
throw new NotImplementedException();
Expand Down