Initial Commit - Lesson 31 (Commit #1)
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
using UnrealBuildTool;
|
||||
|
||||
public class GameLiftMetrics : ModuleRules
|
||||
{
|
||||
public GameLiftMetrics(ReadOnlyTargetRules Target) : base(Target)
|
||||
{
|
||||
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||
bEnableExceptions = true;
|
||||
bUseRTTI = false;
|
||||
|
||||
PublicDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"Core",
|
||||
"GameLiftServerSDK",
|
||||
}
|
||||
);
|
||||
|
||||
PrivateDependencyModuleNames.AddRange(
|
||||
new string[]
|
||||
{
|
||||
"CoreUObject",
|
||||
"Core",
|
||||
"Engine",
|
||||
"Sockets",
|
||||
"Networking",
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetrics.h"
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
#include "GameLiftMetricsConfig.h"
|
||||
#include "UnrealStatCollector.h"
|
||||
#include "TickableCollector.h"
|
||||
|
||||
#include "GameLiftServerSDK.h"
|
||||
#include "aws/gamelift/server/GameLiftServerAPI.h"
|
||||
|
||||
#include "Sockets.h"
|
||||
#include "SocketSubsystem.h"
|
||||
#include "IPAddress.h"
|
||||
#include "Common/UdpSocketBuilder.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GlobalMetricsProcessor.h>
|
||||
|
||||
#if PLATFORM_LINUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
FString FGameLiftMetricsModule::CurrentGameSessionId;
|
||||
FThreadSafeCounter FGameLiftMetricsModule::CurrentPlayerCount(0);
|
||||
|
||||
FGameLiftMetricsModule& FGameLiftMetricsModule::Load()
|
||||
{
|
||||
return FModuleManager::LoadModuleChecked<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
FGameLiftMetricsModule& FGameLiftMetricsModule::Get()
|
||||
{
|
||||
return FModuleManager::GetModuleChecked<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
FGameLiftMetricsModule* FGameLiftMetricsModule::GetPtr()
|
||||
{
|
||||
return FModuleManager::GetModulePtr<FGameLiftMetricsModule>(FName("GameLiftMetrics"));
|
||||
}
|
||||
|
||||
#if WITH_GAMELIFT_METRICS
|
||||
namespace
|
||||
{
|
||||
const TCHAR* GAMELIFT_METRICS_FLEET_ID = TEXT("GAMELIFT_SDK_FLEET_ID");
|
||||
const TCHAR* GAMELIFT_METRICS_PROCESS_ID = TEXT("GAMELIFT_SDK_PROCESS_ID");
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMaxPlayers, "server_max_players", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMaxPlayers);
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricPlayers, "server_players", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricPlayers);
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricServerCrashes, "game_server_crashes", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricServerCrashes);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::StartupModule() {}
|
||||
|
||||
void FGameLiftMetricsModule::ShutdownModule()
|
||||
{
|
||||
// Terminate here just in case the user forgot.
|
||||
Terminate();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::StartMetricsCollector()
|
||||
{
|
||||
FPlatformMisc::SetCrashHandler(&FGameLiftMetricsModule::CrashHandler);
|
||||
|
||||
bMetricsRunning = true;
|
||||
|
||||
auto *Module = FGameLiftMetricsModule::GetPtr();
|
||||
if (!Module)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("GameLiftMetrics module no longer loaded."));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Begin ticking the collector.
|
||||
*/
|
||||
const bool bComputeFallbackGameThreadTime = !STATS;
|
||||
Module->Collector.Reset(new FTickableCollector(bComputeFallbackGameThreadTime));
|
||||
|
||||
/*
|
||||
* Create stats collector.
|
||||
*/
|
||||
if (STATS)
|
||||
{
|
||||
Module->UnrealStatCollector = TSharedPtr<FUnrealStatCollector>(new FUnrealStatCollector());
|
||||
Module->UnrealStatCollector->Subscribe();
|
||||
}
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("GameLift metrics initialized successfully."));
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Initialize()
|
||||
{
|
||||
if (GIsEditor) return;
|
||||
|
||||
// Initialize GameLift Server SDK metrics
|
||||
auto& ServerSDKModule = FModuleManager::LoadModuleChecked<FGameLiftServerSDKModule>("GameLiftServerSDK");
|
||||
auto InitResult = ServerSDKModule.InitMetrics();
|
||||
if (!InitResult.IsSuccess())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Failed to initialize GameLift metrics: %s"), *InitResult.GetError().m_errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
StartMetricsCollector();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Initialize(const FMetricsParameters& metricsParameters)
|
||||
{
|
||||
if (GIsEditor) return;
|
||||
|
||||
// Initialize GameLift Server SDK metrics with parameters
|
||||
auto& ServerSDKModule = FModuleManager::LoadModuleChecked<FGameLiftServerSDKModule>("GameLiftServerSDK");
|
||||
auto InitResult = ServerSDKModule.InitMetrics(metricsParameters);
|
||||
if (!InitResult.IsSuccess())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Failed to initialize GameLift metrics with parameters: %s"), *InitResult.GetError().m_errorMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
StartMetricsCollector();
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::Terminate()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
if (UnrealStatCollector)
|
||||
{
|
||||
UnrealStatCollector->Unsubscribe();
|
||||
UnrealStatCollector.Reset();
|
||||
}
|
||||
|
||||
Collector.Reset();
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("GameLift metrics terminated successfully."));
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& Session)
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Store the session ID regardless of metrics being enabled
|
||||
CurrentGameSessionId = FString(Session.GetGameSessionId());
|
||||
CurrentPlayerCount.Set(0);
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Verbose, TEXT("Metrics disabled: Skipping OnStartGameSession metrics"));
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricMaxPlayers, Session.GetMaximumPlayerSessionCount());
|
||||
GAMELIFT_METRICS_RESET(MetricPlayers);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnAcceptPlayerSession()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Always track player count even if metrics are disabled
|
||||
int32 NewPlayerCount = CurrentPlayerCount.Increment();
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, NewPlayerCount);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::OnRemovePlayerSession()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
// Always track player count even if metrics are disabled
|
||||
int32 NewPlayerCount = CurrentPlayerCount.Decrement();
|
||||
if (NewPlayerCount < 0)
|
||||
{
|
||||
CurrentPlayerCount.Set(0);
|
||||
NewPlayerCount = 0;
|
||||
}
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, NewPlayerCount);
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::ReEmitMetrics()
|
||||
{
|
||||
if (GIsEditor) { return; }
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GAMELIFT_METRICS_SET(MetricPlayers, CurrentPlayerCount.GetValue());
|
||||
}
|
||||
|
||||
void FGameLiftMetricsModule::CrashHandler(const FGenericCrashContext& GenericContext)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Server crashed, CrashHandler being called..."));
|
||||
|
||||
const UGameLiftMetricsConfig& Config = UGameLiftMetricsConfig::Get();
|
||||
if (!Config.bEnableMetrics)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Metrics disabled: Skipping crash metrics"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CurrentGameSessionId.IsEmpty())
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Incrementing crash metrics for session: %s"), *CurrentGameSessionId);
|
||||
GAMELIFT_METRICS_INCREMENT(MetricServerCrashes);
|
||||
GAMELIFT_METRICS_TAG_SET(MetricServerCrashes, "game_session_id", TCHAR_TO_UTF8(*CurrentGameSessionId));
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Crash metrics incremented"));
|
||||
|
||||
// Force process the metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Sending crash metrics..."));
|
||||
Aws::GameLift::Metrics::MetricsProcess();
|
||||
|
||||
// Small sleep to allow the metrics to be sent
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Waiting for metrics to send..."));
|
||||
FPlatformProcess::Sleep(0.2f);
|
||||
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Crash metrics incremented and processed"));
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Warning, TEXT("Server crashed with no active game session"));
|
||||
}
|
||||
}
|
||||
|
||||
bool FGameLiftMetricsModule::SetMetricsEnabled(bool bEnable)
|
||||
{
|
||||
if (GIsEditor)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Warning, TEXT("Cannot enable/disable metrics in editor - only applicable in game server"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the state is already what's requested, no change needed
|
||||
if (bEnable == bMetricsRunning)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Metrics already %s, no change needed"),
|
||||
bEnable ? TEXT("enabled") : TEXT("disabled"));
|
||||
return true;
|
||||
}
|
||||
// Get current configuration and check current state
|
||||
UGameLiftMetricsConfig* Config = const_cast<UGameLiftMetricsConfig*>(&UGameLiftMetricsConfig::Get());
|
||||
|
||||
if (bEnable)
|
||||
{
|
||||
// Enable metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Enabling GameLift metrics at runtime"));
|
||||
|
||||
// Initialize with default parameters
|
||||
Initialize();
|
||||
|
||||
// Flag is set inside Initialize method based on success
|
||||
return bMetricsRunning;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disable metrics
|
||||
UE_LOG(LogGameLiftMetrics, Log, TEXT("Disabling GameLift metrics at runtime"));
|
||||
|
||||
// Terminate metrics system
|
||||
Terminate();
|
||||
Config->bEnableMetrics = false;
|
||||
bMetricsRunning = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FGameLiftMetricsModule::IsMetricsEnabled() const
|
||||
{
|
||||
return bMetricsRunning;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void FGameLiftMetricsModule::StartupModule() {}
|
||||
void FGameLiftMetricsModule::ShutdownModule() {}
|
||||
void FGameLiftMetricsModule::Initialize() {}
|
||||
void FGameLiftMetricsModule::Initialize(const FMetricsParameters& metricsParameters) {}
|
||||
void FGameLiftMetricsModule::Terminate() {}
|
||||
void FGameLiftMetricsModule::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& Session) {}
|
||||
void FGameLiftMetricsModule::OnAcceptPlayerSession() {}
|
||||
void FGameLiftMetricsModule::OnRemovePlayerSession() {}
|
||||
void FGameLiftMetricsModule::ReEmitMetrics() {}
|
||||
bool FGameLiftMetricsModule::SetMetricsEnabled(bool bEnable) { return false; }
|
||||
bool FGameLiftMetricsModule::IsMetricsEnabled() const { return false; }
|
||||
|
||||
#endif // WITH_GAMELIFT_METRICS
|
||||
|
||||
IMPLEMENT_MODULE(FGameLiftMetricsModule, GameLiftMetrics)
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetricsConfig.h"
|
||||
|
||||
|
||||
const UGameLiftMetricsConfig& UGameLiftMetricsConfig::Get()
|
||||
{
|
||||
UGameLiftMetricsConfig* CDO = Cast<UGameLiftMetricsConfig>(StaticClass()->GetDefaultObject());
|
||||
check(IsValid(CDO));
|
||||
return *CDO;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(LogGameLiftMetrics);
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "MemoryStats.h"
|
||||
|
||||
#include "Engine.h"
|
||||
#include "EngineStats.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalTotal);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalAvailable);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryPhysicalUsed);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualTotal);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualAvailable);
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricMemoryVirtualUsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FMemoryStats::Collect()
|
||||
{
|
||||
auto MemoryStats = FPlatformMemory::GetStats();
|
||||
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalTotal, MemoryStats.TotalPhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalAvailable, MemoryStats.AvailablePhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryPhysicalUsed, MemoryStats.UsedPhysical);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualTotal, MemoryStats.TotalVirtual);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualAvailable, MemoryStats.AvailableVirtual);
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricMemoryVirtualUsed, MemoryStats.UsedVirtual);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalTotal, "server_mem_physical_total", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalAvailable, "server_mem_physical_available", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryPhysicalUsed, "server_mem_physical_used", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualTotal, "server_mem_virtual_total", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualAvailable, "server_mem_virtual_available", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricMemoryVirtualUsed, "server_mem_virtual_used", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FMemoryStats
|
||||
{
|
||||
public:
|
||||
void Collect();
|
||||
};
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "NetworkStats.h"
|
||||
|
||||
#include "Engine/NetDriver.h"
|
||||
#include "Engine.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricConnectionCount);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricBytesIn);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricBytesOut);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsIn);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsInLost);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsOut);
|
||||
GAMELIFT_METRICS_DEFINE_COUNTER(MetricPacketsOutLost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FNetworkStats::FNetworkStats()
|
||||
{
|
||||
if (auto NetDriver = GetNetDriver())
|
||||
{
|
||||
LastInBytes = NetDriver->InTotalBytes;
|
||||
LastOutBytes = NetDriver->OutTotalBytes;
|
||||
LastInPackets = NetDriver->InTotalPackets;
|
||||
LastOutPackets = NetDriver->OutTotalPackets;
|
||||
LastInPacketsLost = NetDriver->InTotalPacketsLost;
|
||||
LastOutPacketsLost = NetDriver->OutTotalPacketsLost;
|
||||
}
|
||||
}
|
||||
|
||||
void FNetworkStats::Collect()
|
||||
{
|
||||
if (auto NetDriver = GetNetDriver())
|
||||
{
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricBytesIn, NetDriver->InTotalBytes - LastInBytes);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricBytesOut, NetDriver->OutTotalBytes - LastOutBytes);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsIn, NetDriver->InTotalPackets - LastInPackets);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsOut, NetDriver->OutTotalPackets - LastOutPackets);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsInLost, NetDriver->InTotalPacketsLost - LastInPacketsLost);
|
||||
GAMELIFT_METRICS_ADD(Aws::GameLift::Metrics::MetricPacketsOutLost, NetDriver->OutTotalPacketsLost - LastOutPacketsLost);
|
||||
|
||||
LastInBytes = NetDriver->InTotalBytes;
|
||||
LastOutBytes = NetDriver->OutTotalBytes;
|
||||
LastInPackets = NetDriver->InTotalPackets;
|
||||
LastOutPackets = NetDriver->OutTotalPackets;
|
||||
LastInPacketsLost = NetDriver->InTotalPacketsLost;
|
||||
LastOutPacketsLost = NetDriver->OutTotalPacketsLost;
|
||||
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricConnectionCount, NetDriver->ClientConnections.Num());
|
||||
}
|
||||
else
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Net driver is null. Cannot log network metrics."));
|
||||
}
|
||||
}
|
||||
|
||||
const UNetDriver* FNetworkStats::GetNetDriver() const
|
||||
{
|
||||
UEngine* Engine = GEngine;
|
||||
if (!IsValid(Engine))
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("Engine pointer is not valid when retrieving net driver."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto& WorldContexts = Engine->GetWorldContexts();
|
||||
if (WorldContexts.Num() == 0)
|
||||
{
|
||||
// no worlds are loaded
|
||||
// generally can only be true before everything is fully initialized
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("No world is loaded when retrieving net driver."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Only one world context should be present outside Editor.
|
||||
// (editor has multiple)
|
||||
// Refer to FWorldContext comment in Engine.h
|
||||
const FWorldContext& WorldContext = WorldContexts[0];
|
||||
check(WorldContext.WorldType == EWorldType::Game);
|
||||
|
||||
// In theory multiple net drivers might be present.
|
||||
// One will be for gameplay but additional ones might be opened for non-gameplay traffic.
|
||||
// Might be null during initialisation.
|
||||
if (WorldContext.ActiveNetDrivers.Num() == 0)
|
||||
{
|
||||
UE_LOG(LogGameLiftMetrics, Error, TEXT("No active net drivers. Cannot acquire network metrics."));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return WorldContext.ActiveNetDrivers[0].NetDriver;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
class UNetDriver;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricConnectionCount, "server_connections", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricBytesIn, "server_bytes_in", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricBytesOut, "server_bytes_out", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsIn, "server_packets_in", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsInLost, "server_packets_in_lost", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsOut, "server_packets_out", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
GAMELIFT_METRICS_DECLARE_COUNTER(MetricPacketsOutLost, "server_packets_out_lost", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FNetworkStats
|
||||
{
|
||||
public:
|
||||
FNetworkStats();
|
||||
|
||||
void Collect();
|
||||
|
||||
private:
|
||||
const UNetDriver* GetNetDriver() const;
|
||||
|
||||
private:
|
||||
int32 LastInBytes = 0;
|
||||
int32 LastOutBytes = 0;
|
||||
int32 LastInPackets = 0;
|
||||
int32 LastOutPackets = 0;
|
||||
int32 LastInPacketsLost = 0;
|
||||
int32 LastOutPacketsLost = 0;
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TickableCollector.h"
|
||||
#include "TimeStats.h"
|
||||
#include "GameLiftMetrics.h"
|
||||
|
||||
#include "Misc/App.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_GAUGE(MetricServerUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if WITH_GAMELIFT_METRICS
|
||||
void FTickableCollector::Tick(float)
|
||||
{
|
||||
GAMELIFT_METRICS_SET(Aws::GameLift::Metrics::MetricServerUp, 1);
|
||||
|
||||
NetworkStats.Collect();
|
||||
MemoryStats.Collect();
|
||||
|
||||
const double DeltaTime = FApp::GetDeltaTime();
|
||||
GAMELIFT_METRICS_SET_SEC(Aws::GameLift::Metrics::MetricGameDeltaTime, DeltaTime);
|
||||
if (bComputeFallbackGameThreadTime)
|
||||
{
|
||||
const double EstimatedGameThreadTime = DeltaTime - FApp::GetIdleTime();
|
||||
GAMELIFT_METRICS_SET_SEC(Aws::GameLift::Metrics::MetricGameTickTime, EstimatedGameThreadTime);
|
||||
}
|
||||
|
||||
// Re-emit specific metrics so that they don't go stale.
|
||||
// Grafana reports no data for the metric after 5 minutes of it being stale.
|
||||
FGameLiftMetricsModule::Get().ReEmitMetrics();
|
||||
|
||||
Aws::GameLift::Metrics::MetricsProcess();
|
||||
}
|
||||
#else
|
||||
void FTickableCollector::Tick(float) {}
|
||||
#endif // WITH_GAMELIFT_METRICS
|
||||
|
||||
|
||||
TStatId FTickableCollector::GetStatId() const
|
||||
{
|
||||
return TStatId{};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Tickable.h"
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
#include "NetworkStats.h"
|
||||
#include "MemoryStats.h"
|
||||
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DECLARE_GAUGE(MetricServerUp, "server_up", Aws::GameLift::Metrics::Server, Aws::GameLift::Metrics::SampleAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FTickableCollector : public FTickableGameObject
|
||||
{
|
||||
public:
|
||||
FTickableCollector(bool bComputeFallbackGameThreadTime)
|
||||
: bComputeFallbackGameThreadTime(bComputeFallbackGameThreadTime) {}
|
||||
|
||||
// FTickableGameObject
|
||||
virtual void Tick(float) override;
|
||||
|
||||
virtual bool IsTickable() const override { return true; }
|
||||
|
||||
virtual bool IsTickableWhenPaused() const override { return true; }
|
||||
virtual bool IsTickableInEditor() const override { return false; }
|
||||
virtual ETickableTickType GetTickableTickType() const override { return ETickableTickType::Always; }
|
||||
virtual TStatId GetStatId() const override;
|
||||
// ~FTickableGameObject
|
||||
|
||||
private:
|
||||
bool bComputeFallbackGameThreadTime = false;
|
||||
FNetworkStats NetworkStats;
|
||||
FMemoryStats MemoryStats;
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "TimeStats.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricGameDeltaTime);
|
||||
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricGameTickTime);
|
||||
GAMELIFT_METRICS_DEFINE_TIMER(MetricWorldTickTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
/**
|
||||
* Server time-step in milliseconds.
|
||||
*
|
||||
* This is the time between consecutive ticks.
|
||||
*
|
||||
* When the server is under performing, this will exceed the target tick rate,
|
||||
* otherwise it should hover in its vicinity.
|
||||
*
|
||||
* To compute the tick rate, compute the reciprocal: (1000 / server_delta_time)
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricGameDeltaTime, "server_delta_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
|
||||
/**
|
||||
* The time it takes to process a single tick.
|
||||
*
|
||||
* A subset of delta time.
|
||||
* server_tick_time <= server_delta_time at all times. Typically (much) smaller.
|
||||
*
|
||||
* This is the time it takes to actually process the tick. The remaining
|
||||
* time-step duration is spent waiting for the next tick.
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricGameTickTime, "server_tick_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
|
||||
/**
|
||||
* The time it takes to process the world update.
|
||||
*
|
||||
* A subset of tick time.
|
||||
*
|
||||
* This is the time it takes to process the Actors and Blueprints in the
|
||||
* currently loaded Map. The remainder of server_tick_time is spent in
|
||||
* other engine subsystems like network replication or physics.
|
||||
*
|
||||
* Only available in Debug or Development builds, or Shipping builds with
|
||||
* USE_FORCE_STATS=1.
|
||||
*/
|
||||
GAMELIFT_METRICS_DECLARE_TIMER(
|
||||
MetricWorldTickTime,
|
||||
"server_world_tick_time",
|
||||
Aws::GameLift::Metrics::Server,
|
||||
Aws::GameLift::Metrics::SampleAll(),
|
||||
Aws::GameLift::Metrics::Percentiles(0.5, 0.9, 0.95)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "UnrealStatCollector.h"
|
||||
|
||||
#include "Runtime/Launch/Resources/Version.h"
|
||||
|
||||
#include "TimeStats.h"
|
||||
|
||||
#include "Async/TaskGraphInterfaces.h"
|
||||
#include "Stats/Stats.h"
|
||||
#include "Stats/StatsData.h"
|
||||
#include "EngineStats.h"
|
||||
|
||||
|
||||
#if STATS
|
||||
namespace
|
||||
{
|
||||
#if ENGINE_MAJOR_VERSION >= 5
|
||||
void IncrementStatsRefCount()
|
||||
{
|
||||
StatsPrimaryEnableAdd();
|
||||
}
|
||||
|
||||
void DecrementStatsRefCount()
|
||||
{
|
||||
StatsPrimaryEnableSubtract();
|
||||
}
|
||||
#else
|
||||
void IncrementStatsRefCount()
|
||||
{
|
||||
StatsMasterEnableAdd();
|
||||
}
|
||||
|
||||
void DecrementStatsRefCount()
|
||||
{
|
||||
StatsMasterEnableSubtract();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::Subscribe()
|
||||
{
|
||||
IncrementStatsRefCount();
|
||||
|
||||
/*
|
||||
* From 5.2.0 onwards, UE_STATS_THREAD_AS_PIPE is undefined and the only way to
|
||||
* access the stat system is via the new API.
|
||||
*
|
||||
* Between 5.0.0 and 5.2.0, UE_STATS_THREAD_AS_PIPE enables new API. If it is 0,
|
||||
* the old API can be used.
|
||||
*
|
||||
* See UE engine source commits 10b5e05d00df4f23d3b75f6af5ec08f8ae0e8618
|
||||
* 327a94d1a4e021714f2c3ca820fe9ed5606465bf
|
||||
* d48f6660b807c7377926cffd12020645f91772f8
|
||||
*
|
||||
* All references to UE_STATS_THREAD_AS_PIPE are removed in
|
||||
* d48f6660b807c7377926cffd12020645f91772f8.
|
||||
*/
|
||||
#if ENGINE_MAJOR_VERSION >= 5 && (ENGINE_MINOR_VERSION >= 2 || UE_STATS_THREAD_AS_PIPE)
|
||||
{
|
||||
auto& StatsState = FStatsThreadState::GetLocalState();
|
||||
StatsState.NewFrameDelegate.AddSP(this, &FUnrealStatCollector::OnNewFrame);
|
||||
}
|
||||
#else
|
||||
FSimpleDelegateGraphTask::CreateAndDispatchWhenReady
|
||||
(
|
||||
FSimpleDelegateGraphTask::FDelegate::CreateLambda(
|
||||
[WeakCollector = TWeakPtr<FUnrealStatCollector>(this->AsShared())]() {
|
||||
if (!WeakCollector.IsValid()) { return; }
|
||||
|
||||
auto& StatsState = FStatsThreadState::GetLocalState();
|
||||
StatsState.NewFrameDelegate.AddSP(WeakCollector.Pin().Get(), &FUnrealStatCollector::OnNewFrame);
|
||||
}
|
||||
),
|
||||
TStatId{},
|
||||
nullptr,
|
||||
/*
|
||||
* StatsThread is deprecated since 5.0
|
||||
*
|
||||
* Need to verify post-5.0 behaviour but:
|
||||
* - 4.27 to 5.0 should use the current method to subscribe to NewFrameDelegate
|
||||
* - 5.0 on can subscribe from game thread directly. (See FThreadStats::bUseThreadAsPipe)
|
||||
*/
|
||||
ENamedThreads::StatsThread
|
||||
);
|
||||
#endif // UE_STATS_THREAD_AS_PIPE
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::Unsubscribe()
|
||||
{
|
||||
DecrementStatsRefCount();
|
||||
}
|
||||
|
||||
void FUnrealStatCollector::OnNewFrame(int64 Frame)
|
||||
{
|
||||
TArray<FStatMessage> OutStats;
|
||||
|
||||
auto& Stats = FStatsThreadState::GetLocalState();
|
||||
Stats.GetInclusiveAggregateStackStats(Frame, OutStats);
|
||||
|
||||
for (auto& Message : OutStats)
|
||||
{
|
||||
// GetShortName() is expensive and we're calling it for every stat.
|
||||
// In practice: we'll stick filter by GetRawName first and stick things in a hashmap
|
||||
// might also be able to compare FName indices
|
||||
FName ShortName = Message.NameAndInfo.GetShortName();
|
||||
|
||||
// Robustness: we can check the value type from message before blindly grabbing duration (or other types)
|
||||
|
||||
// Consult EngineStats.h for stat names
|
||||
// (There's also many other stats in other subsystems.)
|
||||
if (ShortName == TEXT("STAT_GameEngineTick"))
|
||||
{
|
||||
GAMELIFT_METRICS_SET_MS(Aws::GameLift::Metrics::MetricGameTickTime, FPlatformTime::ToMilliseconds(Message.GetValue_Duration()));
|
||||
}
|
||||
else if (ShortName == TEXT("STAT_WorldTickTime"))
|
||||
{
|
||||
GAMELIFT_METRICS_SET_MS(Aws::GameLift::Metrics::MetricWorldTickTime, FPlatformTime::ToMilliseconds(Message.GetValue_Duration()));
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void FUnrealStatCollector::Subscribe() {}
|
||||
void FUnrealStatCollector::Unsubscribe() {}
|
||||
void FUnrealStatCollector::OnNewFrame(int64 Frame) {}
|
||||
#endif // STATS
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
class FUnrealStatCollector : public TSharedFromThis<FUnrealStatCollector>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Subscribes to NewFrameDelegate in Unreal stats system.
|
||||
*/
|
||||
void Subscribe();
|
||||
|
||||
/**
|
||||
* Unsubscribes from NewFrameDelegate in Unreal stats system.
|
||||
*/
|
||||
void Unsubscribe();
|
||||
|
||||
void OnNewFrame(int64 Frame);
|
||||
};
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Modules/ModuleManager.h"
|
||||
|
||||
#include "GameLiftMetricsTypes.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GameLiftMetrics.h>
|
||||
|
||||
// Forward declarations
|
||||
struct FMetricsParameters;
|
||||
|
||||
class FSocket;
|
||||
class FUnrealStatCollector;
|
||||
class FTickableCollector;
|
||||
class UGameLiftMetricsConfig;
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Server {
|
||||
namespace Model {
|
||||
class GameSession;
|
||||
} // Model
|
||||
} // Server
|
||||
} // GameLift
|
||||
} // Aws
|
||||
|
||||
class GAMELIFTMETRICS_API FGameLiftMetricsModule : public IModuleInterface
|
||||
{
|
||||
public:
|
||||
// IModuleInterface
|
||||
virtual void StartupModule() override;
|
||||
virtual void ShutdownModule() override;
|
||||
|
||||
virtual bool SupportsDynamicReloading() override { return false; }
|
||||
virtual bool SupportsAutomaticShutdown() override { return true; }
|
||||
// ~IModuleInterface
|
||||
|
||||
static FGameLiftMetricsModule& Load();
|
||||
static FGameLiftMetricsModule& Get();
|
||||
static FGameLiftMetricsModule* GetPtr();
|
||||
|
||||
/**
|
||||
* Initialize GameLift Metrics using default configuration. These
|
||||
* may be overriden by environment variables.
|
||||
*/
|
||||
void Initialize();
|
||||
|
||||
/**
|
||||
* Initialize GameLift Metrics with metrics parameters.
|
||||
*
|
||||
* @param metricsParameters Metrics parameters to use.
|
||||
*/
|
||||
void Initialize(const FMetricsParameters& metricsParameters);
|
||||
|
||||
/**
|
||||
* Terminate the GameLift Metrics SDK.
|
||||
*/
|
||||
void Terminate();
|
||||
|
||||
/**
|
||||
* Enable or disable metrics at runtime.
|
||||
* If metrics were previously disabled, this will initialize the metrics system.
|
||||
* If metrics were previously enabled, this will terminate the metrics system.
|
||||
*
|
||||
* @param bEnable Whether to enable or disable metrics
|
||||
* @return True if the operation was successful
|
||||
*/
|
||||
bool SetMetricsEnabled(bool bEnable);
|
||||
|
||||
/**
|
||||
* Check if metrics are currently enabled and running
|
||||
*
|
||||
* @return True if metrics are currently enabled and running
|
||||
*/
|
||||
bool IsMetricsEnabled() const;
|
||||
|
||||
/**
|
||||
* Records a new game session.
|
||||
* Call when starting a new session from the FProcessSettings::OnStartGameSession callback.
|
||||
*/
|
||||
void OnStartGameSession(const Aws::GameLift::Server::Model::GameSession&);
|
||||
|
||||
/**
|
||||
* Records a new player session.
|
||||
*
|
||||
* Call when accepting a player session.
|
||||
*/
|
||||
void OnAcceptPlayerSession();
|
||||
|
||||
/**
|
||||
* Records a removed player session.
|
||||
*
|
||||
* Call when removing a player session.
|
||||
*/
|
||||
void OnRemovePlayerSession();
|
||||
|
||||
private:
|
||||
void StartMetricsCollector();
|
||||
|
||||
TSharedPtr<FSocket> Socket;
|
||||
TUniquePtr<FTickableCollector> Collector;
|
||||
TSharedPtr<FUnrealStatCollector> UnrealStatCollector;
|
||||
static FString CurrentGameSessionId;
|
||||
static FThreadSafeCounter CurrentPlayerCount;
|
||||
bool bMetricsRunning = false; // Tracks if metrics are currently running
|
||||
|
||||
static void CrashHandler(const FGenericCrashContext& Context);
|
||||
|
||||
void ReEmitMetrics();
|
||||
|
||||
friend class FTickableCollector;
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include "GameLiftMetricsConfig.generated.h"
|
||||
|
||||
/**
|
||||
* GameLift Metrics module configuration.
|
||||
*
|
||||
* Can be configured in `DefaultGame.ini`:
|
||||
* ```
|
||||
* [/Script/GameLiftMetricsUnreal.GameLiftMetricsConfig]
|
||||
* CollectorHost = "127.0.0.1"
|
||||
* CollectorPort = 8125
|
||||
* MaxPacketSize = 2048
|
||||
* CaptureIntervalSeconds = 10
|
||||
* bEnableMetrics = true
|
||||
* ```
|
||||
*/
|
||||
UCLASS(config=Game, defaultconfig)
|
||||
class GAMELIFTMETRICS_API UGameLiftMetricsConfig : public UObject
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UGameLiftMetricsConfig() = default;
|
||||
|
||||
/**
|
||||
* Returns the current configuration.
|
||||
*/
|
||||
static const UGameLiftMetricsConfig& Get();
|
||||
|
||||
/**
|
||||
* Whether metrics collection is enabled.
|
||||
* When disabled, no metrics will be collected or sent.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
bool bEnableMetrics = true;
|
||||
|
||||
/**
|
||||
* Host to send metrics to.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
FString CollectorHost = TEXT("127.0.0.1");
|
||||
|
||||
/**
|
||||
* UDP port number to send metrics to.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
int32 CollectorPort = 8125;
|
||||
|
||||
/**
|
||||
* Metrics capture interval before sending data to the collector.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
float CaptureIntervalSeconds = 10.0f;
|
||||
|
||||
/**
|
||||
* Maximum UDP packet size.
|
||||
*
|
||||
* Typical MTU for Internet packets is 1500 bytes.
|
||||
* We set the default to 1472, leaving room for headers.
|
||||
*
|
||||
* For use with collector on same machine or with AWS jumbo packets this value can be bumped up past 1500 bytes.
|
||||
*/
|
||||
UPROPERTY(Config, EditAnywhere, BlueprintReadOnly, Category="GameLift Metrics")
|
||||
int32 MaxPacketSize = 1472;
|
||||
};
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
|
||||
#include <aws/gamelift/metrics/GameLiftMetrics.h>
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(LogGameLiftMetrics, Log, All);
|
||||
|
||||
#define WITH_GAMELIFT_METRICS (WITH_GAMELIFT && UE_SERVER)
|
||||
|
||||
namespace Aws {
|
||||
namespace GameLift {
|
||||
namespace Metrics {
|
||||
/**
|
||||
* Logs in all server builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, Server, WITH_GAMELIFT_METRICS && UE_SERVER);
|
||||
|
||||
/**
|
||||
* Logs in all development or debug server builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, ServerDevelopment, WITH_GAMELIFT_METRICS && UE_SERVER && (UE_BUILD_DEVELOPMENT || UE_BUILD_DEBUG));
|
||||
|
||||
/**
|
||||
* Logs only in debug builds.
|
||||
*/
|
||||
GAMELIFT_METRICS_DEFINE_PLATFORM_API(GAMELIFTMETRICS_API, ServerDebug, WITH_GAMELIFT_METRICS && UE_SERVER && UE_BUILD_DEBUG);
|
||||
} // Metrics
|
||||
} // GameLift
|
||||
} // Aws
|
||||
Reference in New Issue
Block a user