Saving stats to file

Ok, there was really a lot of digging around but I managed to write a function for gathering stats.

First of all - we need to override FStatsThreadState just to get access to the one protected field:

class MYGAME_API FStatsThreadStateOverlay : public FStatsThreadState
{
public:
	int64 GetLastFullFrameProcessed()
	{
		return LastFullFrameProcessed;
	}
};

Oh, the original FStatsThreadState and all needed methods are in “StatsData.h”

Then I had to prepare a Filter structure for future use:

struct FGroupFilter : public IItemFiler
{
	TSet<FName> const& EnabledItems;

	FGroupFilter(TSet<FName> const& InEnabledItems)
		: EnabledItems(InEnabledItems)
	{
	}

	virtual bool Keep(FStatMessage const& Item)
	{
		const FName MessageName = Item.NameAndInfo.GetRawName();
		return EnabledItems.Contains(MessageName);
	}
};

And now time for some magic. Here’s complete code to get all net stats (with comments):

// Get the reference to the stats thread
FStatsThreadStateOverlay& Stats = FStatsThreadStateOverlay&)FStatsThreadState::GetLocalState();

// Get the number of the last processed frame and check if it is valid (just for sure)
int64 LastGoodGameFrame = Stats.GetLastFullFrameProcessed();
if (Stats.IsFrameValid(LastGoodGameFrame) == false)
{
	return;
}

// This is the name of the group where stats are.
FName GroupName = FName(TEXT("STATGROUP_net"));

// Gather the names of the stats that are in this group.
TArray<FName> GroupItems;
Stats.Groups.MultiFind(GroupName, GroupItems);

// Prepare the set of names and raw names of the stats we want to get
TSet<FName> EnabledItems;
for (const FName& ShortName : GroupItems)
{
	EnabledItems.Add(ShortName);
	if (FStatMessage const* LongName = Stats.ShortNameToLongName.Find(ShortName))
	{
		EnabledItems.Add(LongName->NameAndInfo.GetRawName());
	}
}

// Create a filter (needed by stats gathering function)
FGroupFilter Filter(EnabledItems);
	
// Create empty stat stack node (needed by stats gathering function)
FRawStatStackNode HierarchyInclusive;

// Prepare the array for stat messages
TArray<FStatMessage> NonStackStats;

// COLLECT ALL STATS TO THE ARRAY HERE
Stats.UncondenseStackStats(LastGoodGameFrame, HierarchyInclusive, &Filter, &NonStackStats);

// Go through all stats
// There are many ways to display them, dig around the code to display it as you want :)
for (auto Stat : NonStackStats)
{
	// Here we are getting the raw name
	FName StatName = Stat.NameAndInfo.GetRawName();
	UE_LOG(MyLog, Log, TEXT("Received Stat: %s"), *StatName.ToString());

	// Here we are getting values
	int64 iVal = 0;
	double dVal = 0;
	switch (Stat.NameAndInfo.GetField<EStatDataType>())
	{
		case EStatDataType::ST_int64:
			iVal = Stat.GetValue_int64();
			UE_LOG(DTLog, Log, TEXT("Value int64: %lld"), iVal);
			break;
		case EStatDataType::ST_double:
			dVal = Stat.GetValue_double();
			UE_LOG(MyLog, Log, TEXT("Value double: %f"), dVal);
			break;
		default:
			check(0);
	}		
}

One important thing! The function will work only when the “stat net” has been enabled from console. Without it stats won’t be gathered.

1 Like