#include "Log.h"
#include <sys/stat.h>
#include <unistd.h>
#include "Base/CString.h"
#include "Base/Globals.h"
#include "Base/ImmortalWrapper.h"
#include "Base/SysCall.h"
#include "Base/TimeUtils.h"
#include "os/Path.h"
#include "securec.h"
#include "Base/LogFile.h"
namespace MapleRuntime {
static ImmortalWrapper<Logger> g_loggerInstance;
Logger& Logger::GetLogger() noexcept { return *g_loggerInstance; }
#if defined(_WIN64) || defined(__APPLE__)
static LogHandle g_logHandle = nullptr;
void Logger::RegisterLogHandle(LogHandle handle)
{
if (handle == nullptr) {
PRINT_ERROR("logHandle is nullptr\n");
}
g_logHandle = handle;
}
void Logger::InvokeLogHandle(const char* msg)
{
if (g_logHandle != nullptr) {
g_logHandle(msg);
} else {
PRINT_INFO("%s\n", msg);
}
}
#endif
size_t Logger::GetLogFileSize()
{
auto env = std::getenv("MRT_LOG_FILE_SIZE");
if (env == nullptr) {
return DEFAULT_MAX_FILE_SIZE;
}
size_t size = CString::ParseSizeFromEnv(env) * KB;
if (size != 0) {
return size;
} else {
LOG(RTLOG_ERROR,
"Unsupported MRT_LOG_FILE_SIZE parameter. The unit must be added when configuring, "
"it supports 'kb', 'mb', 'gb'. \n");
}
return DEFAULT_MAX_FILE_SIZE;
}
void ATraceBeginAsync(const char* name, int32_t taskId)
{
#if __ANDROID_API__ >= 28
ATrace_beginAsyncSection(name, taskId);
#else
(void)name;
(void)taskId;
#endif
}
void ATraceEndAsync(const char* name, int32_t taskId) {
#if __ANDROID_API__ >= 28
ATrace_endAsyncSection(name, taskId);
#else
(void)name;
(void)taskId;
#endif
}
void ATraceSetCounter(const char* name, int64_t value)
{
#if __ANDROID_API__ >= 28
ATrace_setCounter(name, value);
#else
(void)name;
(void)value;
#endif
}
bool IsHaveCommandInjection(const CString& logPath)
{
#if defined(_WIN64)
std::vector<const char*> injectionChar = { "|", ";", "&", "$", ">", "<", "`", "!", "\n" };
#else
std::vector<const char*> injectionChar = { "|", ";", "&", "$", ">", "<", "`", "\\", "!", "\n" };
#endif
for (size_t i = 0; i < injectionChar.size(); ++i) {
if (strstr(logPath.Str(), injectionChar[i]) != nullptr) {
return true;
}
}
return false;
}
void Logger::GetLogPath(const char* env, CString& logPath)
{
const char* envPath = ::getenv(env);
if (envPath == nullptr) {
return;
}
CString s = CString(envPath).RemoveBlankSpace();
envPath = s.Str();
size_t envPathLen = strlen(envPath);
if (envPathLen < 2 || envPathLen >= PATH_MAX) {
LOG(RTLOG_ERROR, "Unsupported %s parameter. The length should be in [2, 4096).\n", env);
return;
}
#if defined(_WIN64)
const char* separator = "\\";
#else
const char* separator = "/";
#endif
logPath = CString();
int pos = CString(envPath).RFind(separator);
if (pos < 0) {
LOG(RTLOG_ERROR, "%s is not a valid path . Please check again.\n", env);
return;
}
char pathBuf[PATH_MAX + 1] = { 0x00 };
if (pos != static_cast<int>(envPathLen - 1)) {
CString path = CString(envPath).SubStr(0, pos + 1);
CString name = CString(envPath).SubStr(pos + 1);
if ((!name.IsEmpty()) && Os::Path::GetRealPath(path.Str(), pathBuf)) {
logPath = CString(pathBuf);
int separatorPos = logPath.RFind(separator);
if (separatorPos < 0 || separatorPos != static_cast<int>(logPath.Length() - 1)) {
logPath.Append(separator);
}
logPath.Append(name);
}
} else {
if (Os::Path::GetRealPath(envPath, pathBuf)) {
logPath = CString(pathBuf);
}
}
if (IsHaveCommandInjection(logPath)) {
LOG(RTLOG_ERROR, "Unsupported %s parameter. %s has command injection risk.\n", env, env);
return;
}
if (logPath.IsEmpty()) {
LOG(RTLOG_ERROR, "Unsupported %s parameter. %s is empty.\n", env, env);
}
}
Logger::Logger()
{
maxFileSize = GetLogFileSize();
GetLogPath("MRT_LOG_PATH", filePath);
minimumLogLevel = RTLOG_ERROR;
}
bool Logger::InitLog()
{
FILE* newFd = fopen(filePath.Str(), "w");
if (newFd == nullptr) {
PRINT_ERROR("open log file %s failed. msg: %s\n", filePath.Str(), strerror(errno));
filePath = CString();
return false;
}
fd = newFd;
curPosLocation = 0;
return true;
}
RTLogLevel Logger::GetMinimumLogLevel() const { return minimumLogLevel; }
void Logger::SetMinimumLogLevel(RTLogLevel level)
{
if (level < minimumLogLevel) {
minimumLogLevel = level;
}
}
bool Logger::MaybeRotate(size_t curPos, size_t maxSize, FILE* file)
{
if (curPos < maxSize) {
return false;
}
fflush(file);
(void)ftruncate(fileno(file), ftell(file));
rewind(file);
return true;
}
const char LOG_LEVEL[] = { 'V', 'D', 'I', 'I', 'W', 'E', 'F', 'F' };
const uint64_t ERROR_MSG_SIZE = 128;
void WriteStr(int fd, const char* str, bool notInSigHandler)
{
if (notInSigHandler) {
if (fd >= STDERR_FILENO) {
PRINT_ERROR("%s", str);
} else {
PRINT_INFO("%s", str);
}
} else {
if (write(fd, str, strlen(str)) == -1) {
return;
}
}
}
#if (defined(__OHOS__) && (__OHOS__ == 1))
bool Logger::CheckLogLevel(RTLogLevel level)
{
if ((level == RTLOG_DEBUG) && level < GetMinimumLogLevel()) {
return false;
}
if ((!filePath.IsEmpty()) && fd == nullptr) {
std::lock_guard<std::recursive_mutex> lock(logMutex);
if (fd == nullptr && (!InitLog())) {
if (level == RTLOG_FATAL) {
std::abort();
}
return false;
}
}
return true;
}
#else
bool Logger::CheckLogLevel(RTLogLevel level)
{
if (level < GetMinimumLogLevel()) {
return false;
}
if ((!filePath.IsEmpty()) && fd == nullptr) {
std::lock_guard<std::recursive_mutex> lock(logMutex);
if (fd == nullptr && (!InitLog())) {
if (level == RTLOG_FATAL) {
std::abort();
}
return false;
}
}
return true;
}
#endif
#if (defined(__OHOS__) && (__OHOS__ == 1))
static inline void WriteLogOnOhos(RTLogLevel level, const char* buf, bool printTerminal)
{
switch (level) {
case RTLOG_ERROR: {
if (printTerminal) {
printf("%s\n", buf);
}
PRINT_ERROR("%{public}s\n", buf);
break;
}
case RTLOG_FAIL:
case RTLOG_FATAL:
PRINT_FATAL("%{public}s\n", buf);
break;
case RTLOG_DEBUG:
PRINT_DEBUG("%{public}s\n", buf);
break;
case RTLOG_WARNING:
PRINT_WARN("%{public}s\n", buf);
break;
case RTLOG_REPORT:
VLOG(REPORT, "%{public}s\n", buf)
default:
PRINT_INFO("%{public}s\n", buf);
}
}
#endif
#if defined(__ANDROID__)
static inline void WriteLogOnAndroid(RTLogLevel level, const char* buf)
{
switch (level) {
case RTLOG_DEBUG:
PRINT_DEBUG("%s\n", buf);
break;
case RTLOG_WARNING:
PRINT_WARN("%s\n", buf);
break;
case RTLOG_ERROR: {
PRINT_ERROR("%s\n", buf);
break;
}
case RTLOG_FAIL:
case RTLOG_FATAL:
PRINT_FATAL("%s\n", buf);
break;
case RTLOG_REPORT:
VLOG(REPORT, "%{public}s\n", buf)
default:
PRINT_INFO("%s\n", buf);
}
}
#endif
#if defined(__IOS__)
static inline void WriteLogOnIos(RTLogLevel level, const char* buf)
{
switch (level) {
case RTLOG_DEBUG:
PRINT_DEBUG("%{public}s", buf);
break;
case RTLOG_WARNING:
PRINT_WARN("%{public}s", buf);
break;
case RTLOG_ERROR: {
PRINT_ERROR("%{public}s", buf);
break;
}
case RTLOG_FAIL:
case RTLOG_FATAL: {
PRINT_FATAL("%{public}s", buf);
break;
}
case RTLOG_REPORT:
VLOG(REPORT, "%{public}s\n", buf)
default:
PRINT_INFO("%{public}s", buf);
}
}
#endif
void Logger::FormatLog(RTLogLevel level, bool notInSigHandler, const char* format, ...) noexcept
{
if (!CheckLogLevel(level)) {
return;
}
char buf[LOG_BUFFER_SIZE];
int index;
#if defined (__OHOS__) || defined (__ANDROID__)
index = 0;
(void)LOG_LEVEL[level];
#else
if (notInSigHandler) {
index = sprintf_s(buf, sizeof(buf), "%s %d %c ", TimeUtil::GetTimestamp().Str(), MapleRuntime::GetTid(),
LOG_LEVEL[level]);
} else {
index = sprintf_s(buf, sizeof(buf), "%d %c ", MapleRuntime::GetTid(), LOG_LEVEL[level]);
}
#endif
va_list args;
va_start(args, format);
int ret = vsprintf_s(buf + index, sizeof(buf) - index, format, args);
if (ret == -1) {
char errMsg[ERROR_MSG_SIZE];
int errMsgRet = sprintf_s(errMsg, ERROR_MSG_SIZE, "FormatLog vsprintf_s failed. msg: %s\n", strerror(errno));
if (errMsgRet == -1) {
PRINT_ERROR("FormatLog sprintf_s failed\n");
return;
}
WriteStr(STDOUT_FILENO, errMsg, notInSigHandler);
return;
}
index += ret;
va_end(args);
#if (defined(__OHOS__) && (__OHOS__ == 1))
WriteLogOnOhos(level, buf, true);
#elif defined(__ANDROID__)
WriteLogOnAndroid(level, buf);
#elif defined (__IOS__)
WriteLogOnIos(level, buf);
#else
if (filePath.IsEmpty()) {
std::lock_guard<std::recursive_mutex> lock(logMutex);
PRINT_FATAL_IF(sprintf_s(buf, LOG_BUFFER_SIZE, "%s\n", buf) == -1, "FormatLog sprintf_s failed.\n");
if (level >= RTLOG_ERROR) {
WriteStr(STDERR_FILENO, buf, notInSigHandler);
} else {
WriteStr(STDOUT_FILENO, buf, notInSigHandler);
}
} else {
std::lock_guard<std::recursive_mutex> lock(logMutex);
int err;
PRINT_FATAL_IF(sprintf_s(buf, LOG_BUFFER_SIZE, "%s\n", buf) == -1, "FormatLog sprintf_s failed.\n");
if (notInSigHandler) {
err = fprintf(fd, "%s", buf);
} else {
err = write(reinterpret_cast<uint64_t>(fd), buf, strlen(buf));
}
if ((err - 1) != index) {
char errMsg[ERROR_MSG_SIZE];
PRINT_FATAL_IF(sprintf_s(errMsg, ERROR_MSG_SIZE, "FormatLog fprintf failed. msg: %s\n",
strerror(errno)) == -1, "FormatLog sprintf_s failed.\n");
WriteStr(STDERR_FILENO, errMsg, notInSigHandler);
} else {
curPosLocation += index;
if (MaybeRotate(curPosLocation, maxFileSize, fd)) {
curPosLocation = 0;
}
}
if (level == RTLOG_REPORT) {
VLOG(REPORT, "%{public}s\n", buf);
}
if (level == RTLOG_FATAL || level == RTLOG_ERROR) {
fflush(fd);
}
}
#endif
if (level == RTLOG_FATAL) {
std::abort();
}
}
void HiLogForCJThread(RTLogLevel level, const char* format, va_list args)
{
if (!Logger::GetLogger().CheckLogLevel(level)) {
return;
}
char buf[LOG_BUFFER_SIZE / 2];
int ret = vsprintf_s(buf, sizeof(buf), format, args);
if (ret == -1) {
char errMsg[ERROR_MSG_SIZE];
int errMsgRet = sprintf_s(errMsg, ERROR_MSG_SIZE, "FormatLog vsprintf_s failed. msg: %s\n", strerror(errno));
if (errMsgRet == -1) {
PRINT_ERROR("FormatLog sprintf_s failed\n");
return;
}
WriteStr(STDOUT_FILENO, errMsg, true);
return;
}
#if (defined(__OHOS__) && (__OHOS__ == 1))
WriteLogOnOhos(level, buf, false);
#elif defined(__ANDROID__)
WriteLogOnAndroid(level, buf);
#elif defined (__IOS__)
WriteLogOnIos(level, buf);
#endif
if (level == RTLOG_FATAL) {
std::abort();
}
}
#ifdef __ANDROID__
const char* TraceInfoFormat(const char* name, unsigned long long id, unsigned int argNum, ...)
{
if (name == nullptr || *name == '\0') {
return "null info";
}
CString nameStr(name);
CString idStr(static_cast<uint32_t>(id));
if (argNum > 0) {
va_list args;
va_start(args, argNum);
for (unsigned int i = 0; i < argNum; i++) {
const char* arg = va_arg(args, const char*);
if (arg != nullptr && *arg != '\0') {
CString argStr(arg);
nameStr = nameStr.Append(" ");
nameStr = nameStr.Append(argStr);
}
}
va_end(args);
}
nameStr = nameStr.Append(" ");
nameStr = nameStr.Append(idStr);
return nameStr.Str();
}
#endif
#if defined(__ANDROID__)
ATraceWrapper::ATraceWrapper()
{
libHandle = dlopen("libandroid.so", RTLD_LAZY);
if (!libHandle) {
PRINT_ERROR("Failed to dlopen libandroid.so: %s\n", dlerror());
return;
}
beginAsyncFunc = reinterpret_cast<ATraceBeginAsyncSectionFunc>(dlsym(libHandle, "ATrace_beginAsyncSection"));
endAsyncFunc = reinterpret_cast<ATraceEndAsyncSectionFunc>(dlsym(libHandle, "ATrace_endAsyncSection"));
setCounterFunc = reinterpret_cast<ATraceSetCounterFunc>(dlsym(libHandle, "ATrace_setCounter"));
if (beginAsyncFunc && endAsyncFunc && setCounterFunc) {
PRINT_ERROR("ATrace functions all loaded successfully \n");
} else {
PRINT_ERROR("Failed to load some ATrace functions: begin=%p, end=%p, counter=%p \n",
beginAsyncFunc, endAsyncFunc, setCounterFunc);
}
}
ATraceWrapper::~ATraceWrapper()
{
if (libHandle) {
dlclose(libHandle);
libHandle = nullptr;
}
beginAsyncFunc = nullptr;
endAsyncFunc = nullptr;
setCounterFunc = nullptr;
}
ATraceWrapper& ATraceWrapper::GetInstance()
{
static ATraceWrapper instance;
return instance;
}
void ATraceWrapper::BeginAsyncSection(const char* name, int32_t taskId)
{
if (beginAsyncFunc) {
beginAsyncFunc(name, taskId);
}
}
void ATraceWrapper::EndAsyncSection(const char* name, int32_t taskId)
{
if (endAsyncFunc) {
endAsyncFunc(name, taskId);
}
}
void ATraceWrapper::SetCounter(const char* name, int64_t count)
{
if (setCounterFunc) {
setCounterFunc(name, count);
}
}
#endif
#if defined(__IOS__)
SignpostWrapper::SignpostWrapper()
{
libHandle = dlopen("libSystem.dylib", RTLD_LAZY);
if (!libHandle) {
PRINT_ERROR("Failed to dlopen libSystem.dylib: %{public}s \n", dlerror());
return;
}
emitWithNameImplFunc = reinterpret_cast<EmitWithNameImplFunc>(dlsym(libHandle, "_os_signpost_emit_with_name_impl"));
idGenerateFunc = reinterpret_cast<IdGenerateFunc>(dlsym(libHandle, "os_signpost_id_generate"));
idMakeWithPointerFunc = reinterpret_cast<IdMakeWithPointerFunc>(dlsym(libHandle,
"os_signpost_id_make_with_pointer"));
osSignpostEnabledFunc = reinterpret_cast<OsSignpostEnabledFunc>(dlsym(libHandle, "os_signpost_enabled"));
if (emitWithNameImplFunc && idGenerateFunc && idMakeWithPointerFunc && osSignpostEnabledFunc) {
isAvailable = true;
PRINT_ERROR("signpost functions all loaded successfully \n");
} else {
PRINT_ERROR("Failed to load some signpost functions: impl=%p, idGen=%p, idPointer=%p, enabled=%p \n",
emitWithNameImplFunc, idGenerateFunc, idMakeWithPointerFunc, osSignpostEnabledFunc);
}
}
SignpostWrapper::~SignpostWrapper()
{
isAvailable = false;
if (libHandle) {
dlclose(libHandle);
libHandle = nullptr;
}
emitWithNameImplFunc = nullptr;
idGenerateFunc = nullptr;
idMakeWithPointerFunc = nullptr;
osSignpostEnabledFunc = nullptr;
endName = nullptr;
}
SignpostWrapper& SignpostWrapper::GetInstance()
{
static SignpostWrapper instance;
return instance;
}
bool SignpostWrapper::IsIdValid(os_signpost_id_t spId)
{
if (spId == OS_SIGNPOST_ID_NULL || spId == OS_SIGNPOST_ID_INVALID) {
PRINT_WARN("id is null or invalid \n");
return false;
}
return true;
}
bool SignpostWrapper::IsLogValid(os_log_t osLog)
{
if (osSignpostEnabledFunc(osLog)) {
return true;
}
return false;
}
std::pair<size_t, void *> SignpostWrapper::FormatArgs(SignpostType type, const char* name, int64_t value)
{
size_t alignment = 16;
size_t bufferSize = 0;
void *buffer = nullptr;
switch (type) {
case SignpostType::SIGNPOST_TYPE_EVENT: {
if (value >= 0) {
bufferSize = __builtin_os_log_format_buffer_size(EVENT_FORMAT_STR, name, value);
} else {
bufferSize = __builtin_os_log_format_buffer_size(NEG_NUM_FORMAT_STR, name, SignpostInt(value, false));
}
break;
}
case SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN:
case SignpostType::SIGNPOST_TYPE_INTERVAL_END: {
bufferSize = __builtin_os_log_format_buffer_size(INTERVAL_FORMAT_STR, name);
break;
}
case SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN_ASYNC:
case SignpostType::SIGNPOST_TYPE_INTERVAL_END_ASYNC: {
if (value >= 0) {
bufferSize = __builtin_os_log_format_buffer_size(INTERVAL_ASYNC_FORMAT_STR, name,
static_cast<int32_t>(value));
} else {
bufferSize = __builtin_os_log_format_buffer_size(NEG_NUM_FORMAT_STR, name, SignpostInt(value));
}
break;
}
default:
break;
}
if (bufferSize == 0) {
PRINT_ERROR("Error: buffer size calculation failed \n");
return {0, nullptr};
}
int retVal = posix_memalign(&buffer, alignment, bufferSize);
if (!buffer || retVal != 0) {
PRINT_ERROR("Error: buffer malloc failed, retVal: %d \n", retVal);
return {0, nullptr};
}
switch (type) {
case SignpostType::SIGNPOST_TYPE_EVENT: {
if (value >= 0) {
__builtin_os_log_format(buffer, EVENT_FORMAT_STR, name, value);
} else {
__builtin_os_log_format(buffer, NEG_NUM_FORMAT_STR, name, SignpostInt(value, false));
}
break;
}
case SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN:
case SignpostType::SIGNPOST_TYPE_INTERVAL_END: {
__builtin_os_log_format(buffer, INTERVAL_FORMAT_STR, name);
break;
}
case SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN_ASYNC:
case SignpostType::SIGNPOST_TYPE_INTERVAL_END_ASYNC: {
if (value >= 0) {
__builtin_os_log_format(buffer, INTERVAL_ASYNC_FORMAT_STR, name, static_cast<int32_t>(value));
} else {
__builtin_os_log_format(buffer, NEG_NUM_FORMAT_STR, name, SignpostInt(value));
}
break;
}
default:
break;
}
return {bufferSize, buffer};
}
void SignpostWrapper::IntervalBegin(const char* name)
{
if (!isAvailable) {
return;
}
os_log_t osLog = GetLog();
os_signpost_id_t spId = idGenerateFunc(osLog);
GetId() = spId;
if (!IsIdValid(spId) || !IsLogValid(osLog)) {
return;
}
endName = ((name == nullptr || name[0] == '\0') ? "unnamedOperation" : name);
SetName(endName);
auto bufferPair = FormatArgs(SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN, endName);
size_t bufferSize = bufferPair.first;
void *buffer = bufferPair.second;
if (bufferSize == 0 || buffer == nullptr) {
return;
}
emitWithNameImplFunc(&__dso_handle, osLog, OS_SIGNPOST_INTERVAL_BEGIN, spId, "Operation",
"name:%{public}s", static_cast<uint8_t*>(buffer), static_cast<uint32_t>(bufferSize));
std::free(buffer);
}
void SignpostWrapper::IntervalEnd()
{
if (!isAvailable) {
return;
}
os_log_t osLog = GetLog();
os_signpost_id_t spId = GetId();
if (!IsIdValid(spId) || !IsLogValid(osLog)) {
return;
}
const char* taskName = GetName();
taskName = ((taskName == nullptr || taskName[0] == '\0') ? "unnamedOperation" : taskName);
auto bufferPair = FormatArgs(SignpostType::SIGNPOST_TYPE_INTERVAL_END, taskName);
size_t bufferSize = bufferPair.first;
void *buffer = bufferPair.second;
if (bufferSize == 0 || buffer == nullptr) {
return;
}
emitWithNameImplFunc(&__dso_handle, osLog, OS_SIGNPOST_INTERVAL_END, spId, "Operation",
"name:%{public}s", static_cast<uint8_t*>(buffer), static_cast<uint32_t>(bufferSize));
std::free(buffer);
}
void SignpostWrapper::IntervalBeginAsync(const char* name, int32_t taskId)
{
if (!isAvailable) {
return;
}
os_log_t osLog = GetLog();
uintptr_t ptrVal = static_cast<uintptr_t>(taskId);
os_signpost_id_t spId = idMakeWithPointerFunc(osLog, reinterpret_cast<void*>(ptrVal));
if (!IsIdValid(spId) || !IsLogValid(osLog)) {
return;
}
const char* taskName = ((name == nullptr || name[0] == '\0') ? "unnamedOperationAsync" : name);
auto bufferPair = FormatArgs(SignpostType::SIGNPOST_TYPE_INTERVAL_BEGIN_ASYNC, taskName, taskId);
size_t bufferSize = bufferPair.first;
void *buffer = bufferPair.second;
if (bufferSize == 0 || buffer == nullptr) {
return;
}
emitWithNameImplFunc(&__dso_handle, osLog, OS_SIGNPOST_INTERVAL_BEGIN, spId, "AsyncOperation",
((taskId >= 0) ? "name:%{public}s, taskId:%d" : PRINT_NEG_NUM_FMT),
static_cast<uint8_t*>(buffer), static_cast<uint32_t>(bufferSize));
std::free(buffer);
}
void SignpostWrapper::IntervalEndAsync(const char* name, int32_t taskId)
{
if (!isAvailable) {
return;
}
os_log_t osLog = GetLog();
intptr_t ptrVal = static_cast<uintptr_t>(taskId);
os_signpost_id_t spId = idMakeWithPointerFunc(osLog, reinterpret_cast<void*>(ptrVal));
if (!IsIdValid(spId) || !IsLogValid(osLog)) {
return;
}
const char* taskName = ((name == nullptr || name[0] == '\0') ? "unnamedOperationAsync" : name);
auto bufferPair = FormatArgs(SignpostType::SIGNPOST_TYPE_INTERVAL_END_ASYNC, taskName, taskId);
size_t bufferSize = bufferPair.first;
void *buffer = bufferPair.second;
if (bufferSize == 0 || buffer == nullptr) {
return;
}
emitWithNameImplFunc(&__dso_handle, osLog, OS_SIGNPOST_INTERVAL_END, spId, "AsyncOperation",
((taskId >= 0) ? "name:%{public}s, taskId:%d" : PRINT_NEG_NUM_FMT),
static_cast<uint8_t*>(buffer), static_cast<uint32_t>(bufferSize));
std::free(buffer);
}
void SignpostWrapper::EventEmit(const char* name, int64_t count)
{
if (!isAvailable) {
return;
}
os_log_t osLog = GetLog();
os_signpost_id_t spId = idGenerateFunc(osLog);
if (!IsIdValid(spId) || !IsLogValid(osLog)) {
return;
}
const char* taskName = ((name == nullptr || name[0] == '\0') ? "unnamedOperationEmit" : name);
auto bufferPair = FormatArgs(SignpostType::SIGNPOST_TYPE_EVENT, taskName, count);
size_t bufferSize = bufferPair.first;
void *buffer = bufferPair.second;
if (bufferSize == 0 || buffer == nullptr) {
return;
}
emitWithNameImplFunc(&__dso_handle, osLog, OS_SIGNPOST_EVENT, spId, "OperationEmit",
((count >= 0) ? "name:%{public}s, count: %lld" : PRINT_NEG_NUM_FMT),
static_cast<uint8_t*>(buffer), static_cast<uint32_t>(bufferSize));
std::free(buffer);
}
#endif
}