TelemetryForwarder.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using CommunityToolkit.Mvvm.Messaging; 6 using Microsoft.CmdPal.Core.Common.Services; 7 using Microsoft.CmdPal.Core.ViewModels.Messages; 8 using Microsoft.CmdPal.UI.Events; 9 using Microsoft.CommandPalette.Extensions; 10 using Microsoft.PowerToys.Telemetry; 11 12 namespace Microsoft.CmdPal.UI; 13 14 /// <summary> 15 /// TelemetryForwarder is responsible for forwarding telemetry events from the 16 /// command palette to PowerToys Telemetry. 17 /// Listens to telemetry-specific messages from the core layer and logs them to PowerToys telemetry. 18 /// Also implements ITelemetryService for dependency injection in extensions. 19 /// </summary> 20 internal sealed class TelemetryForwarder : 21 ITelemetryService, 22 IRecipient<TelemetryBeginInvokeMessage>, 23 IRecipient<TelemetryInvokeResultMessage>, 24 IRecipient<TelemetryExtensionInvokedMessage> 25 { 26 public TelemetryForwarder() 27 { 28 WeakReferenceMessenger.Default.Register<TelemetryBeginInvokeMessage>(this); 29 WeakReferenceMessenger.Default.Register<TelemetryInvokeResultMessage>(this); 30 WeakReferenceMessenger.Default.Register<TelemetryExtensionInvokedMessage>(this); 31 } 32 33 // Message handlers for telemetry events from core layer 34 public void Receive(TelemetryBeginInvokeMessage message) 35 { 36 PowerToysTelemetry.Log.WriteEvent(new BeginInvoke()); 37 } 38 39 public void Receive(TelemetryInvokeResultMessage message) 40 { 41 PowerToysTelemetry.Log.WriteEvent(new CmdPalInvokeResult(message.Kind)); 42 } 43 44 public void Receive(TelemetryExtensionInvokedMessage message) 45 { 46 PowerToysTelemetry.Log.WriteEvent(new CmdPalExtensionInvoked( 47 message.ExtensionId, 48 message.CommandId, 49 message.CommandName, 50 message.Success, 51 message.ExecutionTimeMs)); 52 53 // Increment session counter for commands executed 54 if (App.Current.AppWindow is MainWindow mainWindow) 55 { 56 mainWindow.IncrementCommandsExecuted(); 57 } 58 } 59 60 // Static method for logging session duration from UI layer 61 public static void LogSessionDuration( 62 ulong durationMs, 63 int commandsExecuted, 64 int pagesVisited, 65 string dismissalReason, 66 int searchQueriesCount, 67 int maxNavigationDepth, 68 int errorCount) 69 { 70 PowerToysTelemetry.Log.WriteEvent(new CmdPalSessionDuration( 71 durationMs, 72 commandsExecuted, 73 pagesVisited, 74 dismissalReason, 75 searchQueriesCount, 76 maxNavigationDepth, 77 errorCount)); 78 } 79 80 // ITelemetryService implementation for dependency injection in extensions 81 public void LogRunQuery(string query, int resultCount, ulong durationMs) 82 { 83 PowerToysTelemetry.Log.WriteEvent(new CmdPalRunQuery(query, resultCount, durationMs)); 84 } 85 86 public void LogRunCommand(string command, bool asAdmin, bool success) 87 { 88 PowerToysTelemetry.Log.WriteEvent(new CmdPalRunCommand(command, asAdmin, success)); 89 } 90 91 public void LogOpenUri(string uri, bool isWeb, bool success) 92 { 93 PowerToysTelemetry.Log.WriteEvent(new CmdPalOpenUri(uri, isWeb, success)); 94 } 95 }