logging.md
1 # Logging and Telemetry in PowerToys 2 3 ## Logging Types in PowerToys 4 5 PowerToys has several types of logging mechanisms: 6 1. Text file logs (application writes logs to files) 7 2. Telemetry/diagnostic data (sent to Microsoft servers) 8 3. Event Viewer logs (used by some utilities like Mouse Without Borders) 9 4. Watson reports (crash reports sent to Microsoft) 10 11 ## Log File Locations 12 13 ### Regular Logs 14 - Located at: `%LOCALAPPDATA%\Microsoft\PowerToys\Logs` 15 - Organized by utility and sometimes by version 16 - Examples: PowerToys Run logs, module interface logs 17 - C# and C++ components both write logs to these locations 18 19 ### Low-Privilege Logs 20 - Some components (like preview handlers and thumbnail providers) are started by Explorer and have low privileges 21 - These components write logs to: `%USERPROFILE%/AppData/LocalLow/Microsoft/PowerToys` 22 - Example: Monaco preview handler logs 23 24 ### Module Logs 25 - Logs always stored in user's AppData regardless of installation type 26 - Each module creates its own log 27 - Even with machine-wide installation, logs are per-user 28 - Different users can have different logs even with a machine-wide installation 29 30 ## Log Implementation 31 32 ### C++ Logging 33 34 In C++ projects we use the awesome [spdlog](https://github.com/gabime/spdlog) library for logging as a git submodule under the `deps` directory. To use it in your project, just include [spdlog.props](/deps/spdlog.props) in a .vcxproj like this: 35 36 ```xml 37 <Import Project="..\..\..\deps\spdlog.props" /> 38 ``` 39 It'll add the required include dirs and link the library binary itself. 40 41 - Projects need to include the logging project as a dependency 42 - Uses a git submodule for the actual logging library 43 - Logs are initialized in the main file: 44 ```cpp 45 init_logger(); 46 ``` 47 - After initialization, any file can use the logger 48 - Logger settings contain constants like log file locations 49 50 ### C# Logging 51 52 For C# projects there is a static logger class in Managed Common called `Logger`. 53 54 To use it, add a project reference to `ManagedCommon` and add the following line of code to all the files using the logger: 55 56 ```Csharp 57 using ManagedCommon; 58 ``` 59 60 In the `Main` function (or a function with a similar meaning (like `App` in a `App.xaml.cs` file)) you have to call `InitializeLogger` and specify the location where the logs will be saved (always use a path scheme similar to this example): 61 62 ```Csharp 63 Logger.InitializeLogger("\\FancyZones\\Editor\\Logs"); 64 ``` 65 66 For a low-privilege process you have to set the optional second parameter to `true`: 67 68 ```Csharp 69 Logger.InitializeLogger("\\FileExplorer\\Monaco\\Logs", true); 70 ``` 71 72 The `Logger` class contains the following logging functions: 73 74 ```Csharp 75 // Logs an error that the utility encountered 76 Logger.LogError(string message); 77 Logger.LogError(string message, Exception ex); 78 // Logs an error that isn't that grave 79 Logger.LogWarning(string message); 80 // Logs what the app is doing at the moment 81 Logger.LogInfo(string message); 82 // Like LogInfo just with infos important for debugging 83 Logger.LogDebug(string message); 84 // Logs the current state of the utility. 85 Logger.LogTrace(); 86 ``` 87 88 ## Log File Management 89 - Currently, most logs are not automatically cleaned up 90 - Some modules have community contributions to clean old logs, but not universally implemented 91 - By default, all info-level logs are written 92 - Debug and trace logs may not be written by default 93 - Log settings can be found in settings.json, but not all APIs honor these settings 94 95 ## Telemetry 96 97 ### Implementation 98 - Uses Event Tracing for Windows (ETW) for telemetry 99 - Different from the text file logging system 100 - Keys required to send telemetry to the right server 101 - Keys are not stored in the repository 102 - Obfuscated in public code 103 - Replaced during the release process 104 - Stored in private NuGet packages for release builds 105 106 ### C++ Telemetry 107 - Managed through trace_base.h which: 108 - Registers the provider 109 - Checks if user has disabled diagnostics 110 - Defines events 111 - Example from Always On Top: 112 ```cpp 113 Trace::AlwaysOnTop::Enable(true); 114 ``` 115 116 ### C# Telemetry 117 - Uses PowerToysTelemetry class 118 - WriteEvent method sends telemetry 119 - Projects add a reference to the PowerToys.Telemetry project 120 - Example: 121 ```csharp 122 PowerToysTelemetry.Log.WriteEvent(new LauncherShowEvent(hotKey)); 123 ``` 124 125 ### User Controls 126 - Settings page allows users to: 127 - Turn off/on sending telemetry 128 - Enable viewing of telemetry data 129 130 ### Viewing Telemetry Data 131 - When "Enable viewing" is turned on, PowerToys starts ETW tracing 132 - Saves ETL files for 28 days 133 - Located at: `%LOCALAPPDATA%\Microsoft\PowerToys\ETL` (for most utilities) 134 - Low-privilege components save to a different location 135 - Button in settings converts ETL to XML for user readability 136 - XML format chosen to follow approved compliance pattern from Windows Subsystem for Android 137 - Files older than 28 days are automatically deleted 138 139 ## Bug Report Tool 140 141 The [BugReportTool](/tools/BugReportTool) can be triggered via: 142 - Right-click on PowerToys tray icon → Report Bug 143 - Left-click on tray icon → Open Settings → Bug Report Tool 144 145 It creates a zip file on desktop named "PowerToys_Report_[date]_[time].zip" containing logs and system information. 146 147 See [Bug Report Tool](../tools/bug-report-tool.md) for more detailed information about the tool.