AppInstallerTelemetry.h (13372B)
1 // Copyright (c) Microsoft Corporation. 2 // Licensed under the MIT License. 3 #pragma once 4 #include <AppInstallerLanguageUtilities.h> 5 #include <wil/result_macros.h> 6 7 #include <string_view> 8 #include <vector> 9 #include <cguid.h> 10 11 namespace AppInstaller::Settings 12 { 13 struct UserSettings; 14 } 15 16 namespace AppInstaller::Logging 17 { 18 enum class FailureTypeEnum : UINT32 19 { 20 None = 0x0, 21 22 // Failure type from FailureInfo in result_macros.h 23 ResultException = 0x1, // THROW_... 24 ResultReturn = 0x2, // RETURN_..._LOG or RETURN_..._MSG 25 ResultLog = 0x3, // LOG_... 26 ResultFailFast = 0x4, // FAIL_FAST_... 27 28 // Other failure types from LogException() 29 Unknown = 0x10000, 30 WinrtHResultError = 0x10001, 31 ResourceOpen = 0x10002, 32 StdException = 0x10003, 33 34 // Command termination 35 CommandTermination = 0x20000, 36 }; 37 38 // Contains all fields logged through the TelemetryTraceLogger. Last write wins. 39 // This will be used to report a summary event upon destruction of the TelemetryTraceLogger. 40 struct TelemetrySummary 41 { 42 TelemetrySummary() = default; 43 44 // Selectively copy member fields for copy constructor; 45 TelemetrySummary(const TelemetrySummary& other); 46 TelemetrySummary& operator=(const TelemetrySummary&) = default; 47 48 TelemetrySummary(TelemetrySummary&&) = default; 49 TelemetrySummary& operator=(TelemetrySummary&&) = default; 50 51 // Log wil failure, exception, command termination 52 HRESULT FailureHResult = S_OK; 53 std::wstring FailureMessage; 54 std::string FailureModule; 55 UINT32 FailureThreadId = 0; 56 FailureTypeEnum FailureType = FailureTypeEnum::None; 57 std::string FailureFile; 58 UINT32 FailureLine = 0; 59 60 // LogStartup 61 bool IsCOMCall = false; 62 63 // LogCommand 64 std::string Command; 65 66 // LogCommandSuccess 67 bool CommandSuccess = false; 68 69 // LogIsManifestLocal 70 bool IsManifestLocal = false; 71 72 // LogManifestFields, LogAppFound 73 std::string PackageIdentifier; 74 std::string PackageName; 75 std::string PackageVersion; 76 std::string Channel; 77 std::string SourceIdentifier; 78 79 // LogSelectedInstaller 80 INT32 InstallerArchitecture = -1; 81 std::string InstallerUrl; 82 std::string InstallerType; 83 std::string InstallerScope; 84 std::string InstallerLocale; 85 86 // LogSearchRequest 87 std::string SearchType; 88 std::string SearchQuery; 89 std::string SearchId; 90 std::string SearchName; 91 std::string SearchMoniker; 92 std::string SearchTag; 93 std::string SearchCommand; 94 UINT64 SearchMaximum = 0; 95 std::string SearchRequest; 96 97 // LogSearchResultCount 98 UINT64 SearchResultCount = 0; 99 100 // LogInstallerHashMismatch 101 std::vector<uint8_t> HashMismatchExpected; 102 std::vector<uint8_t> HashMismatchActual; 103 bool HashMismatchOverride = false; 104 uint64_t HashMismatchActualSize = 0; 105 std::string HashMismatchContentType; 106 107 // LogInstallerFailure 108 std::string InstallerExecutionType; 109 UINT32 InstallerErrorCode = 0; 110 111 // LogUninstallerFailure 112 std::string UninstallerExecutionType; 113 UINT32 UninstallerErrorCode = 0; 114 115 // LogRepairFailure 116 std::string RepairExecutionType; 117 UINT32 RepairErrorCode = 0; 118 119 // LogSuccessfulInstallARPChange 120 UINT64 ChangesToARP = 0; 121 UINT64 MatchesInARP = 0; 122 UINT64 ChangesThatMatch = 0; 123 UINT64 ARPLanguage = 0; 124 std::string ARPName; 125 std::string ARPVersion; 126 std::string ARPPublisher; 127 128 // LogNonFatalDOError 129 std::string DOUrl; 130 HRESULT DOHResult = S_OK; 131 }; 132 133 // This type contains the registration lifetime of the telemetry trace logging provider. 134 // Due to the nature of trace logging, specific methods should be added per desired trace. 135 // As there should not be a significantly large number of individual telemetry events, 136 // this should not become a burden. 137 struct TelemetryTraceLogger 138 { 139 TelemetryTraceLogger(bool useSummary = true); 140 141 ~TelemetryTraceLogger(); 142 143 TelemetryTraceLogger(const TelemetryTraceLogger&) = default; 144 TelemetryTraceLogger& operator=(const TelemetryTraceLogger&) = default; 145 146 TelemetryTraceLogger(TelemetryTraceLogger&&) = default; 147 TelemetryTraceLogger& operator=(TelemetryTraceLogger&&) = default; 148 149 // Control whether this trace logger is enabled at runtime. 150 bool DisableRuntime(); 151 void EnableRuntime(); 152 153 // Return address of m_activityId 154 const GUID* GetActivityId() const; 155 156 // Return address of m_parentActivityId 157 const GUID* GetParentActivityId() const; 158 159 // Capture if UserSettings is enabled and set user profile path 160 void Initialize(); 161 162 // Try to capture if UserSettings is enabled and set user profile path, returns whether the action is successfully completed. 163 // There is a possible circular dependency with the user settings. When initializing the telemetry, we need to read the settings 164 // to make sure it's not disabled, but a failure when reading the settings would trigger a telemetry event. We work around that 165 // by avoiding initialization (and thus disabling telemetry) until we have successfully read the settings. Subsequent calls to 166 // TryInitialize() would finish the initialization. 167 bool TryInitialize(); 168 169 // Store the passed in name of the Caller for COM calls 170 void SetCaller(const std::string& caller); 171 172 // Store the passed in Telemetry Correlation Json for COM calls 173 void SetTelemetryCorrelationJson(const std::wstring_view jsonStr_view) noexcept; 174 175 void SetExecutionStage(uint32_t stage) noexcept; 176 177 std::unique_ptr<TelemetryTraceLogger> CreateSubTraceLogger() const; 178 179 // Logs the failure info. 180 void LogFailure(const wil::FailureInfo& failure) const noexcept; 181 182 // Logs the initial process startup. 183 void LogStartup(bool isCOMCall = false) const noexcept; 184 185 // Logs the invoked command. 186 void LogCommand(std::string_view commandName) const noexcept; 187 188 // Logs the invoked command success. 189 void LogCommandSuccess(std::string_view commandName) const noexcept; 190 191 // Logs the invoked command termination. 192 void LogCommandTermination(HRESULT hr, std::string_view file, size_t line) const noexcept; 193 194 // Logs the invoked command termination. 195 void LogException(FailureTypeEnum type, std::string_view message) const noexcept; 196 197 // Logs whether the manifest used in workflow is local 198 void LogIsManifestLocal(bool isLocalManifest) const noexcept; 199 200 // Logs the Manifest fields. 201 void LogManifestFields(std::string_view id, std::string_view name, std::string_view version) const noexcept; 202 203 // Logs when there is no matching App found for search 204 void LogNoAppMatch() const noexcept; 205 206 // Logs when there is multiple matching Apps found for search 207 void LogMultiAppMatch() const noexcept; 208 209 // Logs the name and Id of app found 210 void LogAppFound(std::string_view name, std::string_view id) const noexcept; 211 212 // Logs the selected installer details 213 void LogSelectedInstaller(int arch, std::string_view url, std::string_view installerType, std::string_view scope, std::string_view language) const noexcept; 214 215 // Logs details of a search request. 216 void LogSearchRequest( 217 std::string_view type, 218 std::string_view query, 219 std::string_view id, 220 std::string_view name, 221 std::string_view moniker, 222 std::string_view tag, 223 std::string_view command, 224 size_t maximum, 225 std::string_view request) const noexcept; 226 227 // Logs the Search Result 228 void LogSearchResultCount(uint64_t resultCount) const noexcept; 229 230 // Logs a mismatch between the expected and actual hash values. 231 void LogInstallerHashMismatch( 232 std::string_view id, 233 std::string_view version, 234 std::string_view channel, 235 const std::vector<uint8_t>& expected, 236 const std::vector<uint8_t>& actual, 237 bool overrideHashMismatch, 238 uint64_t downloadSizeInBytes, 239 const std::optional<std::string>& contentType) const noexcept; 240 241 // Logs a failed installation attempt. 242 void LogInstallerFailure(std::string_view id, std::string_view version, std::string_view channel, std::string_view type, uint32_t errorCode) const noexcept; 243 244 // Logs a failed uninstallation attempt. 245 void LogUninstallerFailure(std::string_view id, std::string_view version, std::string_view type, uint32_t errorCode) const noexcept; 246 247 // Logs a failed repair attempt. 248 void LogRepairFailure(std::string_view id, std::string_view version, std::string_view type, uint32_t errorCode) const noexcept; 249 250 // Logs data about the changes that ocurred in the ARP entries based on an install. 251 // First 4 arguments are well known values for the package that we installed. 252 // The next 3 are counts of the number of packages in each category. 253 // The last 4 are the fields directly from the ARP entry that has been determined to be related to the package that 254 // was installed, or they will be empty if there is no data or ambiguity about which entry should be logged. 255 virtual void LogSuccessfulInstallARPChange( 256 std::string_view sourceIdentifier, 257 std::string_view packageIdentifier, 258 std::string_view packageVersion, 259 std::string_view packageChannel, 260 size_t changesToARP, 261 size_t matchesInARP, 262 size_t countOfIntersectionOfChangesAndMatches, 263 std::string_view arpName, 264 std::string_view arpVersion, 265 std::string_view arpPublisher, 266 std::string_view arpLanguage) const noexcept; 267 268 void LogNonFatalDOError(std::string_view url, HRESULT hr) const noexcept; 269 270 protected: 271 bool IsTelemetryEnabled() const noexcept; 272 273 // Initializes flags that determine whether telemetry is enabled. 274 void InitializeInternal(const AppInstaller::Settings::UserSettings& userSettings); 275 276 // Used to anonymize a string to the best of our ability. 277 // Should primarily be used on failure messages or paths if needed. 278 std::wstring AnonymizeString(const wchar_t* input) const noexcept; 279 std::wstring AnonymizeString(std::wstring_view input) const noexcept; 280 281 // Flags used to determine whether to send telemetry. All of them are set during initialization and 282 // are CopyConstructibleAtomic to minimize the impact of multiple simultaneous initialization attempts. 283 // m_isSettingEnabled starts as false so we can don't send telemetry until we have read the 284 // settings and confirmed that it is enabled. 285 CopyConstructibleAtomic<bool> m_isSettingEnabled{ false }; 286 287 // We may decide to disable telemetry at runtime, for example, for command line completion. 288 CopyConstructibleAtomic<bool> m_isRuntimeEnabled{ true }; 289 290 // We wait for initialization of the other flags before sending any events. 291 CopyConstructibleAtomic<bool> m_isInitialized{ false }; 292 293 CopyConstructibleAtomic<uint32_t> m_executionStage{ 0 }; 294 295 GUID m_activityId = GUID_NULL; 296 GUID m_parentActivityId = GUID_NULL; 297 std::wstring m_telemetryCorrelationJsonW = L"{}"; 298 std::string m_caller; 299 300 bool m_useSummary = true; 301 mutable TelemetrySummary m_summary; 302 303 // TODO: This and all related code could be removed after transition to summary event in back end. 304 uint32_t m_subExecutionId; 305 }; 306 307 // Helper to make the call sites look clean. 308 TelemetryTraceLogger& Telemetry(); 309 310 // Turns on wil failure telemetry and logging. 311 void EnableWilFailureTelemetry(); 312 313 // TODO: Temporary code to keep existing telemetry behavior for command execution cases. 314 void UseGlobalTelemetryLoggerActivityIdOnly(); 315 316 // An RAII object to disable telemetry during its lifetime. 317 // Primarily used by the complete command to prevent messy input from spamming us. 318 struct DisableTelemetryScope 319 { 320 DisableTelemetryScope(); 321 322 DisableTelemetryScope(const DisableTelemetryScope&) = delete; 323 DisableTelemetryScope& operator=(const DisableTelemetryScope&) = delete; 324 325 DisableTelemetryScope(DisableTelemetryScope&&) = default; 326 DisableTelemetryScope& operator=(DisableTelemetryScope&&) = default; 327 328 ~DisableTelemetryScope(); 329 330 private: 331 DestructionToken m_token; 332 }; 333 }