From 9294c6f5d4afcaf4c1020c3b9de342b66ed258c9 Mon Sep 17 00:00:00 2001 From: Chris Hopman Date: Fri, 19 Feb 2016 16:22:16 -0800 Subject: [PATCH] Initialize glog in react native. Reviewed By: astreet Differential Revision: D2931172 fb-gh-sync-id: 837af947846ba862f7e82110771a680f6991342f shipit-source-id: 837af947846ba862f7e82110771a680f6991342f --- .../jni/first-party/fbgloginit/Android.mk | 24 +++ .../src/main/jni/first-party/fbgloginit/BUCK | 21 +++ .../jni/first-party/fbgloginit/fb/glog_init.h | 11 ++ .../jni/first-party/fbgloginit/glog_init.cpp | 142 ++++++++++++++++++ .../src/main/jni/react/jni/Android.mk | 3 +- ReactAndroid/src/main/jni/react/jni/BUCK | 1 + .../src/main/jni/react/jni/OnLoad.cpp | 2 + 7 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h create mode 100644 ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk b/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk new file mode 100644 index 000000000..e768bb215 --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + glog_init.cpp + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/ +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.. + +LOCAL_CFLAGS := -fexceptions -fno-omit-frame-pointer +LOCAL_CFLAGS += -Wall -Werror + +CXX11_FLAGS := -std=gnu++11 +LOCAL_CFLAGS += $(CXX11_FLAGS) + +LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS) + +LOCAL_LDLIBS := -llog + +LOCAL_SHARED_LIBRARIES := libglog + +LOCAL_MODULE := libglog_init + +include $(BUILD_SHARED_LIBRARY) diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK new file mode 100644 index 000000000..c058851bd --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/BUCK @@ -0,0 +1,21 @@ +cxx_library( + name = 'fbgloginit', + force_static = True, + srcs = [ + 'glog_init.cpp', + ], + exported_headers = ['fb/glog_init.h'], + header_namespace = 'fbgloginit', + compiler_flags = [ + '-fexceptions', + '-fno-omit-frame-pointer', + ], + linker_flags = [ + '-llog', + ], + deps=[ + '//xplat/third-party/glog:glog', + ], + visibility=['PUBLIC'], +) + diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h b/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h new file mode 100644 index 000000000..a37798622 --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/fb/glog_init.h @@ -0,0 +1,11 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#pragma once + +#include + +namespace facebook { namespace gloginit { + +void initialize(const char* tag = "fb"); + +}} diff --git a/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp b/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp new file mode 100644 index 000000000..771516a2d --- /dev/null +++ b/ReactAndroid/src/main/jni/first-party/fbgloginit/glog_init.cpp @@ -0,0 +1,142 @@ +// Copyright 2004-present Facebook. All Rights Reserved. + +#include "fb/glog_init.h" + +#include +#include +#include + +#include + +#ifdef __ANDROID__ + +#include + +static int toAndroidLevel(google::LogSeverity severity) { + switch (severity) { + case google::GLOG_INFO: + return ANDROID_LOG_INFO; + case google::GLOG_WARNING: + return ANDROID_LOG_WARN; + case google::GLOG_ERROR: + return ANDROID_LOG_ERROR; + case google::GLOG_FATAL: + return ANDROID_LOG_FATAL; + default: + return ANDROID_LOG_FATAL; + } +} + +/** + * Sends GLog output to adb logcat. + */ +class LogcatSink : public google::LogSink { + public: + void send( + google::LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const struct ::tm* tm_time, + const char* message, + size_t message_len) override { + auto level = toAndroidLevel(severity); + __android_log_print( + level, + base_filename, + "%.*s", + (int)message_len, + message); + } +}; + +/** + * Sends GLog output to adb logcat. + */ +class TaggedLogcatSink : public google::LogSink { + const std::string tag_; + + public: + TaggedLogcatSink(const std::string &tag) : tag_{tag} {} + + void send( + google::LogSeverity severity, + const char* full_filename, + const char* base_filename, + int line, + const struct ::tm* tm_time, + const char* message, + size_t message_len) override { + auto level = toAndroidLevel(severity); + __android_log_print( + level, + tag_.c_str(), + "%.*s", + (int)message_len, + message); + } +}; + +static google::LogSink* make_sink(const std::string& tag) { + if (tag.empty()) { + return new LogcatSink{}; + } else { + return new TaggedLogcatSink{tag}; + } +} + +static void sendGlogOutputToLogcat(const char* tag) { + google::AddLogSink(make_sink(tag)); + + // Disable logging to files + for (auto i = 0; i < google::NUM_SEVERITIES; ++i) { + google::SetLogDestination(i, ""); + } +} + +#endif // __ANDROID__ + +static void lastResort(const char* tag, const char* msg, const char* arg = nullptr) { +#ifdef __ANDROID__ + if (!arg) { + __android_log_write(ANDROID_LOG_ERROR, tag, msg); + } else { + __android_log_print(ANDROID_LOG_ERROR, tag, "%s: %s", msg, arg); + } +#else + std::cerr << msg; + if (arg) { + std::cerr << ": " << arg; + } + std::cerr << std::endl; +#endif +} + +namespace facebook { namespace gloginit { + +void initialize(const char* tag) { + static std::once_flag flag{}; + static auto failed = false; + + std::call_once(flag, [tag] { + try { + google::InitGoogleLogging(tag); + +#ifdef __ANDROID__ + sendGlogOutputToLogcat(tag); +#endif + } catch (std::exception& ex) { + lastResort(tag, "Failed to initialize glog", ex.what()); + failed = true; + } catch (...) { + lastResort(tag, "Failed to initialize glog"); + failed = true; + } + }); + + if (failed) { + throw std::runtime_error{"Failed to initialize glog"}; + } +} + +}} diff --git a/ReactAndroid/src/main/jni/react/jni/Android.mk b/ReactAndroid/src/main/jni/react/jni/Android.mk index 9d4d9b2b5..e5184d8e8 100644 --- a/ReactAndroid/src/main/jni/react/jni/Android.mk +++ b/ReactAndroid/src/main/jni/react/jni/Android.mk @@ -22,7 +22,7 @@ LOCAL_CFLAGS += $(CXX11_FLAGS) LOCAL_EXPORT_CPPFLAGS := $(CXX11_FLAGS) LOCAL_LDLIBS += -landroid -LOCAL_SHARED_LIBRARIES := libfolly_json libfbjni libjsc +LOCAL_SHARED_LIBRARIES := libfolly_json libfbjni libjsc libglog_init LOCAL_STATIC_LIBRARIES := libreactnative include $(BUILD_SHARED_LIBRARY) @@ -30,5 +30,6 @@ include $(BUILD_SHARED_LIBRARY) $(call import-module,react) $(call import-module,jsc) $(call import-module,folly) +$(call import-module,fbgloginit) $(call import-module,jni) $(call import-module,jsc) diff --git a/ReactAndroid/src/main/jni/react/jni/BUCK b/ReactAndroid/src/main/jni/react/jni/BUCK index bebdf54ce..180bac5b8 100644 --- a/ReactAndroid/src/main/jni/react/jni/BUCK +++ b/ReactAndroid/src/main/jni/react/jni/BUCK @@ -4,6 +4,7 @@ include_defs('//ReactAndroid/DEFS') SUPPORTED_PLATFORMS = '^android-(armv7|x86)$' DEPS = [ + react_native_target('jni/first-party/fbgloginit:fbgloginit'), '//native/jni:jni', '//native/third-party/android-ndk:android', '//xplat/folly:molly', diff --git a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp index 1e4c37950..9f5d95698 100644 --- a/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp +++ b/ReactAndroid/src/main/jni/react/jni/OnLoad.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -844,6 +845,7 @@ jmethodID getLogMarkerMethod() { extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { return initialize(vm, [] { + facebook::gloginit::initialize(LOG_TAG); // Inject some behavior into react/ ReactMarker::logMarker = bridge::logMarker; WebWorkerUtil::createWebWorkerThread = WebWorkers::createWebWorkerThread;