You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Reverted change to where FCrashReportAnalytics was initialized now that we get those settings from the UECrashContext file. Added DelayedSend analytics attribute that determines whether or not the process that is sending an analytics event was the same one that created it. #rb jamie.dale #jira UETOOL-1826 #ROBOMERGE-SOURCE: CL 9731024 in //UE4/Release-4.24/... #ROBOMERGE-BOT: RELEASE (Release-4.24 -> Main) (v539-9700858) [CL 9731027 by sebastian nordgren in Main branch]
228 lines
8.9 KiB
C++
228 lines
8.9 KiB
C++
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "EditorSessionSummarySender.h"
|
|
|
|
#include "AnalyticsEventAttribute.h"
|
|
#include "Algo/Transform.h"
|
|
#include "Interfaces/IAnalyticsProvider.h"
|
|
#include "EditorAnalyticsSession.h"
|
|
#include "HAL/PlatformProcess.h"
|
|
|
|
DEFINE_LOG_CATEGORY_STATIC(LogEditorSessionSummary, Verbose, All);
|
|
|
|
/* FEditorSessionSummarySender */
|
|
|
|
namespace EditorSessionSenderDefs
|
|
{
|
|
static const FTimespan SessionExpiration = FTimespan::FromDays(30.0);
|
|
static const int HeartbeatPeriodSeconds = 60;
|
|
|
|
// shutdown types
|
|
static const FString RunningSessionToken(TEXT("Running"));
|
|
static const FString ShutdownSessionToken(TEXT("Shutdown"));
|
|
static const FString CrashSessionToken(TEXT("Crashed"));
|
|
static const FString TerminatedSessionToken(TEXT("Terminated"));
|
|
static const FString DebuggerSessionToken(TEXT("Debugger"));
|
|
static const FString AbnormalSessionToken(TEXT("AbnormalShutdown"));
|
|
}
|
|
|
|
FEditorSessionSummarySender::FEditorSessionSummarySender(IAnalyticsProvider& InAnalyticsProvider, const FString& InSenderName, const int32 InCurrentSessionProcessId)
|
|
: HeartbeatTimeElapsed(0.0f)
|
|
, AnalyticsProvider(InAnalyticsProvider)
|
|
, Sender(InSenderName)
|
|
, CurrentSessionProcessId(InCurrentSessionProcessId)
|
|
{
|
|
}
|
|
|
|
FEditorSessionSummarySender::~FEditorSessionSummarySender()
|
|
{
|
|
}
|
|
|
|
void FEditorSessionSummarySender::Tick(float DeltaTime)
|
|
{
|
|
HeartbeatTimeElapsed += DeltaTime;
|
|
|
|
if (HeartbeatTimeElapsed > (float) EditorSessionSenderDefs::HeartbeatPeriodSeconds)
|
|
{
|
|
HeartbeatTimeElapsed = 0.0f;
|
|
|
|
SendStoredSessions();
|
|
}
|
|
}
|
|
|
|
void FEditorSessionSummarySender::Shutdown()
|
|
{
|
|
SendStoredSessions(/*bForceSendCurrentSession*/true);
|
|
}
|
|
|
|
void FEditorSessionSummarySender::SetCurrentSessionExitCode(const int32 InCurrentSessionProcessId, const int32 InExitCode)
|
|
{
|
|
check(CurrentSessionProcessId == InCurrentSessionProcessId);
|
|
CurrentSessionExitCode = InExitCode;
|
|
}
|
|
|
|
bool FEditorSessionSummarySender::FindCurrentSession(FEditorAnalyticsSession& OutSession) const
|
|
{
|
|
if (FPlatformProcess::IsApplicationRunning(CurrentSessionProcessId))
|
|
{
|
|
// still running, can't be abnormal termination
|
|
return false;
|
|
}
|
|
|
|
bool bFound = false;
|
|
|
|
if (FEditorAnalyticsSession::Lock(FTimespan::FromMilliseconds(100)))
|
|
{
|
|
TArray<FEditorAnalyticsSession> ExistingSessions;
|
|
FEditorAnalyticsSession::LoadAllStoredSessions(ExistingSessions);
|
|
|
|
const int32 ProcessID = CurrentSessionProcessId;
|
|
FEditorAnalyticsSession* CurrentSession = ExistingSessions.FindByPredicate(
|
|
[ProcessID](const FEditorAnalyticsSession& Session)
|
|
{
|
|
return Session.PlatformProcessID == ProcessID;
|
|
});
|
|
|
|
if (CurrentSession != nullptr)
|
|
{
|
|
OutSession = *CurrentSession;
|
|
bFound = true;
|
|
}
|
|
|
|
FEditorAnalyticsSession::Unlock();
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
|
|
void FEditorSessionSummarySender::SendStoredSessions(const bool bForceSendCurrentSession) const
|
|
{
|
|
TArray<FEditorAnalyticsSession> SessionsToReport;
|
|
|
|
if (FEditorAnalyticsSession::Lock(FTimespan::FromMilliseconds(100)))
|
|
{
|
|
// Get list of sessions in storage
|
|
TArray<FEditorAnalyticsSession> ExistingSessions;
|
|
FEditorAnalyticsSession::LoadAllStoredSessions(ExistingSessions);
|
|
|
|
TArray<FEditorAnalyticsSession> SessionsToDelete;
|
|
|
|
// Check each stored session to see if they should be sent or not
|
|
for (FEditorAnalyticsSession& Session : ExistingSessions)
|
|
{
|
|
const bool bForceSendSession = bForceSendCurrentSession && (Session.PlatformProcessID == CurrentSessionProcessId);
|
|
if (!bForceSendSession && FPlatformProcess::IsApplicationRunning(Session.PlatformProcessID))
|
|
{
|
|
// Skip processes that are still running
|
|
continue;
|
|
}
|
|
|
|
const FTimespan SessionAge = FDateTime::UtcNow() - Session.Timestamp;
|
|
if (SessionAge < EditorSessionSenderDefs::SessionExpiration)
|
|
{
|
|
SessionsToReport.Add(Session);
|
|
}
|
|
SessionsToDelete.Add(Session);
|
|
}
|
|
|
|
for (const FEditorAnalyticsSession& ToDelete : SessionsToDelete)
|
|
{
|
|
ToDelete.Delete();
|
|
ExistingSessions.RemoveAll([&ToDelete](const FEditorAnalyticsSession& Session)
|
|
{
|
|
return Session.SessionId == ToDelete.SessionId;
|
|
});
|
|
}
|
|
|
|
TArray<FString> SessionIDs;
|
|
SessionIDs.Reserve(ExistingSessions.Num());
|
|
Algo::Transform(ExistingSessions, SessionIDs, &FEditorAnalyticsSession::SessionId);
|
|
|
|
FEditorAnalyticsSession::SaveStoredSessionIDs(SessionIDs);
|
|
|
|
FEditorAnalyticsSession::Unlock();
|
|
}
|
|
|
|
for (const FEditorAnalyticsSession& Session : SessionsToReport)
|
|
{
|
|
SendSessionSummaryEvent(Session);
|
|
}
|
|
}
|
|
|
|
void FEditorSessionSummarySender::SendSessionSummaryEvent(const FEditorAnalyticsSession& Session) const
|
|
{
|
|
FGuid SessionId;
|
|
FString SessionIdString = Session.SessionId;
|
|
if (FGuid::Parse(SessionIdString, SessionId))
|
|
{
|
|
// convert session guid to one with braces for sending to analytics
|
|
SessionIdString = SessionId.ToString(EGuidFormats::DigitsWithHyphensInBraces);
|
|
}
|
|
|
|
FString ShutdownTypeString = Session.bCrashed ? EditorSessionSenderDefs::CrashSessionToken :
|
|
(Session.bWasEverDebugger ? EditorSessionSenderDefs::DebuggerSessionToken :
|
|
(Session.bIsTerminating ? EditorSessionSenderDefs::TerminatedSessionToken :
|
|
(Session.bWasShutdown ? EditorSessionSenderDefs::ShutdownSessionToken : EditorSessionSenderDefs::AbnormalSessionToken)));
|
|
|
|
FString PluginsString = FString::Join(Session.Plugins, TEXT(","));
|
|
|
|
TArray<FAnalyticsEventAttribute> AnalyticsAttributes;
|
|
AnalyticsAttributes.Emplace(TEXT("ProjectName"), Session.ProjectName);
|
|
AnalyticsAttributes.Emplace(TEXT("ProjectID"), Session.ProjectID);
|
|
AnalyticsAttributes.Emplace(TEXT("ProjectDescription"), Session.ProjectDescription);
|
|
AnalyticsAttributes.Emplace(TEXT("ProjectVersion"), Session.ProjectVersion);
|
|
AnalyticsAttributes.Emplace(TEXT("Platform"), FPlatformProperties::PlatformName());
|
|
AnalyticsAttributes.Emplace(TEXT("SessionId"), SessionIdString);
|
|
AnalyticsAttributes.Emplace(TEXT("EngineVersion"), Session.EngineVersion);
|
|
AnalyticsAttributes.Emplace(TEXT("ShutdownType"), ShutdownTypeString);
|
|
AnalyticsAttributes.Emplace(TEXT("Timestamp"), Session.Timestamp.ToIso8601());
|
|
AnalyticsAttributes.Emplace(TEXT("CurrentUserActivity"), Session.CurrentUserActivity);
|
|
AnalyticsAttributes.Emplace(TEXT("StartupTimestamp"), Session.StartupTimestamp.ToIso8601());
|
|
AnalyticsAttributes.Emplace(TEXT("AverageFPS"), Session.AverageFPS);
|
|
|
|
double SessionDuration = (Session.Timestamp - Session.StartupTimestamp).GetTotalSeconds();
|
|
AnalyticsAttributes.Emplace(TEXT("SessionDuration"), SessionDuration);
|
|
|
|
AnalyticsAttributes.Emplace(TEXT("1MinIdle"), Session.Idle1Min);
|
|
AnalyticsAttributes.Emplace(TEXT("5MinIdle"), Session.Idle5Min);
|
|
AnalyticsAttributes.Emplace(TEXT("30MinIdle"), Session.Idle30Min);
|
|
AnalyticsAttributes.Emplace(TEXT("DesktopGPUAdapter"), Session.DesktopGPUAdapter);
|
|
AnalyticsAttributes.Emplace(TEXT("RenderingGPUAdapter"), Session.RenderingGPUAdapter);
|
|
AnalyticsAttributes.Emplace(TEXT("GPUVendorID"), Session.GPUVendorID);
|
|
AnalyticsAttributes.Emplace(TEXT("GPUDeviceID"), Session.GPUDeviceID);
|
|
AnalyticsAttributes.Emplace(TEXT("GRHIDeviceRevision"), Session.GRHIDeviceRevision);
|
|
AnalyticsAttributes.Emplace(TEXT("GRHIAdapterInternalDriverVersion"), Session.GRHIAdapterInternalDriverVersion);
|
|
AnalyticsAttributes.Emplace(TEXT("GRHIAdapterUserDriverVersion"), Session.GRHIAdapterUserDriverVersion);
|
|
AnalyticsAttributes.Emplace(TEXT("TotalPhysicalRAM"), Session.TotalPhysicalRAM);
|
|
AnalyticsAttributes.Emplace(TEXT("CPUPhysicalCores"), Session.CPUPhysicalCores);
|
|
AnalyticsAttributes.Emplace(TEXT("CPULogicalCores"), Session.CPULogicalCores);
|
|
AnalyticsAttributes.Emplace(TEXT("CPUVendor"), Session.CPUVendor);
|
|
AnalyticsAttributes.Emplace(TEXT("CPUBrand"), Session.CPUBrand);
|
|
AnalyticsAttributes.Emplace(TEXT("OSMajor"), Session.OSMajor);
|
|
AnalyticsAttributes.Emplace(TEXT("OSMinor"), Session.OSMinor);
|
|
AnalyticsAttributes.Emplace(TEXT("OSVersion"), Session.OSVersion);
|
|
AnalyticsAttributes.Emplace(TEXT("Is64BitOS"), Session.bIs64BitOS);
|
|
|
|
AnalyticsAttributes.Emplace(TEXT("GPUCrash"), Session.bGPUCrashed);
|
|
AnalyticsAttributes.Emplace(TEXT("WasDebugged"), Session.bWasEverDebugger);
|
|
AnalyticsAttributes.Emplace(TEXT("IsVanilla"), Session.bIsVanilla);
|
|
AnalyticsAttributes.Emplace(TEXT("WasShutdown"), Session.bWasShutdown);
|
|
AnalyticsAttributes.Emplace(TEXT("IsInPIE"), Session.bIsInPIE);
|
|
AnalyticsAttributes.Emplace(TEXT("IsInEnterprise"), Session.bIsInEnterprise);
|
|
AnalyticsAttributes.Emplace(TEXT("IsInVRMode"), Session.bIsInVRMode);
|
|
AnalyticsAttributes.Emplace(TEXT("SentFrom"), Sender);
|
|
|
|
// was this sent from some other process than itself or the out-of-process monitor for that run?
|
|
AnalyticsAttributes.Emplace(TEXT("DelayedSend"), Session.PlatformProcessID != CurrentSessionProcessId);
|
|
|
|
if (Session.PlatformProcessID == CurrentSessionProcessId && CurrentSessionExitCode.IsSet())
|
|
{
|
|
AnalyticsAttributes.Emplace(TEXT("ExitCode"), CurrentSessionExitCode.GetValue());
|
|
}
|
|
|
|
// Send the event.
|
|
AnalyticsProvider.RecordEvent(TEXT("SessionSummary"), AnalyticsAttributes);
|
|
|
|
UE_LOG(LogEditorSessionSummary, Log, TEXT("EditorSessionSummary sent report. Type=%s, SessionId=%s"), *ShutdownTypeString, *SessionIdString);
|
|
}
|