You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown Nick.Penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2845644 on 2016/01/27 by Martin.Wilson Clear marker sync flag after creating tick record, add more information to checks incase issue occurs again #Jira OR-13469 #rb Thomas.Sarkanen #tests in editor tests, bot match. Change 2845613 on 2016/01/27 by John.Pollard Latest network profiler binaries #rb none #tests run profiler Change 2845595 on 2016/01/27 by Mieszko.Zielinski Fixed pathfollowing's block detection using wrong distance when testing for blockage #UE4 #rb Lukasz.Furman #test golden path Change 2845593 on 2016/01/27 by Jeff.Farris Added support for setting and choosing filmbacks and lenses for cinematic cameras. - New CineCameraComponent and CineCameraActor classes - can define filmback and lens presets via ini file - details customizations for filmback and lens selection - added prototype set of filmbacks and lenses (primes and zooms) - Camera details customization now gracefully handles when CameraSettings category is hidden - example sequencer usage is content/developers/jeff.farris/CineCams/CineCamTestMap #rb none #tests editor Change 2845585 on 2016/01/27 by Marcus.Wassmer Don't fool with connected state if we're early outing from the OS intercepting controller events. This fixes some missing delegates. Fixes cert bug about controller disconnect screen staying up permanently #rb Cody.Haskell #test Turning off controller, turning on again. #lockdown Andrew.Grant Change 2845528 on 2016/01/27 by Max.Chen Sequencer: Fix new spawnables not immediately getting an object binding. This was resulted in a missing +Track->Animation when first creating a spawnable and duplicate transform keys. #jira UE-26084 #tests Add spawnable, +Track->Animation exists #rb none Change 2845483 on 2016/01/27 by Andrew.Rodham Sequencer: Fixed MaximizedViewport not getting cleared/restored correctly #jria UE-26016 #rb Max.Chen #tests Tested the viewports Change 2845421 on 2016/01/27 by Max.Preussner Sequencer: Implemented go-to feature #RB max.chen #TESTS Editor Change 2845407 on 2016/01/27 by Max.Preussner Sequencer: Moved SetViewRange() into ISequencer and made it public #RB max.chen #TESTS none Change 2845404 on 2016/01/27 by Andrew.Rodham Sequencer: Fixed cinematic viewport not updating when dragging transport range #jira UE-26003 #rb Max.Chen #tests Scrubbed the timeline Change 2845396 on 2016/01/27 by David.Nikdel #OSS #Purchase #Store #PS4 - Minor log cleanup #RB: none #TESTS: compiles Change 2845375 on 2016/01/27 by Max.Chen Sequencer: Implement cinematic shot track thumbnails. #jira UE-25125 #tests Rebuild the trailer with the cinematic shot track #rb none Change 2845359 on 2016/01/27 by Marcus.Wassmer Downgrade some checks to ensures. #rb none #test ps4 Change 2845347 on 2016/01/27 by Nicholas.Davies Remove unused EditorStyle dependency from Social. It is not being used, and causes issues for the engine team. #RB Antony.Carter #TESTS n/a #codereview Robert.Manuszewski Change 2845227 on 2016/01/27 by Robert.Manuszewski Adding flags to create callstack map files when building Arxan protection #rb none #tests Built arxan exe Change 2844871 on 2016/01/26 by Andrew.Grant Prevent enums from being regenerated while cooking (prevents false-positive warning about FText's being regenerated) #rb none #tests ran editor [CL 2847722 by Andrew Grant in Main branch]
307 lines
10 KiB
C++
307 lines
10 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "QoSReporterPrivatePCH.h"
|
|
|
|
#include "Core.h"
|
|
#include "Json.h"
|
|
#include "Analytics.h"
|
|
#include "Http.h"
|
|
#include "EngineVersion.h"
|
|
#include "QoSReporter.h"
|
|
|
|
DEFINE_LOG_CATEGORY(LogQoSReporter);
|
|
|
|
IMPLEMENT_MODULE(FQoSReporterModule, QoSReporter);
|
|
|
|
// helps to version QoS events (date*10 to allow for 10 revisions per day)
|
|
#define QOS_EVENTS_REVISION 201601200
|
|
|
|
FString FQoSReporterModule::Config::GetDefaultAppVersion()
|
|
{
|
|
return FString::Printf(TEXT("UE4-CL-%d"), FEngineVersion::Current().GetChangelist());
|
|
}
|
|
|
|
FString FQoSReporterModule::Config::GetDefaultAppEnvironment()
|
|
{
|
|
return FAnalytics::ToString(FAnalytics::Get().GetBuildType());
|
|
}
|
|
|
|
class FAnalyticsProviderQoSReporter : public IAnalyticsProvider
|
|
{
|
|
public:
|
|
FAnalyticsProviderQoSReporter(const FQoSReporterModule::Config& ConfigValues);
|
|
|
|
/** This provider does not have a concept of sessions */
|
|
virtual bool StartSession(const TArray<FAnalyticsEventAttribute>& Attributes) override { return true; };
|
|
/** This provider does not have a concept of sessions */
|
|
virtual void EndSession() override {};
|
|
/** This provider is not supposed to send many events, and due to nature of QoS we don't want to cache them */
|
|
virtual void FlushEvents() override {};
|
|
|
|
/** This provider is not using user IDs */
|
|
virtual void SetUserID(const FString& InUserID) override {};
|
|
/** This provider is not using user IDs, but we're (ab)using this API to return InstanceId */
|
|
virtual FString GetUserID() const override { return InstanceId.ToString(); };
|
|
|
|
/** This provider does not have a concept of sessions */
|
|
virtual FString GetSessionID() const override { checkf(false, TEXT("FAnalyticsProviderQoSReporter is not session based")); return TEXT("UnknownSessionId"); };
|
|
/** This provider does not have a concept of sessions */
|
|
virtual bool SetSessionID(const FString& InSessionID) override { return false; };
|
|
|
|
/** We're (ab)using this API to set DeploymentName */
|
|
virtual void SetLocation(const FString& InLocation) override { DeploymentName = InLocation; };
|
|
|
|
virtual void RecordEvent(const FString& EventName, const TArray<FAnalyticsEventAttribute>& Attributes) override;
|
|
virtual ~FAnalyticsProviderQoSReporter();
|
|
|
|
FString GetAPIKey() const { return APIKey; }
|
|
|
|
private:
|
|
|
|
/** API key (also known as "upload type" on data router) */
|
|
FString APIKey;
|
|
/** API Server to use (also known as "endpoint"). */
|
|
FString APIServer;
|
|
/** The AppVersion to use. */
|
|
FString AppVersion;
|
|
/** The AppEnvironment to use. */
|
|
FString AppEnvironment;
|
|
/** The upload type to use. */
|
|
FString UploadType;
|
|
|
|
/** Unique identifier for this QoS reporter instance (only changed on module initialization) */
|
|
FGuid InstanceId;
|
|
/** Deployment name (if empty, it won't be sent). */
|
|
FString DeploymentName;
|
|
|
|
/**
|
|
* Delegate called when an event Http request completes
|
|
*/
|
|
void EventRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded);
|
|
|
|
/**
|
|
* Returns application role (server, client)
|
|
*/
|
|
static FString GetApplicationRole();
|
|
};
|
|
|
|
void FQoSReporterModule::StartupModule()
|
|
{
|
|
// FQoSReporter::Initialize() is expected to be called by game code with proper config
|
|
}
|
|
|
|
void FQoSReporterModule::ShutdownModule()
|
|
{
|
|
FQoSReporter::Shutdown();
|
|
}
|
|
|
|
TSharedPtr<IAnalyticsProvider> FQoSReporterModule::CreateAnalyticsProvider(const FAnalytics::FProviderConfigurationDelegate& GetConfigValue) const
|
|
{
|
|
if (GetConfigValue.IsBound())
|
|
{
|
|
Config ConfigValues;
|
|
ConfigValues.APIServer = GetConfigValue.Execute(Config::GetKeyNameForAPIServer(), true);
|
|
ConfigValues.APIKey = GetConfigValue.Execute(Config::GetKeyNameForAPIKey(), false);
|
|
ConfigValues.AppVersion = GetConfigValue.Execute(Config::GetKeyNameForAppVersion(), false);
|
|
ConfigValues.AppEnvironment = GetConfigValue.Execute(Config::GetKeyNameForAppEnvironment(), false);
|
|
ConfigValues.UploadType = GetConfigValue.Execute(Config::GetKeyNameForUploadType(), false);
|
|
return CreateAnalyticsProvider(ConfigValues);
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogQoSReporter, Warning, TEXT("CreateAnalyticsProvider called with an unbound delegate"));
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
TSharedPtr<IAnalyticsProvider> FQoSReporterModule::CreateAnalyticsProvider(const Config& ConfigValues) const
|
|
{
|
|
return TSharedPtr<IAnalyticsProvider>(new FAnalyticsProviderQoSReporter(ConfigValues));
|
|
}
|
|
|
|
/**
|
|
* Perform any initialization.
|
|
*/
|
|
FAnalyticsProviderQoSReporter::FAnalyticsProviderQoSReporter(const FQoSReporterModule::Config& ConfigValues)
|
|
{
|
|
UE_LOG(LogQoSReporter, Verbose, TEXT("Initializing QoS Reporter"));
|
|
|
|
APIKey = ConfigValues.APIKey;
|
|
if (APIKey.IsEmpty())
|
|
{
|
|
UE_LOG(LogQoSReporter, Error, TEXT("QoS API key is not configured, no QoS metrics will be reported."));
|
|
}
|
|
|
|
APIServer = ConfigValues.APIServer;
|
|
if (APIServer.IsEmpty())
|
|
{
|
|
UE_LOG(LogQoSReporter, Error, TEXT("QoS API server is not configured, no QoS metrics will be reported."));
|
|
}
|
|
|
|
AppVersion = ConfigValues.AppVersion;
|
|
if (AppVersion.IsEmpty())
|
|
{
|
|
AppVersion = ConfigValues.GetDefaultAppVersion();
|
|
}
|
|
|
|
AppEnvironment = ConfigValues.AppEnvironment;
|
|
if (AppEnvironment.IsEmpty())
|
|
{
|
|
AppEnvironment = ConfigValues.GetDefaultAppEnvironment();
|
|
}
|
|
|
|
UploadType = ConfigValues.UploadType;
|
|
if (UploadType.IsEmpty())
|
|
{
|
|
UploadType = ConfigValues.GetDefaultUploadType();
|
|
}
|
|
|
|
// add a unique id
|
|
InstanceId = FGuid::NewGuid();
|
|
FPlatformMisc::CreateGuid(InstanceId);
|
|
|
|
UE_LOG(LogQoSReporter, Log, TEXT("QoSReporter initialized (Guid = '%s')"), *InstanceId.ToString());
|
|
UE_LOG(LogQoSReporter, Log, TEXT("APIKey = '%s'. APIServer = '%s'. AppVersion = '%s'. AppEnvironment = '%s'"), *APIKey, *APIServer, *AppVersion, *AppEnvironment);
|
|
}
|
|
|
|
FAnalyticsProviderQoSReporter::~FAnalyticsProviderQoSReporter()
|
|
{
|
|
UE_LOG(LogQoSReporter, Verbose, TEXT("Destroying QoS Reporter"));
|
|
EndSession();
|
|
}
|
|
|
|
void FAnalyticsProviderQoSReporter::RecordEvent(const FString& EventName, const TArray<FAnalyticsEventAttribute>& InAttributes)
|
|
{
|
|
if (APIKey.IsEmpty() || APIServer.IsEmpty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
// add attributes common to each QoS event first
|
|
TArray<FAnalyticsEventAttribute> Attributes;
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("QoSRevision"), QOS_EVENTS_REVISION));
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Role"), GetApplicationRole()));
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("SystemId"), FPlatformMisc::GetOperatingSystemId()));
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("InstanceId"), InstanceId.ToString()));
|
|
if (LIKELY(DeploymentName.Len() > 0))
|
|
{
|
|
Attributes.Add(FAnalyticsEventAttribute(TEXT("Deployment"), DeploymentName));
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogQoSReporter, Warning, TEXT("QoSReporter was not configured for any deployment; metrics will be likely discarded."));
|
|
}
|
|
|
|
// append the rest
|
|
Attributes += InAttributes;
|
|
|
|
// encode params as Json
|
|
if (ensure(FModuleManager::Get().IsModuleLoaded("HTTP")))
|
|
{
|
|
FString Payload;
|
|
|
|
FDateTime CurrentTime = FDateTime::UtcNow();
|
|
|
|
TSharedRef< TJsonWriter<TCHAR, TCondensedJsonPrintPolicy<TCHAR> > > JsonWriter = TJsonWriterFactory<TCHAR, TCondensedJsonPrintPolicy<TCHAR> >::Create(&Payload);
|
|
JsonWriter->WriteObjectStart();
|
|
JsonWriter->WriteArrayStart(TEXT("Events"));
|
|
|
|
// write just a single event
|
|
JsonWriter->WriteObjectStart();
|
|
JsonWriter->WriteValue(TEXT("EventName"), EventName);
|
|
|
|
if (Attributes.Num() > 0)
|
|
{
|
|
// optional attributes for this event
|
|
for (int32 AttrIdx = 0; AttrIdx < Attributes.Num(); AttrIdx++)
|
|
{
|
|
const FAnalyticsEventAttribute& Attr = Attributes[AttrIdx];
|
|
JsonWriter->WriteValue(Attr.AttrName, Attr.AttrValue);
|
|
}
|
|
}
|
|
JsonWriter->WriteObjectEnd();
|
|
|
|
JsonWriter->WriteArrayEnd();
|
|
JsonWriter->WriteObjectEnd();
|
|
JsonWriter->Close();
|
|
|
|
FString URLPath = FString::Printf(TEXT("?AppID=%s&AppVersion=%s&AppEnvironment=%s&UploadType=%s"),
|
|
*FGenericPlatformHttp::UrlEncode(APIKey),
|
|
*FGenericPlatformHttp::UrlEncode(AppVersion),
|
|
*FGenericPlatformHttp::UrlEncode(AppEnvironment),
|
|
*FGenericPlatformHttp::UrlEncode(UploadType)
|
|
);
|
|
|
|
// Recreate the URLPath for logging because we do not want to escape the parameters when logging.
|
|
// We cannot simply UrlEncode the entire Path after logging it because UrlEncode(Params) != UrlEncode(Param1) & UrlEncode(Param2) ...
|
|
UE_LOG(LogQoSReporter, VeryVerbose, TEXT("[%s] QoS URL:%s?AppID=%s&AppVersion=%s&AppEnvironment=%s&UploadType=%s. Payload:%s"),
|
|
*APIKey,
|
|
*APIServer,
|
|
*APIKey,
|
|
*AppVersion,
|
|
*AppEnvironment,
|
|
*UploadType,
|
|
*Payload);
|
|
|
|
// Create/send Http request for an event
|
|
TSharedRef<IHttpRequest> HttpRequest = FHttpModule::Get().CreateRequest();
|
|
HttpRequest->SetHeader(TEXT("Content-Type"), TEXT("application/json; charset=utf-8"));
|
|
|
|
HttpRequest->SetURL(APIServer + URLPath);
|
|
HttpRequest->SetVerb(TEXT("POST"));
|
|
HttpRequest->SetContentAsString(Payload);
|
|
HttpRequest->OnProcessRequestComplete().BindRaw(this, &FAnalyticsProviderQoSReporter::EventRequestComplete);
|
|
HttpRequest->ProcessRequest();
|
|
|
|
}
|
|
}
|
|
|
|
void FAnalyticsProviderQoSReporter::EventRequestComplete(FHttpRequestPtr HttpRequest, FHttpResponsePtr HttpResponse, bool bSucceeded)
|
|
{
|
|
if (bSucceeded && HttpResponse.IsValid())
|
|
{
|
|
// normal operation is silent, but any problems are reported as warnings
|
|
if (EHttpResponseCodes::IsOk(HttpResponse->GetResponseCode()))
|
|
{
|
|
UE_LOG(LogQoSReporter, VeryVerbose, TEXT("QoS response for [%s]. Code: %d. Payload: %s"),
|
|
*HttpRequest->GetURL(), HttpResponse->GetResponseCode(), *HttpResponse->GetContentAsString());
|
|
}
|
|
else
|
|
{
|
|
UE_LOG(LogQoSReporter, Warning, TEXT("Bad QoS response for [%s] - code: %d. Payload: %s"),
|
|
*HttpRequest->GetURL(), HttpResponse->GetResponseCode(), *HttpResponse->GetContentAsString());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// if we cannot report QoS metrics this is pretty bad; report at least a warning
|
|
UE_LOG(LogQoSReporter, Warning, TEXT("QoS response for [%s]. No response"), *HttpRequest->GetURL());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns application role (server, client)
|
|
*/
|
|
FString FAnalyticsProviderQoSReporter::GetApplicationRole()
|
|
{
|
|
if (IsRunningDedicatedServer())
|
|
{
|
|
static FString DedicatedServer(TEXT("DedicatedServer"));
|
|
return DedicatedServer;
|
|
}
|
|
else if (IsRunningClientOnly())
|
|
{
|
|
static FString ClientOnly(TEXT("ClientOnly"));
|
|
return ClientOnly;
|
|
}
|
|
else if (IsRunningGame())
|
|
{
|
|
static FString StandaloneGame(TEXT("StandaloneGame"));
|
|
return StandaloneGame;
|
|
}
|
|
|
|
static FString Editor(TEXT("Editor"));
|
|
return Editor;
|
|
}
|
|
|