winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }