1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ #include < future>
1516#include < map>
17+ #include < mutex>
1618#include < sstream>
1719#include < string>
1820#include < vector>
2527#include " app/src/include/firebase/future.h"
2628#include " app/src/include/firebase/variant.h"
2729#include " app/src/log.h"
30+ #include " firebase/log.h"
2831
2932#if defined(_WIN32)
3033#include < windows.h>
@@ -36,14 +39,16 @@ namespace firebase {
3639namespace analytics {
3740
3841#if defined(_WIN32)
39- #define ANALYTICS_DLL_FILENAME L" analytics_win .dll"
42+ #define ANALYTICS_DLL_FILENAME L" google_analytics .dll"
4043
4144static HMODULE g_analytics_module = 0 ;
4245#endif // defined(_WIN32)
4346
4447// Future data for analytics.
4548// This is initialized in `Initialize()` and cleaned up in `Terminate()`.
4649static bool g_initialized = false ;
50+ static LogCallback g_log_callback;
51+ static std::mutex g_log_callback_mutex;
4752static int g_fake_instance_id = 0 ;
4853static bool g_analytics_collection_enabled = true ;
4954static std::string g_app_id;
@@ -134,6 +139,10 @@ bool IsInitialized() { return g_initialized; }
134139void Terminate () {
135140#if defined(_WIN32)
136141 if (g_analytics_module) {
142+ // Make sure to notify the SDK that the analytics is being terminated to
143+ // upload any pending data.
144+ NotifyAppLifecycleChange (AppLifecycleState::kTermination );
145+
137146 FirebaseAnalytics_UnloadDynamicFunctions ();
138147 FreeLibrary (g_analytics_module);
139148 g_analytics_module = 0 ;
@@ -386,6 +395,58 @@ void ResetAnalyticsData() {
386395 g_fake_instance_id++;
387396}
388397
398+ LogLevel ConvertAnalyticsLogLevelToFirebaseLogLevel (
399+ GoogleAnalytics_LogLevel log_level) {
400+ switch (log_level) {
401+ case kDebug :
402+ return kLogLevelDebug ;
403+ case kInfo :
404+ return kLogLevelInfo ;
405+ case kWarning :
406+ return kLogLevelWarning ;
407+ case kError :
408+ return kLogLevelError ;
409+ default :
410+ return kLogLevelInfo ;
411+ }
412+ }
413+
414+
415+ extern " C" void GoogleAnalyticsWrapperLogCallback (
416+ GoogleAnalytics_LogLevel log_level, const char * message) {
417+ LogCallback callback_to_call;
418+
419+ {
420+ std::lock_guard<std::mutex> lock (g_log_callback_mutex);
421+ callback_to_call = g_log_callback;
422+ }
423+
424+ if (callback_to_call) {
425+ LogLevel firebase_log_level =
426+ ConvertAnalyticsLogLevelToFirebaseLogLevel (log_level);
427+ callback_to_call (firebase_log_level, message);
428+ }
429+ }
430+
431+ // Allows the passing of a callback to be used when the SDK logs any
432+ // messages regarding its behavior. The callback must be thread-safe.
433+ void SetLogCallback (const LogCallback& callback) {
434+ FIREBASE_ASSERT_RETURN_VOID (internal::IsInitialized ());
435+ // The C API does not support user data, so we must use a global variable.
436+ {
437+ std::lock_guard<std::mutex> lock (g_log_callback_mutex);
438+ g_log_callback = callback;
439+ }
440+ GoogleAnalytics_SetLogCallback (GoogleAnalyticsWrapperLogCallback);
441+ }
442+
443+ // Notify the Analytics SDK about the current state of the app's lifecycle.
444+ void NotifyAppLifecycleChange (AppLifecycleState state) {
445+ FIREBASE_ASSERT_RETURN_VOID (internal::IsInitialized ());
446+ GoogleAnalytics_NotifyAppLifecycleChange (
447+ static_cast <GoogleAnalytics_AppLifecycleState>(state));
448+ }
449+
389450// Overloaded versions of LogEvent for convenience.
390451
391452void LogEvent (const char * name) {
0 commit comments