From 18a1f82035289a19d999a61459f0fa4d56fda73a Mon Sep 17 00:00:00 2001
From: Stephanie Anderl <46726333+sanderl@users.noreply.github.com>
Date: Thu, 12 Mar 2020 14:05:47 -0700
Subject: [PATCH] Graphing Calculator Diagnostics Instrumentation (#1041)
* Add telemetry for keyboard button usage in graphing mode
* Added the diagnostics for EquationAdded and FunctionAnalysis
* Added remaining diagnostics events for graphing calculator
* Fix proj files to include the IsStoreBuild condition. Move the Delayer class to the Calculator/Utils folder
* Ensure the variable textbox has focus before logging diagnostics
* Move maxVariableCount check into the tracelogger class
* Created enums and updated the slider value changed method to remove the variable from the map after the log method is called
* Re-enable hidden lines when the expression is updated
* Fixed extra line in grapher.h and removed the conditional logging for variable count
* Updated logging per PR feedback
* Updated variable logging and fixed issues in the IsEquationLineDisabled binding the EditTextBox control.
* Update per PR feedback
* Added TraceLogging project to contain shared logging logic.
* Updated TraceLogging project and updated tracelogger classes to use the TraceLogging project methods
* Updated VariableLogging to log variable name. And updated per PR comments
* Updated Variables logging to log count changed instead of variable added and fixed issue with variableSliders not being initialized
* Remove outdated tracelogging call caused by rebase
* Updated Delayer class to DispatcherTimerDelayer and fixed some small formatting issues
* Fixed missing Dalyer class name updates
* Removed extra line in traceloger.h
---
src/CalcViewModel/CalcViewModel.vcxproj | 4 +-
.../CalcViewModel.vcxproj.filters | 5 +-
.../Common/CalculatorButtonUser.h | 3 +-
src/CalcViewModel/Common/TraceActivity.h | 55 ----
src/CalcViewModel/Common/TraceLogger.cpp | 305 +++++++-----------
src/CalcViewModel/Common/TraceLogger.h | 58 ++--
.../GraphingSettingsViewModel.cpp | 2 +
.../GraphingSettingsViewModel.h | 10 +
src/Calculator.sln | 18 ++
src/Calculator/Calculator.vcxproj | 4 +-
src/Calculator/Calculator.vcxproj.filters | 4 +
src/Calculator/Controls/EquationTextBox.cpp | 16 +-
src/Calculator/Controls/EquationTextBox.h | 2 +
.../EquationStylePanelControl.xaml.cpp | 2 +
.../EquationStylePanelControl.xaml.h | 1 +
.../Utils/DispatcherTimerDelayer.cpp | 39 +++
src/Calculator/Utils/DispatcherTimerDelayer.h | 26 ++
src/Calculator/Views/Calculator.xaml.cpp | 8 +-
.../GraphingCalculator/EquationInputArea.xaml | 6 +-
.../EquationInputArea.xaml.cpp | 51 +++
.../EquationInputArea.xaml.h | 5 +-
.../GraphingCalculator.xaml | 2 +-
.../GraphingCalculator.xaml.cpp | 12 +
.../GraphingCalculator.xaml.h | 2 +
.../GraphingNumPad.xaml.cpp | 4 +
.../GraphingCalculator/GraphingNumPad.xaml.h | 1 +
src/Calculator/pch.h | 1 +
src/GraphControl/Control/Grapher.cpp | 36 ++-
src/GraphControl/Control/Grapher.h | 4 +
src/GraphControl/GraphControl.vcxproj | 12 +
src/GraphControl/GraphControl.vcxproj.filters | 7 +-
src/GraphControl/Logger/TraceLogger.cpp | 89 +++++
src/GraphControl/Logger/TraceLogger.h | 27 ++
.../Models/KeyGraphFeaturesInfo.cpp | 4 +
src/GraphControl/pch.h | 3 +
src/GraphControl/winrtHeaders.h | 1 +
src/TraceLogging/TraceLogging.vcxproj | 294 +++++++++++++++++
src/TraceLogging/TraceLogging.vcxproj.filters | 17 +
src/TraceLogging/TraceLoggingCommon.cpp | 88 +++++
src/TraceLogging/TraceLoggingCommon.h | 31 ++
src/TraceLogging/pch.cpp | 4 +
src/TraceLogging/pch.h | 10 +
42 files changed, 981 insertions(+), 292 deletions(-)
delete mode 100644 src/CalcViewModel/Common/TraceActivity.h
create mode 100644 src/Calculator/Utils/DispatcherTimerDelayer.cpp
create mode 100644 src/Calculator/Utils/DispatcherTimerDelayer.h
create mode 100644 src/GraphControl/Logger/TraceLogger.cpp
create mode 100644 src/GraphControl/Logger/TraceLogger.h
create mode 100644 src/TraceLogging/TraceLogging.vcxproj
create mode 100644 src/TraceLogging/TraceLogging.vcxproj.filters
create mode 100644 src/TraceLogging/TraceLoggingCommon.cpp
create mode 100644 src/TraceLogging/TraceLoggingCommon.h
create mode 100644 src/TraceLogging/pch.cpp
create mode 100644 src/TraceLogging/pch.h
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj b/src/CalcViewModel/CalcViewModel.vcxproj
index db212ad..c2a69b5 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj
+++ b/src/CalcViewModel/CalcViewModel.vcxproj
@@ -314,7 +314,6 @@
-
@@ -383,6 +382,9 @@
{e727a92b-f149-492c-8117-c039a298719b}
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+
diff --git a/src/CalcViewModel/CalcViewModel.vcxproj.filters b/src/CalcViewModel/CalcViewModel.vcxproj.filters
index 0b3507f..7a0619e 100644
--- a/src/CalcViewModel/CalcViewModel.vcxproj.filters
+++ b/src/CalcViewModel/CalcViewModel.vcxproj.filters
@@ -169,9 +169,6 @@
DataLoaders
-
- Common
-
DataLoaders
@@ -200,7 +197,7 @@
GraphingCalculator
- Common
+ Common
diff --git a/src/CalcViewModel/Common/CalculatorButtonUser.h b/src/CalcViewModel/Common/CalculatorButtonUser.h
index 8afd0fe..bc03b0a 100644
--- a/src/CalcViewModel/Common/CalculatorButtonUser.h
+++ b/src/CalcViewModel/Common/CalculatorButtonUser.h
@@ -202,6 +202,7 @@ public
GreaterThan,
GreaterThanOrEqualTo,
X,
- Y
+ Y,
+ Submit
};
}
diff --git a/src/CalcViewModel/Common/TraceActivity.h b/src/CalcViewModel/Common/TraceActivity.h
deleted file mode 100644
index 003bf6b..0000000
--- a/src/CalcViewModel/Common/TraceActivity.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-#pragma once
-#include
-
-namespace CalculatorApp
-{
- // RAII wrapper that automatically sends the Stop event when the class gets destructed.
- class TraceActivity
- {
- public:
- TraceActivity()
- : m_channel(nullptr)
- , m_activity(nullptr)
- , m_fields(nullptr)
- {
- }
-
- TraceActivity(
- winrt::Windows::Foundation::Diagnostics::LoggingChannel channel,
- std::wstring_view activityName,
- winrt::Windows::Foundation::Diagnostics::LoggingFields fields)
- : m_channel(channel)
- , m_activityName(activityName)
- , m_fields(fields)
- , m_activity(nullptr)
- {
- // Write the activity's START event. Note that you must not specify keyword
- // or level for START and STOP events because they always use the activity's
- // keyword and level.
- m_activity = m_channel.StartActivity(
- m_activityName,
- m_fields,
- winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
- winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
- }
-
- ~TraceActivity()
- {
- if (m_activity != nullptr)
- {
- // Write the activity's STOP event.
- m_activity.StopActivity(m_activityName, m_fields);
- m_activity = nullptr;
- }
- }
-
- private:
- std::wstring m_activityName;
- winrt::Windows::Foundation::Diagnostics::LoggingChannel m_channel;
- winrt::Windows::Foundation::Diagnostics::LoggingFields m_fields;
- winrt::Windows::Foundation::Diagnostics::LoggingActivity m_activity;
- };
-}
diff --git a/src/CalcViewModel/Common/TraceLogger.cpp b/src/CalcViewModel/Common/TraceLogger.cpp
index 845b010..64a99cb 100644
--- a/src/CalcViewModel/Common/TraceLogger.cpp
+++ b/src/CalcViewModel/Common/TraceLogger.cpp
@@ -8,15 +8,15 @@
using namespace CalculatorApp;
using namespace CalculatorApp::Common;
+using namespace TraceLogging;
using namespace Concurrency;
using namespace std;
using namespace Platform;
-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;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+using namespace Windows::Globalization;
+using namespace Windows::Globalization::DateTimeFormatting;
+using namespace Windows::System::UserProfile;
namespace CalculatorApp
{
@@ -35,36 +35,22 @@ namespace CalculatorApp
constexpr auto EVENT_NAME_VISUAL_STATE_CHANGED = L"VisualStateChanged";
constexpr auto EVENT_NAME_CONVERTER_INPUT_RECEIVED = L"ConverterInputReceived";
constexpr auto EVENT_NAME_INPUT_PASTED = L"InputPasted";
+ constexpr auto EVENT_NAME_SHOW_HIDE_BUTTON_CLICKED = L"ShowHideButtonClicked";
+ constexpr auto EVENT_NAME_GRAPH_BUTTON_CLICKED = L"GraphButtonClicked";
+ constexpr auto EVENT_NAME_GRAPH_LINE_STYLE_CHANGED = L"GraphLineStyleChanged";
+ constexpr auto EVENT_NAME_VARIABLE_CHANGED = L"VariableChanged";
+ constexpr auto EVENT_NAME_VARIABLE_SETTING_CHANGED = L"VariableSettingChanged";
+ constexpr auto EVENT_NAME_GRAPH_SETTINGS_CHANGED = L"GraphSettingsChanged";
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_DIAGNOSTICS
- // 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_LEVEL_1 = 0x0000800000000000; // Bit 47
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45
-#else
- // define all Keyword options as 0 when we do not want to upload app diagnostics
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0;
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0;
- constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0;
-#endif
+ constexpr auto CALC_MODE = L"CalcMode";
+ constexpr auto GRAPHING_MODE = L"Graphing";
#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 }),
- GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 })
- , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
- m_appLaunchActivity{ nullptr }
{
- CoCreateGuid(&sessionGuid);
}
TraceLogger ^ TraceLogger::GetInstance()
@@ -73,33 +59,6 @@ namespace CalculatorApp
return s_selfInstance;
}
- bool TraceLogger::GetTraceLoggingProviderEnabled()
- {
- return g_calculatorProvider.Enabled();
- }
-
-#pragma region Tracing methods
- void TraceLogger::LogLevel1Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1));
- }
-
- void TraceLogger::LogLevel2Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2));
- }
-
- void TraceLogger::LogLevel3Event(wstring_view eventName, LoggingFields fields)
- {
- g_calculatorProvider.LogEvent(eventName, fields, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3));
- }
-
- unique_ptr TraceLogger::CreateTraceActivity(wstring_view eventName, LoggingFields fields)
- {
- return make_unique(g_calculatorProvider, eventName, fields);
- }
-#pragma endregion
-
// return true if windowId is logged once else return false
bool TraceLogger::IsWindowIdInLog(int windowId)
{
@@ -116,18 +75,12 @@ namespace CalculatorApp
void TraceLogger::LogVisualStateChanged(ViewMode mode, String ^ state, bool isAlwaysOnTop)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
+ auto fields = ref new LoggingFields();
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"VisualState", state->Data());
- fields.AddBoolean(L"IsAlwaysOnTop", isAlwaysOnTop);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_VISUAL_STATE_CHANGED, fields);
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"VisualState"), state);
+ fields->AddBoolean(StringReference(L"IsAlwaysOnTop"), isAlwaysOnTop);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VISUAL_STATE_CHANGED), fields);
}
void TraceLogger::LogWindowCreated(ViewMode mode, int windowId)
@@ -138,122 +91,69 @@ namespace CalculatorApp
windowIdLog.push_back(windowId);
}
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(L"NumOfOpenWindows", currentWindowCount);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_WINDOW_ON_CREATED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddUInt64(StringReference(L"NumOfOpenWindows"), currentWindowCount);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_WINDOW_ON_CREATED), fields);
}
void TraceLogger::LogModeChange(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
if (NavCategory::IsValidViewMode(mode))
{
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_MODE_CHANGED, fields);
+ auto fields = ref new LoggingFields();
+ ;
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MODE_CHANGED), fields);
}
}
void TraceLogger::LogHistoryItemLoad(ViewMode mode, int historyListSize, int loadedIndex)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddInt32(L"HistoryListSize", historyListSize);
- fields.AddInt32(L"HistoryItemIndex", loadedIndex);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_HISTORY_ITEM_LOAD, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddInt32(StringReference(L"HistoryListSize"), historyListSize);
+ fields->AddInt32(StringReference(L"HistoryItemIndex"), loadedIndex);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_HISTORY_ITEM_LOAD), fields);
}
void TraceLogger::LogMemoryItemLoad(ViewMode mode, int memoryListSize, int loadedIndex)
{
- if (!GetTraceLoggingProviderEnabled())
- {
- return;
- }
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddInt32(L"MemoryListSize", memoryListSize);
- fields.AddInt32(L"MemoryItemIndex", loadedIndex);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_MEMORY_ITEM_LOAD, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddInt32(StringReference(L"MemoryListSize"), memoryListSize);
+ fields->AddInt32(StringReference(L"MemoryItemIndex"), loadedIndex);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MEMORY_ITEM_LOAD), fields);
}
void TraceLogger::LogError(ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName->Data());
- fields.AddString(L"Message", errorString->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), functionName);
+ fields->AddString(StringReference(L"Message"), errorString);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::LogStandardException(ViewMode mode, wstring_view functionName, const exception& e)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data()));
wstringstream exceptionMessage;
exceptionMessage << e.what();
- fields.AddString(L"Message", exceptionMessage.str());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
- }
-
- void TraceLogger::LogWinRTException(ViewMode mode, wstring_view functionName, hresult_error const& e)
- {
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
- fields.AddString(L"Message", e.message());
- fields.AddInt32(L"HRESULT", e.code());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ fields->AddString(StringReference(L"Message"), StringReference(exceptionMessage.str().data()));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::LogPlatformException(ViewMode mode, wstring_view functionName, Platform::Exception ^ e)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddString(L"FunctionName", functionName);
- fields.AddString(L"Message", e->Message->Data());
- fields.AddInt32(L"HRESULT", e->HResult);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_EXCEPTION, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ fields->AddString(StringReference(L"FunctionName"), StringReference(functionName.data()));
+ fields->AddString(StringReference(L"Message"), e->Message);
+ fields->AddInt32(StringReference(L"HRESULT"), e->HResult);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EXCEPTION), fields);
}
void TraceLogger::UpdateButtonUsage(NumbersAndOperatorsEnum button, ViewMode mode)
@@ -305,9 +205,6 @@ namespace CalculatorApp
void TraceLogger::LogButtonUsage()
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
// Writer lock for the buttonLog resource
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
@@ -330,11 +227,9 @@ namespace CalculatorApp
}
}
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"ButtonUsage", buttonUsageString->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_BUTTON_USAGE, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(L"ButtonUsage"), buttonUsageString);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_BUTTON_USAGE), fields);
buttonLog.clear();
}
@@ -342,46 +237,78 @@ namespace CalculatorApp
void TraceLogger::LogDateCalculationModeUsed(bool AddSubtractMode)
{
const wchar_t* calculationType = AddSubtractMode ? L"AddSubtractMode" : L"DateDifferenceMode";
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(ViewMode::Date)->Data());
- fields.AddString(L"CalculationType", calculationType);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_DATE_CALCULATION_MODE_USED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(ViewMode::Date));
+ fields->AddString(StringReference(L"CalculationType"), StringReference(calculationType));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_DATE_CALCULATION_MODE_USED), fields);
}
void TraceLogger::LogConverterInputReceived(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"CalcMode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_CONVERTER_INPUT_RECEIVED, fields);
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_CONVERTER_INPUT_RECEIVED), fields);
}
void TraceLogger::LogNavBarOpened()
{
- if (!GetTraceLoggingProviderEnabled())
- return;
-
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_NAV_BAR_OPENED, fields);
+ auto fields = ref new LoggingFields();
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_NAV_BAR_OPENED), fields);
}
void TraceLogger::LogInputPasted(ViewMode mode)
{
- if (!GetTraceLoggingProviderEnabled())
- return;
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), NavCategory::GetFriendlyName(mode));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_INPUT_PASTED), fields);
+ }
- LoggingFields fields{};
- fields.AddGuid(L"SessionGuid", sessionGuid);
- fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
- fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
- LogLevel2Event(EVENT_NAME_INPUT_PASTED, fields);
+ void TraceLogger::LogShowHideButtonClicked(bool isHideButton)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddBoolean(StringReference(L"IsHideButton"), isHideButton);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_SHOW_HIDE_BUTTON_CLICKED), fields);
+ }
+
+ void TraceLogger::LogGraphButtonClicked(GraphButton buttonName)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(StringReference(L"ButtonName"), static_cast(buttonName));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_BUTTON_CLICKED), fields);
+ }
+
+ void TraceLogger::LogGraphLineStyleChanged(LineStyleType style)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(StringReference(L"StyleType"), static_cast(style));
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_LINE_STYLE_CHANGED), fields);
+ }
+
+ void TraceLogger::LogVariableChanged(String ^ inputChangedType, String ^ variableName)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddString(StringReference(L"InputChangedType"), inputChangedType);
+ fields->AddString(StringReference(L"VariableName"), variableName);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLE_CHANGED), fields);
+ }
+ void TraceLogger::LogVariableSettingsChanged(String ^ setting)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddString(StringReference(L"SettingChanged"), setting);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLE_SETTING_CHANGED), fields);
+ }
+
+ void TraceLogger::LogGraphSettingsChanged(GraphSettingsType settingType)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt16(L"SettingType", static_cast(settingType));
+
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_GRAPH_SETTINGS_CHANGED), fields);
}
}
diff --git a/src/CalcViewModel/Common/TraceLogger.h b/src/CalcViewModel/Common/TraceLogger.h
index fa24f8e..37e4b2b 100644
--- a/src/CalcViewModel/Common/TraceLogger.h
+++ b/src/CalcViewModel/Common/TraceLogger.h
@@ -3,13 +3,9 @@
#pragma once
-#include "CalcManager/Command.h"
-#include "TraceActivity.h"
#include "NavCategory.h"
#include "CalculatorButtonUser.h"
-static const int maxFunctionSize = (int)CalculationManager::Command::CommandBINEDITEND;
-
// A trace logging provider can only be instantiated and registered once per module.
// This class implements a singleton model ensure that only one instance is created.
namespace CalculatorApp
@@ -28,12 +24,35 @@ namespace CalculatorApp
}
};
-public
- ref class TraceLogger sealed
+ public enum class GraphSettingsType
+ {
+ Grid,
+ TrigUnits
+ };
+
+ public enum class GraphButton
+ {
+ StylePicker,
+ RemoveFunction,
+ ActiveTracingChecked,
+ ActiveTracingUnchecked,
+ GraphSettings,
+ Share,
+ ZoomIn,
+ ZoomOut,
+ ZoomReset
+ };
+
+ public enum class LineStyleType
+ {
+ Color
+ };
+
+ public ref class TraceLogger sealed
{
public:
static TraceLogger ^ GetInstance();
- bool GetTraceLoggingProviderEnabled();
+
void LogModeChange(CalculatorApp::Common::ViewMode mode);
void LogHistoryItemLoad(CalculatorApp::Common::ViewMode mode, int historyListSize, int loadedIndex);
void LogMemoryItemLoad(CalculatorApp::Common::ViewMode mode, int memoryListSize, int loadedIndex);
@@ -48,9 +67,14 @@ public
void LogConverterInputReceived(CalculatorApp::Common::ViewMode mode);
void LogNavBarOpened();
void LogError(CalculatorApp::Common::ViewMode mode, Platform::String ^ functionName, Platform::String ^ errorString);
- internal :
+ void LogShowHideButtonClicked(bool isHideButton);
+ void LogGraphButtonClicked(GraphButton buttonName);
+ void LogGraphLineStyleChanged(LineStyleType style);
+ void LogVariableChanged(Platform::String ^ inputChangedType, Platform::String ^ variableName);
+ void LogVariableSettingsChanged(Platform::String ^ setting);
+ void LogGraphSettingsChanged(GraphSettingsType settingsType);
+ internal:
void LogStandardException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ const std::exception& e);
- void LogWinRTException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ winrt::hresult_error const& e);
void LogPlatformException(CalculatorApp::Common::ViewMode mode, std::wstring_view functionName, _In_ Platform::Exception ^ e);
void LogInputPasted(CalculatorApp::Common::ViewMode mode);
@@ -58,24 +82,8 @@ public
// Create an instance of TraceLogger
TraceLogger();
- // As mentioned in Microsoft's Privacy Statement(https://privacy.microsoft.com/en-US/privacystatement#maindiagnosticsmodule),
- // sampling is involved in Microsoft's diagnostic data collection process.
- // These keywords provide additional input into how frequently an event might be sampled.
- // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled.
- void LogLevel1Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
- void LogLevel2Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
- void LogLevel3Event(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
-
- std::unique_ptr CreateTraceActivity(std::wstring_view activityName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields);
-
- winrt::Windows::Foundation::Diagnostics::LoggingChannel g_calculatorProvider;
-
std::vector buttonLog;
std::vector windowIdLog;
-
- GUID sessionGuid;
uint64 currentWindowCount = 0;
-
- winrt::Windows::Foundation::Diagnostics::LoggingActivity m_appLaunchActivity;
};
}
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
index a1031a1..4313e26 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
+++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.cpp
@@ -99,6 +99,8 @@ void GraphingSettingsViewModel::UpdateDisplayRange()
}
m_Graph->SetDisplayRanges(m_XMinValue, m_XMaxValue, m_YMinValue, m_YMaxValue);
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::Grid);
}
bool GraphingSettingsViewModel::HasError()
diff --git a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
index 60c5e16..cdead6f 100644
--- a/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
+++ b/src/CalcViewModel/GraphingCalculator/GraphingSettingsViewModel.h
@@ -2,6 +2,7 @@
// Licensed under the MIT License.
#include "../Common/Utils.h"
+#include "CalcViewModel/Common/TraceLogger.h"
namespace CalculatorApp::ViewModel
{
@@ -226,9 +227,12 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Radians)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Radians;
+
RaisePropertyChanged(L"TrigModeRadians");
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeGradians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits);
}
}
}
@@ -244,9 +248,12 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Degrees)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Degrees;
+
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeRadians");
RaisePropertyChanged(L"TrigModeGradians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits);
}
}
}
@@ -262,9 +269,12 @@ namespace CalculatorApp::ViewModel
if (value && m_Graph != nullptr && m_Graph->TrigUnitMode != (int)Graphing::EvalTrigUnitMode::Grads)
{
m_Graph->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Grads;
+
RaisePropertyChanged(L"TrigModeGradians");
RaisePropertyChanged(L"TrigModeDegrees");
RaisePropertyChanged(L"TrigModeRadians");
+
+ TraceLogger::GetInstance()->LogGraphSettingsChanged(GraphSettingsType::TrigUnits);
}
}
}
diff --git a/src/Calculator.sln b/src/Calculator.sln
index 717c6b8..ce6eb3b 100644
--- a/src/Calculator.sln
+++ b/src/Calculator.sln
@@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphingImpl", "GraphingImp
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GraphControl", "GraphControl\GraphControl.vcxproj", "{E727A92B-F149-492C-8117-C039A298719B}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TraceLogging", "TraceLogging\TraceLogging.vcxproj", "{FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|ARM = Debug|ARM
@@ -173,6 +175,22 @@ Global
{E727A92B-F149-492C-8117-C039A298719B}.Release|x64.Build.0 = Release|x64
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.ActiveCfg = Release|Win32
{E727A92B-F149-492C-8117-C039A298719B}.Release|x86.Build.0 = Release|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM.ActiveCfg = Debug|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM.Build.0 = Debug|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|ARM64.Build.0 = Debug|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x64.ActiveCfg = Debug|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x64.Build.0 = Debug|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x86.ActiveCfg = Debug|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Debug|x86.Build.0 = Debug|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM.ActiveCfg = Release|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM.Build.0 = Release|ARM
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM64.ActiveCfg = Release|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|ARM64.Build.0 = Release|ARM64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.ActiveCfg = Release|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x64.Build.0 = Release|x64
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.ActiveCfg = Release|Win32
+ {FC81FF41-02CD-4CD9-9BC5-45A1E39AC6ED}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/src/Calculator/Calculator.vcxproj b/src/Calculator/Calculator.vcxproj
index ae19536..98f041c 100644
--- a/src/Calculator/Calculator.vcxproj
+++ b/src/Calculator/Calculator.vcxproj
@@ -17,7 +17,7 @@
black
Always
TemporaryKey.pfx
- true
+ True
False
@@ -262,6 +262,7 @@
+
App.xaml
@@ -431,6 +432,7 @@
+
Create
Create
diff --git a/src/Calculator/Calculator.vcxproj.filters b/src/Calculator/Calculator.vcxproj.filters
index 5b6e9ec..6365b6f 100644
--- a/src/Calculator/Calculator.vcxproj.filters
+++ b/src/Calculator/Calculator.vcxproj.filters
@@ -328,6 +328,7 @@
Common
+
@@ -435,6 +436,7 @@
Common
+
@@ -1537,5 +1539,7 @@
+
+
\ No newline at end of file
diff --git a/src/Calculator/Controls/EquationTextBox.cpp b/src/Calculator/Controls/EquationTextBox.cpp
index 48f84ec..5a607eb 100644
--- a/src/Calculator/Controls/EquationTextBox.cpp
+++ b/src/Calculator/Controls/EquationTextBox.cpp
@@ -27,6 +27,7 @@ DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, EquationButtonContentIndex);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, HasError);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsAddEquationMode);
DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, MathEquation);
+DEPENDENCY_PROPERTY_INITIALIZATION(EquationTextBox, IsEquationLineDisabled);
EquationTextBox::EquationTextBox()
{
@@ -69,9 +70,8 @@ void EquationTextBox::OnApplyTemplate()
auto toolTip = ref new ToolTip();
auto equationButtonMessage = LocalizationStringUtil::GetLocalizedString(
- m_equationButton->IsChecked->Value ? resProvider->GetResourceString(L"showEquationButtonToolTip")
- : resProvider->GetResourceString(L"hideEquationButtonToolTip"),
- EquationButtonContentIndex);
+ IsEquationLineDisabled ? resProvider->GetResourceString(L"showEquationButtonToolTip")
+ : resProvider->GetResourceString(L"hideEquationButtonToolTip"), EquationButtonContentIndex);
toolTip->Content = equationButtonMessage;
ToolTipService::SetToolTip(m_equationButton, toolTip);
@@ -238,9 +238,8 @@ void EquationTextBox::OnEquationButtonClicked(Object ^ sender, RoutedEventArgs ^
auto resProvider = AppResourceProvider::GetInstance();
auto equationButtonMessage = LocalizationStringUtil::GetLocalizedString(
- m_equationButton->IsChecked->Value ? resProvider->GetResourceString(L"showEquationButtonToolTip")
- : resProvider->GetResourceString(L"hideEquationButtonToolTip"),
- EquationButtonContentIndex);
+ IsEquationLineDisabled ? resProvider->GetResourceString(L"showEquationButtonToolTip")
+ : resProvider->GetResourceString(L"hideEquationButtonToolTip"), EquationButtonContentIndex);
toolTip->Content = equationButtonMessage;
ToolTipService::SetToolTip(m_equationButton, toolTip);
@@ -269,9 +268,11 @@ void EquationTextBox::OnRemoveButtonClicked(Object ^ sender, RoutedEventArgs ^ e
if (m_equationButton)
{
- m_equationButton->IsChecked = false;
+ IsEquationLineDisabled = false;
}
+ TraceLogger::GetInstance()->LogGraphButtonClicked(GraphButton::RemoveFunction);
+
VisualStateManager::GoToState(this, "Normal", true);
}
@@ -280,6 +281,7 @@ void EquationTextBox::OnColorChooserButtonClicked(Object ^ sender, RoutedEventAr
if (ColorChooserFlyout != nullptr && m_richEditBox != nullptr)
{
ColorChooserFlyout->ShowAt(m_richEditBox);
+ TraceLogger::GetInstance()->LogGraphButtonClicked(GraphButton::StylePicker);
}
}
diff --git a/src/Calculator/Controls/EquationTextBox.h b/src/Calculator/Controls/EquationTextBox.h
index 1a5e881..cb768a6 100644
--- a/src/Calculator/Controls/EquationTextBox.h
+++ b/src/Calculator/Controls/EquationTextBox.h
@@ -6,6 +6,7 @@
#include "CalcViewModel/Common/Utils.h"
#include "CalcViewModel/GraphingCalculator/EquationViewModel.h"
#include "Calculator/Controls/MathRichEditBox.h"
+#include "CalcViewModel/Common/TraceLogger.h"
namespace CalculatorApp
{
@@ -24,6 +25,7 @@ namespace CalculatorApp
DEPENDENCY_PROPERTY(Platform::String ^, MathEquation);
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, HasError);
DEPENDENCY_PROPERTY_WITH_CALLBACK(bool, IsAddEquationMode);
+ DEPENDENCY_PROPERTY(bool, IsEquationLineDisabled);
PROPERTY_R(bool, HasFocus);
diff --git a/src/Calculator/EquationStylePanelControl.xaml.cpp b/src/Calculator/EquationStylePanelControl.xaml.cpp
index e143d07..f35861b 100644
--- a/src/Calculator/EquationStylePanelControl.xaml.cpp
+++ b/src/Calculator/EquationStylePanelControl.xaml.cpp
@@ -41,6 +41,8 @@ void EquationStylePanelControl::SelectionChanged(Object ^ /*sender */, Selection
{
SelectedColor = brush->Color;
}
+
+ TraceLogger::GetInstance()->LogGraphLineStyleChanged(LineStyleType::Color);
}
}
diff --git a/src/Calculator/EquationStylePanelControl.xaml.h b/src/Calculator/EquationStylePanelControl.xaml.h
index b3c3aab..4876e7b 100644
--- a/src/Calculator/EquationStylePanelControl.xaml.h
+++ b/src/Calculator/EquationStylePanelControl.xaml.h
@@ -5,6 +5,7 @@
#include "EquationStylePanelControl.g.h"
#include "CalcViewModel/Common/Utils.h"
+#include "CalcViewModel/Common/TraceLogger.h"
namespace CalculatorApp
{
diff --git a/src/Calculator/Utils/DispatcherTimerDelayer.cpp b/src/Calculator/Utils/DispatcherTimerDelayer.cpp
new file mode 100644
index 0000000..219b416
--- /dev/null
+++ b/src/Calculator/Utils/DispatcherTimerDelayer.cpp
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "DispatcherTimerDelayer.h"
+
+using namespace CalculatorApp;
+using namespace Windows::UI::Xaml;
+using namespace Windows::Foundation;
+
+DispatcherTimerDelayer::DispatcherTimerDelayer(TimeSpan timeSpan)
+{
+ m_timer = ref new DispatcherTimer();
+ m_timer->Interval = timeSpan;
+ auto interval = m_timer->Interval;
+ m_timer->Tick += ref new EventHandler
+
+
+ /DSEND_DIAGNOSTICS %(AdditionalOptions)
+
+
+
@@ -301,6 +307,7 @@
+
@@ -322,6 +329,11 @@
{52E03A58-B378-4F50-8BFB-F659FB85E790}
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+
+
\ No newline at end of file
diff --git a/src/GraphControl/GraphControl.vcxproj.filters b/src/GraphControl/GraphControl.vcxproj.filters
index 2b7c4e9..e9d9d8f 100644
--- a/src/GraphControl/GraphControl.vcxproj.filters
+++ b/src/GraphControl/GraphControl.vcxproj.filters
@@ -32,6 +32,7 @@
Models
+
@@ -59,6 +60,7 @@
Models
+
@@ -66,9 +68,8 @@
-
-
-
+
+
diff --git a/src/GraphControl/Logger/TraceLogger.cpp b/src/GraphControl/Logger/TraceLogger.cpp
new file mode 100644
index 0000000..8654f2e
--- /dev/null
+++ b/src/GraphControl/Logger/TraceLogger.cpp
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "TraceLogger.h"
+
+using namespace TraceLogging;
+using namespace Concurrency;
+using namespace std;
+using namespace Platform;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+using namespace Windows::Globalization;
+
+namespace GraphControl
+{
+ static reader_writer_lock s_traceLoggerLock;
+
+ constexpr auto GRAPHING_MODE = L"Graphing";
+ constexpr auto CALC_MODE = L"CalcMode";
+
+ // Diagnostics events. Uploaded to asimov.
+ constexpr auto EVENT_NAME_EQUATION_COUNT_CHANGED = L"EquationCountChanged";
+ constexpr auto EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED = L"FunctionAnalysisPerformed";
+ constexpr auto EVENT_NAME_VARIABLES_COUNT_CHANGED = L"VariablesCountChanged";
+
+ TraceLogger ^ TraceLogger::GetInstance()
+ {
+ static TraceLogger ^ s_selfInstance = ref new TraceLogger();
+ return s_selfInstance;
+ }
+
+ void TraceLogger::LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations)
+ {
+ static bool firstRun = true;
+ if (firstRun)
+ {
+ firstRun = false;
+ return;
+ }
+
+ // Update the total valid/invalid equations to record the max value.
+ // Equations are added/removed/updated one at a time, so we know either
+ // currentValidEquations or currentInvalidEquations increased,
+ // but they cannot both increase at the same time
+ // If an equation was removed, do not decrement the total count.
+ static uint64 TotalValidEquations = 0;
+ static uint64 TotalInvalidEquations = 0;
+ static uint64 PreviousValidEquations = 0;
+ static uint64 PreviousInvalidEquations = 0;
+
+ if (currentValidEquations > PreviousValidEquations)
+ {
+ TotalValidEquations++;
+ }
+ else if (currentInvalidEquations > PreviousInvalidEquations)
+ {
+ TotalInvalidEquations++;
+ }
+
+ PreviousValidEquations = currentValidEquations;
+ PreviousInvalidEquations = currentInvalidEquations;
+
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddUInt64(StringReference(L"ConcurrentValidFunctions"), currentValidEquations);
+ fields->AddUInt64(StringReference(L"ConcurrentInvalidFunctions"), currentInvalidEquations);
+ fields->AddUInt64(StringReference(L"TotalValidFunctions"), TotalValidEquations);
+ fields->AddUInt64(StringReference(L"TotalInvalidFunctions"), TotalInvalidEquations);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_EQUATION_COUNT_CHANGED), fields);
+ }
+
+ void TraceLogger::LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt32(StringReference(L"AnalysisErrorType"), analysisErrorType);
+ fields->AddUInt32(StringReference(L"TooComplexFeatures"), tooComplexFlag);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED), fields);
+ }
+
+ void TraceLogger::LogVariableCountChanged(int variablesCount)
+ {
+ auto fields = ref new LoggingFields();
+ fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
+ fields->AddInt64(StringReference(L"VariableCount"), variablesCount);
+ TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLES_COUNT_CHANGED), fields);
+ }
+}
diff --git a/src/GraphControl/Logger/TraceLogger.h b/src/GraphControl/Logger/TraceLogger.h
new file mode 100644
index 0000000..682c668
--- /dev/null
+++ b/src/GraphControl/Logger/TraceLogger.h
@@ -0,0 +1,27 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include "Common.h"
+
+// A trace logging provider can only be instantiated and registered once per module.
+// This class implements a singleton model ensure that only one instance is created.
+namespace GraphControl
+{
+
+ public ref class TraceLogger sealed
+ {
+ internal:
+ static TraceLogger ^ GetInstance();
+
+ void LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations);
+ void LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag);
+ void LogVariableCountChanged(int variablesCount);
+
+ private:
+ TraceLogger()
+ {
+ }
+ };
+}
diff --git a/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp b/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
index 3d5a7d2..ca48f5c 100644
--- a/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
+++ b/src/GraphControl/Models/KeyGraphFeaturesInfo.cpp
@@ -59,6 +59,8 @@ KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(IGraphFunctionAnalysisData d
res->ObliqueAsymptotes = ConvertWStringVector(data.ObliqueAsymptotes);
res->TooComplexFeatures = data.TooComplexFeatures;
res->AnalysisError = CalculatorApp::AnalysisErrorType::NoError;
+
+ TraceLogger::GetInstance()->LogFunctionAnalysisPerformed(CalculatorApp::AnalysisErrorType::NoError, res->TooComplexFeatures);
return res;
}
@@ -66,5 +68,7 @@ KeyGraphFeaturesInfo ^ KeyGraphFeaturesInfo::Create(CalculatorApp::AnalysisError
{
auto res = ref new KeyGraphFeaturesInfo();
res->AnalysisError = type;
+
+ TraceLogger::GetInstance()->LogFunctionAnalysisPerformed(type, 0);
return res;
}
diff --git a/src/GraphControl/pch.h b/src/GraphControl/pch.h
index 2861384..7906103 100644
--- a/src/GraphControl/pch.h
+++ b/src/GraphControl/pch.h
@@ -1,3 +1,6 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
#pragma once
//C4453: A '[WebHostHidden]' type should not be used on the published surface of a public type that is not '[WebHostHidden]'
diff --git a/src/GraphControl/winrtHeaders.h b/src/GraphControl/winrtHeaders.h
index 971dfd3..3730cb5 100644
--- a/src/GraphControl/winrtHeaders.h
+++ b/src/GraphControl/winrtHeaders.h
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
template
diff --git a/src/TraceLogging/TraceLogging.vcxproj b/src/TraceLogging/TraceLogging.vcxproj
new file mode 100644
index 0000000..ba0a960
--- /dev/null
+++ b/src/TraceLogging/TraceLogging.vcxproj
@@ -0,0 +1,294 @@
+
+
+
+
+ Debug
+ ARM
+
+
+ Debug
+ ARM64
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ ARM
+
+
+ Release
+ ARM64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ {fc81ff41-02cd-4cd9-9bc5-45a1e39ac6ed}
+ WindowsRuntimeComponent
+ TraceLogging
+ en-US
+ 14.0
+ true
+ Windows Store
+ 10.0.18362.0
+ 10.0.17134.0
+ 10.0
+
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+ DynamicLibrary
+ false
+ true
+ v142
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj /await /std:c++17 /utf-8 %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ Use
+ _WINRT_DLL;NDEBUG;%(PreprocessorDefinitions)
+ pch.h
+ $(IntDir)pch.pch
+ $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)
+ /bigobj %(AdditionalOptions)
+ 28204
+
+
+ Console
+ false
+
+
+
+
+ /DSEND_DIAGNOSTICS %(AdditionalOptions)
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TraceLogging/TraceLogging.vcxproj.filters b/src/TraceLogging/TraceLogging.vcxproj.filters
new file mode 100644
index 0000000..23e4274
--- /dev/null
+++ b/src/TraceLogging/TraceLogging.vcxproj.filters
@@ -0,0 +1,17 @@
+
+
+
+
+ 32f35fa0-613c-4f4e-b062-c61ab420e23b
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/TraceLogging/TraceLoggingCommon.cpp b/src/TraceLogging/TraceLoggingCommon.cpp
new file mode 100644
index 0000000..715bb8c
--- /dev/null
+++ b/src/TraceLogging/TraceLoggingCommon.cpp
@@ -0,0 +1,88 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
+#include "TraceLoggingCommon.h"
+
+using namespace TraceLogging;
+using namespace std;
+using namespace Platform;;
+using namespace Windows::Foundation;
+using namespace Windows::Foundation::Diagnostics;
+
+#ifdef SEND_DIAGNOSTICS
+// 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_LEVEL_1 = 0x0000800000000000; // Bit 47
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0x0000400000000000; // Bit 46
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0x0000200000000000; // Bit 45
+#else
+// define all Keyword options as 0 when we do not want to upload app diagnostics
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_1 = 0;
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_2 = 0;
+constexpr int64_t MICROSOFT_KEYWORD_LEVEL_3 = 0;
+#endif
+
+constexpr auto SESSION_GUID = L"SessionGuid";
+constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
+constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
+
+TraceLoggingCommon::TraceLoggingCommon()
+ : g_calculatorProvider(
+ ref new LoggingChannel(
+ L"MicrosoftCalculator",
+ ref new LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }),
+ GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }))
+ , // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
+ m_appLaunchActivity{ nullptr }
+{
+ CoCreateGuid(&sessionGuid);
+}
+
+ TraceLoggingCommon ^ TraceLoggingCommon::GetInstance()
+{
+ static TraceLoggingCommon ^ s_selfInstance = ref new TraceLoggingCommon();
+ return s_selfInstance;
+}
+
+bool TraceLoggingCommon::GetTraceLoggingProviderEnabled()
+{
+ return g_calculatorProvider->Enabled;
+}
+
+void TraceLoggingCommon::LogLevel1Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_1));
+}
+
+void TraceLoggingCommon::LogLevel2Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_2));
+}
+
+void TraceLoggingCommon::LogLevel3Event(String ^ eventName, LoggingFields ^ fields)
+{
+ if (!GetTraceLoggingProviderEnabled())
+ {
+ return;
+ }
+
+ fields->AddGuid(ref new String(SESSION_GUID), sessionGuid);
+ fields->AddUInt64(ref new String(PDT_PRIVACY_DATA_TAG), PDT_PRODUCT_AND_SERVICE_USAGE);
+ g_calculatorProvider->LogEvent(eventName, fields, LoggingLevel::Verbose, ref new LoggingOptions(MICROSOFT_KEYWORD_LEVEL_3));
+}
diff --git a/src/TraceLogging/TraceLoggingCommon.h b/src/TraceLogging/TraceLoggingCommon.h
new file mode 100644
index 0000000..c81253d
--- /dev/null
+++ b/src/TraceLogging/TraceLoggingCommon.h
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+namespace TraceLogging
+{
+ public ref class TraceLoggingCommon sealed
+ {
+ public:
+ static TraceLoggingCommon ^ GetInstance();
+
+ // As mentioned in Microsoft's Privacy Statement(https://privacy.microsoft.com/en-US/privacystatement#maindiagnosticsmodule),
+ // sampling is involved in Microsoft's diagnostic data collection process.
+ // These keywords provide additional input into how frequently an event might be sampled.
+ // The lower the level of the keyword, the higher the possibility that the corresponding event may be sampled.
+ void LogLevel1Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+ void LogLevel2Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+ void LogLevel3Event(Platform::String ^ eventName, Windows::Foundation::Diagnostics::LoggingFields ^ fields);
+
+ bool GetTraceLoggingProviderEnabled();
+
+ private:
+ TraceLoggingCommon();
+
+
+ Windows::Foundation::Diagnostics::LoggingChannel ^ g_calculatorProvider;
+ Windows::Foundation::Diagnostics::LoggingActivity ^ m_appLaunchActivity;
+ GUID sessionGuid;
+ };
+}
diff --git a/src/TraceLogging/pch.cpp b/src/TraceLogging/pch.cpp
new file mode 100644
index 0000000..b175e3f
--- /dev/null
+++ b/src/TraceLogging/pch.cpp
@@ -0,0 +1,4 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#include "pch.h"
diff --git a/src/TraceLogging/pch.h b/src/TraceLogging/pch.h
new file mode 100644
index 0000000..f1d2ac3
--- /dev/null
+++ b/src/TraceLogging/pch.h
@@ -0,0 +1,10 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+#pragma once
+
+#include
+#include
+
+// C++\WinRT Headers
+#include "Windows.Foundation.Diagnostics.h"