terminal/src/terminal/parser/telemetry.cpp
Dustin Howett c910045187 Merged PR 3315789: Migrate GitHub changes up until cfc72cee
* cfc72cee (origin/dev/duhowett/ibxint, github/master) Make sure cursor blinks after opening new tab (1030)
* 9ad25440 Fix #936: misuse of uninitialized objects causes AppVerifier breaks on Windows Terminal startup (1015)
* 5f938a04 Update Terminal.cpp (1034)
* 4c47631b Cleanup - termDispatch.hpp & adaptDispatch.hpp overrides (1004)
* cc304759 add audit mode to ci (948)
* 80f10796 Fix the bell sound when Alt+key is pressed. (1006)
* 42e87ed3 fix build break from using `await` instead of `co_await` (1009)
* 40b557a4 Update manifest to correct 1903 version, unref param fix (1008)
* 0f62ec81 Eat all tap keypresses no matter what. (985)
* ce0eaab9 inbox: Merge accumulated build fixes from RS_ONECORE_DEP_ACIOSS (1002)
* 1c509683 add .editorconfig file (585)
* efd69990 Add support for OSC 10 and 11 to set the default colors (891)

Related work items: #21610659, #21838182
2019-05-28 22:51:48 +00:00

254 lines
9.6 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include <precomp.h>
#include "telemetry.hpp"
TRACELOGGING_DEFINE_PROVIDER(g_hConsoleVirtTermParserEventTraceProvider,
"Microsoft.Windows.Console.VirtualTerminal.Parser",
// {c9ba2a84-d3ca-5e19-2bd6-776a0910cb9d}
(0xc9ba2a84, 0xd3ca, 0x5e19, 0x2b, 0xd6, 0x77, 0x6a, 0x09, 0x10, 0xcb, 0x9d));
using namespace Microsoft::Console::VirtualTerminal;
#pragma warning(push)
// Disable 4351 so we can initialize the arrays to 0 without a warning.
#pragma warning(disable:4351)
TermTelemetry::TermTelemetry()
: _uiTimesUsedCurrent(0),
_uiTimesFailedCurrent(0),
_uiTimesFailedOutsideRangeCurrent(0),
_uiTimesUsed(),
_uiTimesFailed(),
_uiTimesFailedOutsideRange(0),
_activityId(),
_fShouldWriteFinalLog(false)
{
TraceLoggingRegister(g_hConsoleVirtTermParserEventTraceProvider);
// Create a random activityId just in case it doesn't get set later in SetActivityId().
EventActivityIdControl(EVENT_ACTIVITY_CTRL_CREATE_ID, &_activityId);
}
#pragma warning(pop)
TermTelemetry::~TermTelemetry()
{
WriteFinalTraceLog();
TraceLoggingUnregister(g_hConsoleVirtTermParserEventTraceProvider);
}
// Routine Description:
// - Logs the usage of a particular VT100 code.
//
// Arguments:
// - code - VT100 code.
// Return Value:
// - <none>
void TermTelemetry::Log(const Codes code)
{
// Initially we wanted to pass over a string (ex. "CUU") and use a dictionary data type to hold the counts.
// However we would have to search through the dictionary every time we called this method, so we decided
// to use an array which has very quick access times.
// The downside is we have to create an enum type, and then convert them to strings when we finally
// send out the telemetry, but the upside is we should have very good performance.
_uiTimesUsed[code]++;
_uiTimesUsedCurrent++;
}
// Routine Description:
// - Logs a particular VT100 escape code failed or was unsupported.
//
// Arguments:
// - code - VT100 code.
// Return Value:
// - <none>
void TermTelemetry::LogFailed(const wchar_t wch)
{
if (wch > CHAR_MAX)
{
_uiTimesFailedOutsideRange++;
_uiTimesFailedOutsideRangeCurrent++;
}
else
{
// Even though we pass over a wide character, we only care about the ASCII single byte character.
_uiTimesFailed[wch]++;
_uiTimesFailedCurrent++;
}
}
// Routine Description:
// - Gets and resets the total count of codes used.
//
// Arguments:
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesUsedCurrent()
{
unsigned int uiTemp = _uiTimesUsedCurrent;
_uiTimesUsedCurrent = 0;
return uiTemp;
}
// Routine Description:
// - Gets and resets the total count of codes failed.
//
// Arguments:
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesFailedCurrent()
{
unsigned int uiTemp = _uiTimesFailedCurrent;
_uiTimesFailedCurrent = 0;
return uiTemp;
}
// Routine Description:
// - Gets and resets the total count of codes failed outside the valid range.
//
// Arguments:
// - <none>
// Return Value:
// - total number.
unsigned int TermTelemetry::GetAndResetTimesFailedOutsideRangeCurrent()
{
unsigned int uiTemp = _uiTimesFailedOutsideRangeCurrent;
_uiTimesFailedOutsideRangeCurrent = 0;
return uiTemp;
}
// Routine Description:
// - Lets us know whether we should write the final log. Typically set true when the console has been
// interacted with, to help reduce the amount of telemetry we're sending.
//
// Arguments:
// - writeLog - true if we should write the log.
// Return Value:
// - <none>
void TermTelemetry::SetShouldWriteFinalLog(const bool writeLog)
{
_fShouldWriteFinalLog = writeLog;
}
// Routine Description:
// - Sets the activity Id, so we can match our events with other providers (such as Microsoft.Windows.Console.Host).
//
// Arguments:
// - activityId - Pointer to Guid to set our activity Id to.
// Return Value:
// - <none>
void TermTelemetry::SetActivityId(const GUID *activityId)
{
_activityId = *activityId;
}
// Routine Description:
// - Writes the final log of all the telemetry collected. The primary reason to send back a final log instead
// of individual events is to reduce the amount of telemetry being sent and potentially overloading our servers.
//
// Arguments:
// - code - VT100 code.
// Return Value:
// - <none>
void TermTelemetry::WriteFinalTraceLog() const
{
if (_fShouldWriteFinalLog)
{
// Determine if we've logged any VT100 sequences at all.
bool fLoggedSequence = (_uiTimesFailedOutsideRange > 0);
if (!fLoggedSequence)
{
for (int n = 0; n < ARRAYSIZE(_uiTimesUsed); n++)
{
if (_uiTimesUsed[n] > 0)
{
fLoggedSequence = true;
break;
}
}
}
if (!fLoggedSequence)
{
for (int n = 0; n < ARRAYSIZE(_uiTimesFailed); n++)
{
if (_uiTimesFailed[n] > 0)
{
fLoggedSequence = true;
break;
}
}
}
// Only send telemetry if we've logged some VT100 sequences. This should help reduce the amount of unnecessary
// telemetry being sent.
if (fLoggedSequence)
{
// I could use the TraceLoggingUIntArray, but then we would have to know the order of the enums on the backend.
// So just log each enum count separately with its string representation which makes it more human readable.
// Set the related activity to NULL since we aren't using it.
TraceLoggingWriteActivity(g_hConsoleVirtTermParserEventTraceProvider,
"ControlCodesUsed",
&_activityId,
NULL,
TraceLoggingUInt32(_uiTimesUsed[CUU], "CUU"),
TraceLoggingUInt32(_uiTimesUsed[CUD], "CUD"),
TraceLoggingUInt32(_uiTimesUsed[CUF], "CUF"),
TraceLoggingUInt32(_uiTimesUsed[CUB], "CUB"),
TraceLoggingUInt32(_uiTimesUsed[CNL], "CNL"),
TraceLoggingUInt32(_uiTimesUsed[CPL], "CPL"),
TraceLoggingUInt32(_uiTimesUsed[CHA], "CHA"),
TraceLoggingUInt32(_uiTimesUsed[CUP], "CUP"),
TraceLoggingUInt32(_uiTimesUsed[ED], "ED"),
TraceLoggingUInt32(_uiTimesUsed[EL], "EL"),
TraceLoggingUInt32(_uiTimesUsed[SGR], "SGR"),
TraceLoggingUInt32(_uiTimesUsed[DECSC], "DECSC"),
TraceLoggingUInt32(_uiTimesUsed[DECRC], "DECRC"),
TraceLoggingUInt32(_uiTimesUsed[DECSET], "DECSET"),
TraceLoggingUInt32(_uiTimesUsed[DECRST], "DECRST"),
TraceLoggingUInt32(_uiTimesUsed[DECKPAM], "DECKPAM"),
TraceLoggingUInt32(_uiTimesUsed[DECKPNM], "DECKPNM"),
TraceLoggingUInt32(_uiTimesUsed[DSR], "DSR"),
TraceLoggingUInt32(_uiTimesUsed[DA], "DA"),
TraceLoggingUInt32(_uiTimesUsed[VPA], "VPA"),
TraceLoggingUInt32(_uiTimesUsed[ICH], "ICH"),
TraceLoggingUInt32(_uiTimesUsed[DCH], "DCH"),
TraceLoggingUInt32(_uiTimesUsed[IL], "IL"),
TraceLoggingUInt32(_uiTimesUsed[DL], "DL"),
TraceLoggingUInt32(_uiTimesUsed[SU], "SU"),
TraceLoggingUInt32(_uiTimesUsed[SD], "SD"),
TraceLoggingUInt32(_uiTimesUsed[ANSISYSSC], "ANSISYSSC"),
TraceLoggingUInt32(_uiTimesUsed[ANSISYSRC], "ANSISYSRC"),
TraceLoggingUInt32(_uiTimesUsed[DECSTBM], "DECSTBM"),
TraceLoggingUInt32(_uiTimesUsed[RI], "RI"),
TraceLoggingUInt32(_uiTimesUsed[OSCWT], "OscWindowTitle"),
TraceLoggingUInt32(_uiTimesUsed[HTS], "HTS"),
TraceLoggingUInt32(_uiTimesUsed[CHT], "CHT"),
TraceLoggingUInt32(_uiTimesUsed[CBT], "CBT"),
TraceLoggingUInt32(_uiTimesUsed[TBC], "TBC"),
TraceLoggingUInt32(_uiTimesUsed[ECH], "ECH"),
TraceLoggingUInt32(_uiTimesUsed[DesignateG0], "DesignateG0"),
TraceLoggingUInt32(_uiTimesUsed[DesignateG1], "DesignateG1"),
TraceLoggingUInt32(_uiTimesUsed[DesignateG2], "DesignateG2"),
TraceLoggingUInt32(_uiTimesUsed[DesignateG3], "DesignateG3"),
TraceLoggingUInt32(_uiTimesUsed[HVP], "HVP"),
TraceLoggingUInt32(_uiTimesUsed[DECSTR], "DECSTR"),
TraceLoggingUInt32(_uiTimesUsed[RIS], "RIS"),
TraceLoggingUInt32(_uiTimesUsed[DECSCUSR], "DECSCUSR"),
TraceLoggingUInt32(_uiTimesUsed[DTTERM_WM], "DTTERM_WM"),
TraceLoggingUInt32(_uiTimesUsed[OSCCT], "OscColorTable"),
TraceLoggingUInt32(_uiTimesUsed[OSCSCC], "OscSetCursorColor"),
TraceLoggingUInt32(_uiTimesUsed[OSCRCC], "OscResetCursorColor"),
TraceLoggingUInt32(_uiTimesUsed[OSCFG], "OscForegroundColor"),
TraceLoggingUInt32(_uiTimesUsed[OSCBG], "OscBackgroundColor"),
TraceLoggingUInt32(_uiTimesUsed[REP], "REP"),
TraceLoggingUInt32Array(_uiTimesFailed, ARRAYSIZE(_uiTimesFailed), "Failed"),
TraceLoggingUInt32(_uiTimesFailedOutsideRange, "FailedOutsideRange"));
}
}
}