move rncxx logging (#50652)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/50652

Changelog: [Internal]

Reviewed By: zeyap

Differential Revision: D72800216

fbshipit-source-id: 722546b4538fce0d30d90a346a737a564bfd21ee
This commit is contained in:
Andrew Datsenko
2025-04-11 08:06:06 -07:00
committed by Facebook GitHub Bot
parent d18abc8ec7
commit 798eb0ab84
7 changed files with 310 additions and 0 deletions
@@ -0,0 +1,35 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "DefaultLogger.h"
#include <glog/logging.h>
#include <logger/react_native_log.h>
#include <string>
namespace facebook::react {
Logger getDefaultLogger() {
return [](const std::string& message, unsigned int logLevel) {
static std::string tag = "[JavaScript]: ";
switch (logLevel) {
case ReactNativeLogLevelFatal:
case ReactNativeLogLevelError:
LOG(ERROR) << tag << message;
break;
case ReactNativeLogLevelWarning:
LOG(WARNING) << tag << message;
break;
case ReactNativeLogLevelInfo:
default:
LOG(INFO) << tag << message;
break;
}
};
}
} // namespace facebook::react
@@ -0,0 +1,20 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <functional>
#include <string>
namespace facebook::react {
using Logger =
std::function<void(const std::string& message, unsigned int logLevel)>;
Logger getDefaultLogger();
} // namespace facebook::react
@@ -0,0 +1,22 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <glog/logging.h>
#include <jserrorhandler/JsErrorHandler.h>
namespace facebook::react {
static inline JsErrorHandler::OnJsError getDefaultOnJsErrorFunc() {
return [](jsi::Runtime& /*runtime*/,
const JsErrorHandler::ProcessedError& error) {
LOG(ERROR) << "[onJsError called]: " << error << std::endl;
};
}
} // namespace facebook::react
@@ -0,0 +1,43 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "LogOnce.h"
#include <glog/logging.h>
#include <unordered_set>
namespace facebook::react {
LogOnceWrapper::~LogOnceWrapper() {
std::string message = str();
static std::unordered_set<std::string> loggedMessages;
if (loggedMessages.find(message) != loggedMessages.end()) {
return;
}
switch (severity_) {
case Severity::Info:
LOG(INFO) << message;
break;
case Severity::Warning:
LOG(WARNING) << message;
break;
case Severity::Error:
LOG(ERROR) << message;
break;
case Severity::Fatal:
default:
LOG(FATAL) << message;
break;
}
loggedMessages.insert(message);
}
} // namespace facebook::react
@@ -0,0 +1,33 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <glog/logging.h>
#include <sstream>
#define LOG_INFO_ONCE LogOnceWrapper(LogOnceWrapper::Severity::Info)
#define LOG_WARNING_ONCE LogOnceWrapper(LogOnceWrapper::Severity::Warning)
#define LOG_ERROR_ONCE LogOnceWrapper(LogOnceWrapper::Severity::Error)
#define LOG_FATAL_ONCE LogOnceWrapper(LogOnceWrapper::Severity::Fatal)
namespace facebook::react {
class LogOnceWrapper : public std::stringstream {
public:
enum class Severity { Info, Warning, Error, Fatal };
LogOnceWrapper(Severity severity = Severity::Info) : severity_(severity) {}
~LogOnceWrapper();
private:
Severity severity_{Severity::Info};
};
} // namespace facebook::react
@@ -0,0 +1,69 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "NativeExceptionsManager.h"
#include <utility>
namespace facebook::react {
void NativeExceptionsManager::reportFatalException(
jsi::Runtime& rt,
std::string message,
std::vector<StackFrame> stack,
int32_t exceptionId) {
reportException(
rt,
ExceptionData{
.message = std::move(message),
.stack = std::move(stack),
.id = exceptionId,
.isFatal = true});
}
void NativeExceptionsManager::reportSoftException(
jsi::Runtime& rt,
std::string message,
std::vector<StackFrame> stack,
int32_t exceptionId) {
reportException(
rt,
ExceptionData{
.message = std::move(message),
.stack = std::move(stack),
.id = exceptionId,
.isFatal = false});
}
void NativeExceptionsManager::reportException(
jsi::Runtime& runtime,
const ExceptionData& data) {
if (onJsError_) {
std::vector<JsErrorHandler::ProcessedError::StackFrame> frames;
frames.reserve(data.stack.size());
for (const auto& frame : data.stack) {
frames.push_back(JsErrorHandler::ProcessedError::StackFrame{
.file = frame.file,
.methodName = frame.methodName,
.lineNumber = frame.lineNumber,
.column = frame.column});
}
JsErrorHandler::ProcessedError processedError{
.message = data.message,
.originalMessage = std::nullopt,
.name = std::nullopt,
.componentStack = std::nullopt,
.stack = frames,
.id = data.id,
.isFatal = data.isFatal,
.extraData = jsi::Object(runtime),
};
onJsError_(runtime, processedError);
}
}
} // namespace facebook::react
@@ -0,0 +1,88 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <FBReactNativeSpec/FBReactNativeSpecJSI.h>
#include <jserrorhandler/JsErrorHandler.h>
#include <react/bridging/Base.h>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
namespace facebook::react {
// https://github.com/facebook/react-native/blob/v0.71.1/Libraries/Core/NativeExceptionsManager.js#L17-L35
using StackFrame = NativeExceptionsManagerStackFrame<
std::optional<int32_t>,
std::optional<std::string>,
std::optional<int32_t>,
std::string,
std::optional<bool>>;
template <>
struct Bridging<StackFrame>
: NativeExceptionsManagerStackFrameBridging<StackFrame> {};
using ExceptionData = NativeExceptionsManagerExceptionData<
std::string,
std::optional<std::string>,
std::optional<std::string>,
std::optional<std::string>,
std::vector<StackFrame>,
int32_t,
bool,
std::optional<std::unordered_map<std::string, std::string>>>;
template <>
struct Bridging<ExceptionData>
: NativeExceptionsManagerExceptionDataBridging<ExceptionData> {};
class NativeExceptionsManager
: public NativeExceptionsManagerCxxSpec<NativeExceptionsManager> {
public:
NativeExceptionsManager(
JsErrorHandler::OnJsError onJsError,
std::shared_ptr<CallInvoker> jsInvoker)
: NativeExceptionsManagerCxxSpec(jsInvoker),
onJsError_(std::move(onJsError)) {}
void reportFatalException(
jsi::Runtime& rt,
std::string message,
std::vector<StackFrame> stack,
int32_t exceptionId);
void reportSoftException(
jsi::Runtime& rt,
std::string message,
std::vector<StackFrame> stack,
int32_t exceptionId);
void reportException(jsi::Runtime& runtime, const ExceptionData& data);
void updateExceptionMessage(
jsi::Runtime& rt,
jsi::String message,
jsi::Array stack,
double exceptionId) {
// This method is not in modern React Native:
// https://github.com/search?q=repo%3Afacebook%2Freact-native+updateExceptionMessage&type=code
}
void dismissRedbox(jsi::Runtime& rt) {
// Redbox is not supported at this time, LogBox is:
// https://reactnative.dev/blog/2020/07/06/version-0.63
}
private:
JsErrorHandler::OnJsError onJsError_;
};
} // namespace facebook::react