I need to implement an analytics module. And currently I have 2 problems:
a) In EngineAnalytics.cpp in FEngineAnalytics::Initialize() there’s a hardcoded name for a module - “AnalyticsET”. Below in the code there’s mysterious GetEngineAnalyticsOverrideConfigDelegate().IsBound() check. This function is defined as:
/**
* Engine analytics config log to initialize the engine analytics provider.
* External code should bind this delegate if engine analytics are desired,
* preferably in private code that won't be redistributed.
*/
FAnalytics::FProviderConfigurationDelegate& GetEngineAnalyticsOverrideConfigDelegate()
{
static FAnalytics::FProviderConfigurationDelegate Delegate;
return Delegate;
}
But the problem is that declared and defined in *.cpp, I can’t access it from outside.
b) But even if I’ll declare this function in *.h and access it (I tried, but I have an errors - engine tells me something about two_params_delegate or so), this FEngineAnalytics::Initialize() is called in the very begining, i.e. immediately after engine starts. So even if I’ll bind to this delegate in, say MyGameMode constructor, it will be too late - the analytics engine is initialized already.
Just to be sure we are on the same page, are you trying to implement your own analytics module with your own analytics provider, or trying to add analytics to your game using an existing module (like Swrve)?
Beyond that, FEngineAnalytics is meant for analytics of UE4 itself, and exists as an engine singleton to facilitate those needs. those outside of the Epic engine team should have no need to mess with it.
If you are trying to analytics for your game, you should create your own analytics provider outside of that, and control its lifetime in a way that suits your game. For instance, Fortnite and Gears handle analytics by having a provider instance per connected client on the host (they hang it off a PlayerController and/or LocalPlayer). Game like Infinity Blade uses a single, global instance because it is not a multiplayer game.
To see how to configure an analytics provider, look at Analytics.h, particularly the function FAnalytics::GetDefaultConfiguredProvider() and the associated code documentation around it. In general analytics providers are configured flexibly using a configuration delegate, but there is a default implementation provided that configures the provider via INI entries (see FAnalytics::ConfigFromIni).
If you have any other questions getting started, let me know. Documentation for this module is coming, but unfortunately, right now the code docs are the best place to look. They are fairly comprehensive, but it can be frustrating to know where to look first.
Thank you, that helped. I think FAnalytics::CreateAnalyticsProvider is enough for me. But still I have an issue - on shutdown FEngineAnalytics calls destructors for providers before any other module closes (in UEngine::PreExit()) . That way I have an access to, say, HTTPModule on provider close. And this was very handy! Now, managing provider manually when it’s best (and how) to close my module? Is there some sort of PreExit event?
You are correct that module shutdown around this stuff is pretty messy when dealing with singletons. The tricky part is knowing when to shut down your analytics singleton safely. As you can imagine, the earlier you can destroy it, the better.
When you hold onto a TSharedPtr, you are managing the lifetime of the analytics instance outside the lifetime of the module that created it (AnalyticsSwrve for instance), so you have to ensure that you release all references to the SharedPtr<> before modules are destroyed. Overriding UGameEngine::PreExit for your game seems like a reasonable place to destroy your reference, but there are lots of other places that may work better for you as well.