Fixed comments that were inconsistent with the style guidelines described in C++ core guidelines and the modern C++/WinRT language projections and removed trailing whitespace. Inserted a space after the beginning of the comment so the text wasn't touching the // on all occurrences. Removed all occurrences of trailing whitespace
989 lines
37 KiB
C++
989 lines
37 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#include "pch.h"
|
|
#include "TraceLogger.h"
|
|
#include "NetworkManager.h"
|
|
#include "CalculatorButtonUser.h"
|
|
|
|
using namespace CalculatorApp;
|
|
using namespace CalculatorApp::Common;
|
|
using namespace Concurrency;
|
|
using namespace std;
|
|
using namespace winrt;
|
|
using namespace winrt::Windows::Foundation;
|
|
using namespace winrt::Windows::Foundation::Diagnostics;
|
|
using namespace winrt::Windows::Globalization;
|
|
using namespace winrt::Windows::Globalization::DateTimeFormatting;
|
|
using namespace winrt::Windows::System::UserProfile;
|
|
|
|
namespace CalculatorApp
|
|
{
|
|
static multimap<int, vector<wstring>> s_memoryMap;
|
|
|
|
static constexpr array<const wchar_t * const, 9> s_programmerType{
|
|
L"N/A", L"QwordType", L"DwordType",
|
|
L"WordType", L"ByteType", L"HexBase",
|
|
L"DecBase", L"OctBase", L"BinBase" };
|
|
static reader_writer_lock s_traceLoggerLock;
|
|
|
|
// Telemetry events. Uploaded to asimov.
|
|
constexpr auto EVENT_NAME_DEBUG = L"Debug";
|
|
constexpr auto EVENT_NAME_ERROR = L"ErrorMessage";
|
|
constexpr auto EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM = L"AppPrelaunchedBySystem";
|
|
constexpr auto EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER = L"PrelaunchedAppActivatedByUser";
|
|
constexpr auto EVENT_NAME_APP_LAUNCH_BEGIN = L"AppLaunchBegin";
|
|
constexpr auto EVENT_NAME_APP_LAUNCH_END = L"AppLaunchEnd";
|
|
constexpr auto EVENT_NAME_APP_RESUME_END = L"AppResumeEnd";
|
|
constexpr auto EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION = L"PreviousStateOnWindowCreation";
|
|
constexpr auto EVENT_NAME_SIZE_ON_SUSPENSION = L"CalculatorSizeOnSuspension";
|
|
constexpr auto EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION = L"CalculatorViewedInSession";
|
|
constexpr auto EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION = L"DateCalculatorViewedInSession";
|
|
constexpr auto EVENT_NAME_CONVERTER_VIEWED_IN_SESSION = L"ConverterViewedInSession";
|
|
constexpr auto EVENT_NAME_MODE_CHANGE_BEGIN = L"ModeChangeBegin";
|
|
constexpr auto EVENT_NAME_MODE_CHANGE_END = L"ModeChangeEnd";
|
|
constexpr auto EVENT_NAME_HISTORY_BODY_OPENED = L"HistoryBodyOpened";
|
|
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN = L"HistoryItemLoadBegin";
|
|
constexpr auto EVENT_NAME_HISTORY_ITEM_LOAD_END = L"HistoryItemLoadEnd";
|
|
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN = L"HistoryFlyoutOpenBegin";
|
|
constexpr auto EVENT_NAME_HISTORY_FLYOUT_OPEN_END = L"HistoryFlyoutOpenEnd";
|
|
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_BEGIN = L"NewWindowCreationBegin";
|
|
constexpr auto EVENT_NAME_NEW_WINDOW_CREATION_END = L"NewWindowCreationEnd";
|
|
constexpr auto EVENT_NAME_HISTORY_CLEAR = L"HistoryClearBegin";
|
|
constexpr auto EVENT_NAME_MULTIPLE_MEMORY_USED = L"MultipleMemoryUsed";
|
|
constexpr auto EVENT_NAME_SINGLE_MEMORY_USED = L"SingleMemoryUsed";
|
|
constexpr auto EVENT_NAME_SHARED_MEMORY_USED = L"SharedMemoryUsed";
|
|
constexpr auto EVENT_NAME_MEMORY_BODY_OPENED = L"MemoryBodyOpened";
|
|
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
|
|
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
|
|
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
|
|
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
|
|
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
|
|
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
|
|
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
|
|
constexpr auto EVENT_NAME_ANGLE_BUTTONS_USED = L"AngleButtonUsedInSession";
|
|
constexpr auto EVENT_NAME_HYP_BUTTON_USED = L"HypButtonUsedInSession";
|
|
constexpr auto EVENT_NAME_FUNCTION_USAGE = L"FunctionUsageInSession";
|
|
constexpr auto EVENT_NAME_BITLENGTH_BUTTON_USED = L"BitLengthButtonUsed";
|
|
constexpr auto EVENT_NAME_RADIX_BUTTON_USED = L"RadixButtonUsed";
|
|
constexpr auto EVENT_NAME_MAX_WINDOW_COUNT = L"MaxWindowCountInSession";
|
|
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL = L"WindowActivatedThroughProtocol";
|
|
constexpr auto EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH = L"WindowLaunchedThroughTile";
|
|
constexpr auto EVENT_NAME_DATE_DIFFERENCE_USED = L"DateDifferenceModeUsed";
|
|
constexpr auto EVENT_NAME_DATE_ADD_SUBTRACT_USED = L"DateAddSubtractModeUsed";
|
|
constexpr auto EVENT_NAME_DATE_DIFFERENCE_FOUND = L"DateDifferenceFound";
|
|
constexpr auto EVENT_NAME_HIDE_IF_SHOWN = L"HideIfShown";
|
|
constexpr auto EVENT_NAME_ABOUT_FLYOUT_OPENED = L"AboutFlyoutOpened";
|
|
constexpr auto EVENT_NAME_NAV_BAR_OPENED = L"NavBarOpened";
|
|
constexpr auto EVENT_NAME_CORE_WINDOW_WAS_NULL = L"CoreWindowWasNull";
|
|
|
|
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
|
|
|
|
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
|
|
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
|
|
|
|
#ifdef SEND_TELEMETRY
|
|
// c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
|
|
// c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
|
|
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0x0000800000000000; // Bit 47
|
|
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0x0000400000000000; // Bit 46
|
|
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0x0000200000000000; // Bit 45
|
|
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0x0000100000000000; // Bit 44 (reserved for future assignment)
|
|
#else
|
|
// define all Keyword options as 0 when we do not want to upload app telemetry
|
|
constexpr int64_t MICROSOFT_KEYWORD_CRITICAL_DATA = 0;
|
|
constexpr int64_t MICROSOFT_KEYWORD_MEASURES = 0;
|
|
constexpr int64_t MICROSOFT_KEYWORD_TELEMETRY = 0;
|
|
constexpr int64_t MICROSOFT_KEYWORD_RESERVED_44 = 0;
|
|
#endif
|
|
|
|
#pragma region TraceLogger setup and cleanup
|
|
|
|
TraceLogger::TraceLogger() :
|
|
g_calculatorProvider(
|
|
L"MicrosoftCalculator",
|
|
LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group
|
|
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }), // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
|
|
m_appLaunchActivity{ nullptr }
|
|
{
|
|
// initialize the function array
|
|
InitFunctionLogArray();
|
|
}
|
|
|
|
TraceLogger::~TraceLogger()
|
|
{
|
|
}
|
|
|
|
TraceLogger& TraceLogger::GetInstance()
|
|
{
|
|
static TraceLogger s_selfInstance;
|
|
return s_selfInstance;
|
|
}
|
|
|
|
bool TraceLogger::GetTraceLoggingProviderEnabled() const
|
|
{
|
|
return g_calculatorProvider.Enabled();
|
|
}
|
|
|
|
#pragma region Tracing methods
|
|
void TraceLogger::LogTelemetryEvent(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
|
|
}
|
|
|
|
void TraceLogger::LogMeasureEvent(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_MEASURES));
|
|
}
|
|
|
|
void TraceLogger::LogCriticalDataEvent(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_CRITICAL_DATA));
|
|
}
|
|
|
|
void TraceLogger::LogPerformanceEvent(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
|
|
}
|
|
|
|
void TraceLogger::LogInfoEvent(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Information);
|
|
}
|
|
|
|
unique_ptr<TraceActivity> TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields) const
|
|
{
|
|
return make_unique<TraceActivity>(g_calculatorProvider, eventName, fields);
|
|
}
|
|
#pragma endregion
|
|
|
|
void TraceLogger::InsertIntoMemoryMap(int windowId, bool isStandard, bool isScientific, bool isProgrammer)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
auto iterMap = s_memoryMap.find(windowId);
|
|
if (iterMap == s_memoryMap.end())
|
|
{
|
|
s_memoryMap.insert(std::make_pair(windowId, vector<wstring>()));
|
|
iterMap = s_memoryMap.find(windowId);
|
|
}
|
|
|
|
if (isScientific)
|
|
{
|
|
iterMap->second.insert(iterMap->second.begin(), L"Scientific");
|
|
}
|
|
else if (isProgrammer)
|
|
{
|
|
iterMap->second.insert(iterMap->second.begin(), L"Programmer");
|
|
}
|
|
else if (isStandard)
|
|
{
|
|
iterMap->second.insert(iterMap->second.begin(), L"Standard");
|
|
}
|
|
}
|
|
|
|
void TraceLogger::UpdateMemoryMap(int windowId, int memoryPosition, bool isStandard, bool isScientific, bool isProgrammer)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
auto iterMap = s_memoryMap.find(windowId);
|
|
assert(iterMap != s_memoryMap.end());
|
|
assert(iterMap->second.size() >= (unsigned int)memoryPosition);
|
|
|
|
if (isScientific)
|
|
{
|
|
iterMap->second[memoryPosition] = L"Scientific";
|
|
}
|
|
else if (isProgrammer)
|
|
{
|
|
iterMap->second[memoryPosition] = L"Programmer";
|
|
}
|
|
else if (isStandard)
|
|
{
|
|
iterMap->second[memoryPosition] = L"Standard";
|
|
}
|
|
}
|
|
|
|
void TraceLogger::DeleteFromMemoryMap(int windowId, int memoryPosition)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
auto iterMap = s_memoryMap.find(windowId);
|
|
assert(iterMap != s_memoryMap.end());
|
|
|
|
iterMap->second.erase(iterMap->second.begin() + memoryPosition);
|
|
}
|
|
|
|
// return true if windowId is logged once else return false
|
|
bool TraceLogger::UpdateWindowIdLog(int windowId)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
if (windowIdLog.find(windowId) == windowIdLog.end())
|
|
{
|
|
return false;
|
|
}
|
|
if (windowIdLog[windowId] == false)
|
|
{
|
|
windowIdLog[windowId] = true;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// call comes here at the time of ApplicationViewModel initialisation
|
|
void TraceLogger::LogCalculatorModeViewed(ViewMode mode, int windowId)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
// store windowId in windowIdLog which says we have logged mode for the present windowId.
|
|
if (windowIdLog.find(windowId) == windowIdLog.end())
|
|
{
|
|
windowIdLog.insert(pair<int, bool>(windowId, false));
|
|
}
|
|
// if the event is not logged already for the present mode
|
|
if (currentMode != mode)
|
|
{
|
|
currentMode = mode;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"CalculatorMode", NavCategory::GetFriendlyName(mode)->Data());
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_CALCULATOR_VIEWED_IN_SESSION, fields);
|
|
}
|
|
}
|
|
|
|
// call comes here at the time of ApplicationViewModel initialization
|
|
void TraceLogger::LogDateCalculatorModeViewed(ViewMode mode, int windowId)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
// store windowId in windowIdLog which says we have logged mode for the present windowId.
|
|
if (windowIdLog.find(windowId) == windowIdLog.end())
|
|
{
|
|
windowIdLog.insert(pair<int, bool>(windowId, false));
|
|
}
|
|
// if the event is not logged already for the present mode
|
|
if (currentMode != mode)
|
|
{
|
|
currentMode = mode;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"DateCalculatorMode", NavCategory::GetFriendlyName(mode)->Data());
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_DATE_CALCULATOR_VIEWED_IN_SESSION, fields);
|
|
}
|
|
}
|
|
|
|
// call comes here at the time of ApplicationViewModel initialization
|
|
void TraceLogger::LogConverterModeViewed(ViewMode mode, int windowId)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
if (windowIdLog.find(windowId) == windowIdLog.end())
|
|
{
|
|
windowIdLog.insert(pair<int, bool>(windowId, false));
|
|
}
|
|
// if the event is not logged already for the present mode
|
|
if (currentMode != mode)
|
|
{
|
|
currentMode = mode;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"ConverterMode", NavCategory::GetFriendlyName(mode)->Data());
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_CONVERTER_VIEWED_IN_SESSION, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FromMode", fromMode);
|
|
fields.AddString(L"ToMode", toMode);
|
|
fields.AddUInt32(L"MemoryListSize", memorySize);
|
|
LogTelemetryEvent(EVENT_NAME_SHARED_MEMORY_USED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogBitFlipPaneClicked() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogBitFlipUsed() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogAppLaunchStart()
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
if (!isAppLaunchBeginLogged)
|
|
{
|
|
m_appLaunchActivity = g_calculatorProvider.StartActivity(
|
|
EVENT_NAME_APP_LAUNCH_BEGIN,
|
|
nullptr,
|
|
LoggingLevel::Verbose,
|
|
LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
|
|
|
|
isAppLaunchBeginLogged = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogAppLaunchComplete(/*Windows::ApplicationModel::Activation::ActivationKind activationKind, Windows::ApplicationModel::Activation::ApplicationExecutionState executionState*/)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
if ((m_appLaunchActivity != nullptr) && (!isAppLaunchEndLogged))
|
|
{
|
|
m_appLaunchActivity.StopActivity(EVENT_NAME_APP_LAUNCH_END);
|
|
|
|
isAppLaunchEndLogged = true;
|
|
}
|
|
|
|
m_appLaunchActivity = nullptr;
|
|
}
|
|
|
|
void TraceLogger::LogAppResumeComplete()
|
|
{
|
|
if (m_appLaunchActivity != nullptr)
|
|
{
|
|
m_appLaunchActivity.StopActivity(EVENT_NAME_APP_RESUME_END);
|
|
}
|
|
|
|
m_appLaunchActivity = nullptr;
|
|
}
|
|
|
|
void TraceLogger::LogDebug(wstring_view debugData)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"DebugData", debugData);
|
|
LogTelemetryEvent(EVENT_NAME_DEBUG, fields);
|
|
}
|
|
|
|
void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"PreviousExecutionState", previousExecutionState);
|
|
LogTelemetryEvent(EVENT_NAME_PREVIOUS_STATE_WINDOW_ON_CREATION, fields);
|
|
}
|
|
|
|
void TraceLogger::LogAboutFlyoutOpened() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogNavBarOpened() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogClearHistory() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields);
|
|
}
|
|
|
|
void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
// we want to record the event only when history item count is atleast 20
|
|
if (historyItemCount >= 20)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"HistoryItemCount", historyItemCount);
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_FLYOUT_OPEN_BEGIN, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
if (historyItemCount >= 20)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"HistoryItemCount", historyItemCount);
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_FLYOUT_OPEN_END, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogHistoryBodyOpened() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
// we want to record the event only when memory item count is atleast 4
|
|
if (memoryItemCount >= 4)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"MemoryItemCount", memoryItemCount);
|
|
LogTelemetryEvent(EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
if (memoryItemCount >= 4)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"MemoryItemCount", memoryItemCount);
|
|
LogTelemetryEvent(EVENT_NAME_MEMORY_FLYOUT_OPEN_END, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogMemoryBodyOpened() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
|
|
}
|
|
|
|
// If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it.
|
|
// So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that.
|
|
// Use of this function is to analyze perf of mode change.
|
|
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode))
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FromMode", NavCategory::GetFriendlyName(fromMode)->Data());
|
|
fields.AddString(L"ToMode", NavCategory::GetFriendlyName(toMode)->Data());
|
|
fields.AddInt32(L"WindowId", windowId);
|
|
LogMeasureEvent(EVENT_NAME_MODE_CHANGE_BEGIN, fields);
|
|
}
|
|
}
|
|
|
|
// comment: same as LogModeChangeBegin
|
|
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
if (NavCategory::IsValidViewMode(toMode))
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddString(L"ToMode", NavCategory::GetFriendlyName(toMode)->Data());
|
|
fields.AddInt32(L"WindowId", windowId);
|
|
LogMeasureEvent(EVENT_NAME_MODE_CHANGE_END, fields);
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogHistoryItemLoadBegin() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields);
|
|
}
|
|
|
|
void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"HistoryTokenCount", historyTokenCount);
|
|
LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_END, fields);
|
|
}
|
|
|
|
void TraceLogger::LogNewWindowCreationBegin(int windowId)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_NEW_WINDOW_CREATION_BEGIN, fields);
|
|
}
|
|
|
|
void TraceLogger::LogNewWindowCreationEnd(int windowId)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_NEW_WINDOW_CREATION_END, fields);
|
|
}
|
|
|
|
void TraceLogger::LogError(wstring_view errorString)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"ErrorString", errorString);
|
|
LogTelemetryEvent(EVENT_NAME_ERROR, fields);
|
|
}
|
|
|
|
void TraceLogger::LogPrelaunchedAppActivatedByUser()
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields);
|
|
}
|
|
|
|
void TraceLogger::LogAppPrelaunchedBySystem()
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields);
|
|
}
|
|
|
|
void TraceLogger::LogMemoryClearAll(int windowId)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
auto iterMap = s_memoryMap.find(windowId);
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_MEMORY_CLEAR_ALL, fields);
|
|
|
|
if (iterMap != s_memoryMap.end())
|
|
{
|
|
iterMap->second.clear();
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
// Reader lock for the static resources
|
|
reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock);
|
|
auto iterMap = s_memoryMap.find(windowId);
|
|
|
|
if (slotPosition == 0)
|
|
{
|
|
LogSingleMemoryUsed(memorySize);
|
|
}
|
|
else
|
|
{
|
|
LogMultipleMemoryUsed(slotPosition, memorySize);
|
|
}
|
|
|
|
if (iterMap != s_memoryMap.end())
|
|
{
|
|
// if current mode is not equal to mode of memoryMap[slotPosition] then LogSharedMemoryUsed
|
|
if (isStandard && (iterMap->second[slotPosition] != L"Standard"))
|
|
{
|
|
LogSharedMemoryUsed(iterMap->second[slotPosition], L"Standard", memorySize);
|
|
}
|
|
else if (isScientific && (iterMap->second[slotPosition] != L"Scientific"))
|
|
{
|
|
LogSharedMemoryUsed(iterMap->second[slotPosition], L"Scientific", memorySize);
|
|
}
|
|
else if (isProgrammer && (iterMap->second[slotPosition] != L"Programmer"))
|
|
{
|
|
LogSharedMemoryUsed(iterMap->second[slotPosition], L"Programmer", memorySize);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"MemoryIndex", slotPosition);
|
|
fields.AddUInt32(L"MemoryListSize", memorySize);
|
|
LogTelemetryEvent(EVENT_NAME_MULTIPLE_MEMORY_USED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"MemoryListSize", memorySize);
|
|
LogTelemetryEvent(EVENT_NAME_SINGLE_MEMORY_USED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
|
|
fields.AddString(L"Reason", reason);
|
|
fields.AddString(L"ProgrammerNumberBase", GetProgrammerType(programmerNumberBase).c_str());
|
|
fields.AddString(L"BitLengthType", GetProgrammerType(bitLengthType).c_str());
|
|
fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
|
|
LogTelemetryEvent(EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogValidInputPasted(ViewMode mode) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
|
|
LogTelemetryEvent(EVENT_NAME_VALID_INPUT_PASTED, fields);
|
|
}
|
|
|
|
void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FunctionName", functionName);
|
|
wstringstream exceptionMessage;
|
|
exceptionMessage << e.what();
|
|
fields.AddString(L"ExceptionMessage", exceptionMessage.str());
|
|
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
|
|
}
|
|
|
|
void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FunctionName", functionName);
|
|
fields.AddInt32(L"HRESULT", e.code());
|
|
fields.AddString(L"ExceptionMessage", e.message());
|
|
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
|
|
}
|
|
|
|
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception^ e) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FunctionName", functionName);
|
|
fields.AddInt32(L"HRESULT", e->HResult);
|
|
fields.AddString(L"ExceptionMessage", e->Message->Data());
|
|
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
|
|
}
|
|
|
|
void TraceLogger::UpdateFunctionUsage(int funcIndex)
|
|
{
|
|
// Writer lock for the static resources
|
|
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
|
|
|
if (GetIndex(funcIndex))
|
|
{
|
|
// funcIndex is passed by reference and will be having the returned index
|
|
funcLog[funcIndex].count++;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::InitFunctionLogArray()
|
|
{
|
|
int i = -1;
|
|
for (int funcIndex = 0; funcIndex != maxFunctionSize; funcIndex++)
|
|
{
|
|
FunctionLogEnum func = safe_cast<FunctionLogEnum>(funcIndex);
|
|
wstring functionName = func.ToString()->Data();
|
|
if (functionName.compare(L"CalculatorApp.FunctionLogEnum") != 0)
|
|
{
|
|
findIndex[funcIndex] = ++i;
|
|
funcLog.push_back(FuncLog(functionName));
|
|
}
|
|
}
|
|
// update the functionCount with total function count which we are tracking through tracelog.
|
|
functionCount = i;
|
|
}
|
|
|
|
wstring TraceLogger::GetProgrammerType(int index)
|
|
{
|
|
if (index >= 0)
|
|
{
|
|
return s_programmerType[index];
|
|
}
|
|
//return "N/A"
|
|
return s_programmerType[0];
|
|
}
|
|
|
|
bool TraceLogger::GetIndex(int &index)
|
|
{
|
|
if (findIndex[index] > 0)
|
|
{
|
|
index = findIndex[index];
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void TraceLogger::UpdateWindowCount(size_t windowCount)
|
|
{
|
|
maxWindowCount = (maxWindowCount > windowCount) ? maxWindowCount : windowCount;
|
|
windowLaunchCount++;
|
|
}
|
|
|
|
void TraceLogger::LogMaxWindowCount()
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount);
|
|
LogTelemetryEvent(EVENT_NAME_MAX_WINDOW_COUNT, fields);
|
|
}
|
|
|
|
void TraceLogger::LogWindowActivated() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields);
|
|
}
|
|
|
|
void TraceLogger::LogWindowLaunched() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields);
|
|
}
|
|
|
|
void TraceLogger::LogBitLengthButtonUsed(int windowId)
|
|
{
|
|
if (bitLengthButtonUsage.find(windowId) == bitLengthButtonUsage.end())
|
|
{
|
|
bitLengthButtonUsage.insert(pair<int, int>(windowId, 1));
|
|
}
|
|
else
|
|
{
|
|
bitLengthButtonUsage[windowId]++;
|
|
}
|
|
if ((bitLengthButtonUsage[windowId] == 5) && !bitLengthButtonLoggedInSession)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_BITLENGTH_BUTTON_USED, fields);
|
|
|
|
bitLengthButtonLoggedInSession = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogRadixButtonUsed(int windowId)
|
|
{
|
|
if (radixButtonUsage.find(windowId) == radixButtonUsage.end())
|
|
{
|
|
radixButtonUsage.insert(pair<int, int>(windowId, 1));
|
|
}
|
|
else
|
|
{
|
|
radixButtonUsage[windowId]++;
|
|
}
|
|
if ((radixButtonUsage[windowId] == 2) && !radixButtonLoggedInSession)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_RADIX_BUTTON_USED, fields);
|
|
|
|
radixButtonLoggedInSession = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogAngleButtonUsed(int windowId)
|
|
{
|
|
if (angleButtonUsage.find(windowId) == angleButtonUsage.end())
|
|
{
|
|
angleButtonUsage.insert(pair<int, int>(windowId, 1));
|
|
}
|
|
else
|
|
{
|
|
angleButtonUsage[windowId]++;
|
|
}
|
|
if ((angleButtonUsage[windowId] == 2) && !angleButtonLoggedInSession)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_ANGLE_BUTTONS_USED, fields);
|
|
|
|
angleButtonLoggedInSession = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogFunctionUsage(int windowId)
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
for (int i = 0; i < functionCount; i++)
|
|
{
|
|
// log only those functions which are used
|
|
if (funcLog[i].count > 0)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddString(L"FunctionName", funcLog[i].funcName.data());
|
|
fields.AddUInt32(L"UsageCount", funcLog[i].count);
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_FUNCTION_USAGE, fields);
|
|
}
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogHypButtonUsed(int windowId)
|
|
{
|
|
if (!isHypButtonLogged)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_HYP_BUTTON_USED, fields);
|
|
|
|
isHypButtonLogged = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogDateDifferenceModeUsed(int windowId)
|
|
{
|
|
if (!m_dateDiffUsageLoggedInSession)
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddUInt32(L"WindowId", windowId);
|
|
LogTelemetryEvent(EVENT_NAME_DATE_DIFFERENCE_USED, fields);
|
|
|
|
m_dateDiffUsageLoggedInSession = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogDateAddSubtractModeUsed(int windowId, bool isAddMode)
|
|
{
|
|
auto usageMap = isAddMode ? &m_dateAddModeUsage : &m_dateSubtractModeUsage;
|
|
auto isLoggedInSession = isAddMode ? &m_dateAddUsageLoggedInSession : &m_dateSubtractUsageLoggedInSession;
|
|
|
|
if (usageMap->find(windowId) == usageMap->end())
|
|
{
|
|
usageMap->insert(pair<int, int>(windowId, 1));
|
|
}
|
|
else
|
|
{
|
|
(*usageMap)[windowId]++;
|
|
}
|
|
|
|
// Ignore first 3 calls during the initialization of the combo box selected items for Add mode
|
|
int firstChangeEventCount = isAddMode ? 4 : 1;
|
|
|
|
if (((*usageMap)[windowId] == firstChangeEventCount)
|
|
&& (!(*isLoggedInSession)))
|
|
{
|
|
LoggingFields fields{};
|
|
fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract");
|
|
LogTelemetryEvent(EVENT_NAME_DATE_ADD_SUBTRACT_USED, fields);
|
|
|
|
*isLoggedInSession = true;
|
|
}
|
|
}
|
|
|
|
void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
auto calendarSystem = today.GetCalendarSystem();
|
|
auto clock = today.GetClock();
|
|
DateTimeFormatter dtFormatter{
|
|
L"longdate shorttime",
|
|
{ L"en-US" },
|
|
GlobalizationPreferences::HomeGeographicRegion(),
|
|
calendarSystem,
|
|
clock };
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage());
|
|
fields.AddString(L"Timezone", today.GetTimeZone());
|
|
fields.AddString(L"CalendarSystem", calendarSystem);
|
|
fields.AddString(L"Clock", clock);
|
|
fields.AddBoolean(L"IsDaylightSavingTime", today.IsDaylightSavingTime());
|
|
fields.AddString(L"TodayDate", dtFormatter.Format(today.GetDateTime()));
|
|
fields.AddString(L"ClippedDate", dtFormatter.Format(clippedTime));
|
|
LogTelemetryEvent(EVENT_NAME_DATE_DIFFERENCE_FOUND, fields);
|
|
}
|
|
|
|
void TraceLogger::LogUserRequestedRefreshFailed() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(L"UserRequestedRefreshFailed", fields);
|
|
}
|
|
|
|
void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
wstring behaviorString{};
|
|
NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior();
|
|
switch (behavior)
|
|
{
|
|
case NetworkAccessBehavior::Offline:
|
|
behaviorString = L"Offline";
|
|
break;
|
|
|
|
case NetworkAccessBehavior::OptIn:
|
|
behaviorString = L"Metered";
|
|
break;
|
|
|
|
case NetworkAccessBehavior::Normal:
|
|
default:
|
|
behaviorString = L"Online";
|
|
break;
|
|
}
|
|
|
|
LoggingFields fields{};
|
|
fields.AddString(L"NetworkAccess", behaviorString);
|
|
fields.AddString(L"FromValue", fromValue);
|
|
fields.AddString(L"FromUnit", fromUnit);
|
|
fields.AddString(L"ToValue", toValue);
|
|
fields.AddString(L"ToUnit", toUnit);
|
|
LogTelemetryEvent(L"CurrencyConverterInputReceived", fields);
|
|
}
|
|
|
|
void TraceLogger::LogViewClosingTelemetry(int windowId)
|
|
{
|
|
LogFunctionUsage(windowId);
|
|
LogMaxWindowCount();
|
|
}
|
|
|
|
void TraceLogger::LogCoreWindowWasNull() const
|
|
{
|
|
if (!GetTraceLoggingProviderEnabled()) return;
|
|
|
|
LoggingFields fields{};
|
|
LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields);
|
|
}
|
|
}
|
|
|