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