-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial pass at AppInsights sending custom events (#899)
### Motivation and Context Tracking high level user engagement of features can direct further development and enable measurements of active user counts. It is important to note that completions and conversations themselves should not be logged, just data useful in aggregate. ### Description This is an initial pass for review by the team. ### Motivation and Context <!-- Thank you for your contribution to the semantic-kernel repo! Please help reviewers and future users, providing the following information: 1. Why is this change required? 2. What problem does it solve? 3. What scenario does it contribute to? 4. If it fixes an open issue, please link to the issue here. --> 1. This change is essential for tracking user engagement and creating an audit trail of user activity. 2. This change adds a basic framework for tracking key telemetry events 3. This scenario enables management of those teams deploying instances to understand how their deployment is being used by their team. 4. This is not related to an open issue. ### Description <!-- Describe your changes, the overall approach, the underlying design. These notes will help understanding how your code works. Thanks! --> The overall design is to add a service accessible to controllers and other services that enables telemetry to be fired with minimal context. For this an abstract ITelemetryService interface was added, allowing systems to fire events on this from across the kernel without any dependencies on a specific implementation. ### Contribution Checklist <!-- Before submitting this PR, please make sure: --> - [X] The code builds clean without any errors or warnings - [X] The PR follows SK Contribution Guidelines (https://github.com/microsoft/semantic-kernel/blob/main/CONTRIBUTING.md) - [X] The code follows the .NET coding conventions (https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions) verified with `dotnet format` - [] All unit tests pass, and I have added new tests where possible - _tests appear to fail locally for config related reasons._ - [ ] I didn't break anyone 😄 - _maybe myself, a bit..._ --------- Co-authored-by: Ian Norris <ianorr@microsoft.com> Co-authored-by: Adrian Bonar <56417140+adrianwyatt@users.noreply.github.com> Co-authored-by: Gil LaHaye <gillahaye@microsoft.com> Co-authored-by: Ben Thomas <ben.thomas@microsoft.com>
- Loading branch information
1 parent
f8a8d88
commit 18c6f46
Showing
8 changed files
with
276 additions
and
11 deletions.
There are no files selected for viewing
17 changes: 17 additions & 0 deletions
17
dotnet/src/SemanticKernel.Abstractions/Diagnostics/ITelemetryService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
namespace Microsoft.SemanticKernel.Diagnostics; | ||
|
||
/// <summary> | ||
/// Interface for common telemetry events to track actions across the semantic kernel. | ||
/// </summary> | ||
public interface ITelemetryService | ||
{ | ||
/// <summary> | ||
/// Creates a telemetry event when a skill function is executed. | ||
/// </summary> | ||
/// <param name="skillName">Name of the skill</param> | ||
/// <param name="functionName">Skill function name</param> | ||
/// <param name="success">If the skill executed successfully</param> | ||
void TrackSkillFunction(string skillName, string functionName, bool success); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
samples/apps/copilot-chat-app/webapi/Diagnostics/ITelemetryService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
namespace SemanticKernel.Service.Diagnostics; | ||
|
||
/// <summary> | ||
/// Interface for common telemetry events to track actions across the semantic kernel. | ||
/// </summary> | ||
public interface ITelemetryService | ||
{ | ||
/// <summary> | ||
/// Creates a telemetry event when a skill function is executed. | ||
/// </summary> | ||
/// <param name="skillName">Name of the skill</param> | ||
/// <param name="functionName">Skill function name</param> | ||
/// <param name="success">If the skill executed successfully</param> | ||
void TrackSkillFunction(string skillName, string functionName, bool success); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
samples/apps/copilot-chat-app/webapi/Services/AppInsightsTelemetryService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using System.Collections.Generic; | ||
using System.Security.Claims; | ||
using Microsoft.ApplicationInsights; | ||
using Microsoft.AspNetCore.Http; | ||
using SemanticKernel.Service.Diagnostics; | ||
|
||
namespace SemanticKernel.Service.Services; | ||
|
||
/// <summary> | ||
/// Implementation of the telemetry service interface for Azure Application Insights (AppInsights). | ||
/// </summary> | ||
public class AppInsightsTelemetryService : ITelemetryService | ||
{ | ||
private const string UnknownUserId = "unauthenticated"; | ||
|
||
private readonly TelemetryClient _telemetryClient; | ||
private readonly IHttpContextAccessor _httpContextAccessor; | ||
|
||
/// <summary> | ||
/// Creates an instance of the app insights telemetry service. | ||
/// This should be injected into the service collection during startup. | ||
/// </summary> | ||
/// <param name="telemetryClient">An AppInsights telemetry client</param> | ||
/// <param name="httpContextAccessor">Accessor for the current request's http context</param> | ||
public AppInsightsTelemetryService(TelemetryClient telemetryClient, IHttpContextAccessor httpContextAccessor) | ||
{ | ||
this._telemetryClient = telemetryClient; | ||
this._httpContextAccessor = httpContextAccessor; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void TrackSkillFunction(string skillName, string functionName, bool success) | ||
{ | ||
var properties = new Dictionary<string, string>(this.BuildDefaultProperties()) | ||
{ | ||
{ "skillName", skillName }, | ||
{ "functionName", functionName }, | ||
{ "success", success.ToString() }, | ||
}; | ||
|
||
this._telemetryClient.TrackEvent("SkillFunction", properties); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the current user's ID from the http context for the current request. | ||
/// </summary> | ||
/// <param name="contextAccessor">The http context accessor</param> | ||
/// <returns></returns> | ||
public static string GetUserIdFromHttpContext(IHttpContextAccessor contextAccessor) | ||
{ | ||
var context = contextAccessor.HttpContext; | ||
if (context == null) | ||
{ | ||
return UnknownUserId; | ||
} | ||
|
||
var user = context.User; | ||
if (user?.Identity?.IsAuthenticated != true) | ||
{ | ||
return UnknownUserId; | ||
} | ||
|
||
var userId = user.FindFirst(ClaimTypes.NameIdentifier)?.Value; | ||
|
||
if (userId == null) | ||
{ | ||
return UnknownUserId; | ||
} | ||
|
||
return userId; | ||
} | ||
|
||
/// <summary> | ||
/// Prepares a list of common properties that all telemetry events should contain. | ||
/// </summary> | ||
/// <returns>Collection of common properties for all telemetry events</returns> | ||
private Dictionary<string, string> BuildDefaultProperties() | ||
{ | ||
string? userId = GetUserIdFromHttpContext(this._httpContextAccessor); | ||
|
||
return new Dictionary<string, string> | ||
{ | ||
{ "userId", GetUserIdFromHttpContext(this._httpContextAccessor) } | ||
}; | ||
} | ||
} |
35 changes: 35 additions & 0 deletions
35
samples/apps/copilot-chat-app/webapi/Services/AppInsightsUserTelemetryInitializerService.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright (c) Microsoft. All rights reserved. | ||
|
||
using Microsoft.ApplicationInsights.Channel; | ||
using Microsoft.ApplicationInsights.DataContracts; | ||
using Microsoft.ApplicationInsights.Extensibility; | ||
using Microsoft.AspNetCore.Http; | ||
|
||
namespace SemanticKernel.Service.Services; | ||
|
||
/// <summary> | ||
/// A telemetry initializer used by the TelemetryClient to fill in data for requests. | ||
/// This implementation injects the id of the current authenticated user (if there is one). | ||
/// </summary> | ||
public class AppInsightsUserTelemetryInitializerService : ITelemetryInitializer | ||
{ | ||
public AppInsightsUserTelemetryInitializerService(IHttpContextAccessor httpContextAccessor) | ||
{ | ||
this._contextAccessor = httpContextAccessor; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void Initialize(ITelemetry telemetry) | ||
{ | ||
if (telemetry is not RequestTelemetry requestTelemetry) | ||
{ | ||
return; | ||
} | ||
|
||
var userId = AppInsightsTelemetryService.GetUserIdFromHttpContext(this._contextAccessor); | ||
|
||
telemetry.Context.User.Id = userId; | ||
} | ||
|
||
private readonly IHttpContextAccessor _contextAccessor; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters