12498b56bSopenharmony_ci/*
22498b56bSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
32498b56bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
42498b56bSopenharmony_ci * you may not use this file except in compliance with the License.
52498b56bSopenharmony_ci * You may obtain a copy of the License at
62498b56bSopenharmony_ci *
72498b56bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
82498b56bSopenharmony_ci *
92498b56bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
102498b56bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
112498b56bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122498b56bSopenharmony_ci * See the License for the specific language governing permissions and
132498b56bSopenharmony_ci * limitations under the License.
142498b56bSopenharmony_ci */
152498b56bSopenharmony_ci#include <cerrno>
162498b56bSopenharmony_ci#include <cstdarg>
172498b56bSopenharmony_ci#include <cstdio>
182498b56bSopenharmony_ci#include <ctime>
192498b56bSopenharmony_ci#include <fstream>
202498b56bSopenharmony_ci#include <iostream>
212498b56bSopenharmony_ci#include <mutex>
222498b56bSopenharmony_ci#include <securec.h>
232498b56bSopenharmony_ci#include <fcntl.h>
242498b56bSopenharmony_ci#include <sys/stat.h>
252498b56bSopenharmony_ci#include <sys/types.h>
262498b56bSopenharmony_ci
272498b56bSopenharmony_ci#ifdef __LINUX__
282498b56bSopenharmony_ci#include <atomic>
292498b56bSopenharmony_ci#endif
302498b56bSopenharmony_ci
312498b56bSopenharmony_ci#ifndef __WINDOWS__
322498b56bSopenharmony_ci#include <sys/syscall.h>
332498b56bSopenharmony_ci#include <sys/types.h>
342498b56bSopenharmony_ci#else
352498b56bSopenharmony_ci#include <windows.h>
362498b56bSopenharmony_ci#include <memory.h>
372498b56bSopenharmony_ci#endif
382498b56bSopenharmony_ci#include <unistd.h>
392498b56bSopenharmony_ci
402498b56bSopenharmony_ci#include "log_timestamp.h"
412498b56bSopenharmony_ci#include "hilog_trace.h"
422498b56bSopenharmony_ci#include "hilog_inner.h"
432498b56bSopenharmony_ci#include "hilog/log.h"
442498b56bSopenharmony_ci#include "hilog_common.h"
452498b56bSopenharmony_ci#include "vsnprintf_s_p.h"
462498b56bSopenharmony_ci#include "log_utils.h"
472498b56bSopenharmony_ci
482498b56bSopenharmony_ci#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ ))
492498b56bSopenharmony_ci#include "properties.h"
502498b56bSopenharmony_ci#include "hilog_input_socket_client.h"
512498b56bSopenharmony_ci#else
522498b56bSopenharmony_ci#include "log_print.h"
532498b56bSopenharmony_ci#endif
542498b56bSopenharmony_ci
552498b56bSopenharmony_ciusing namespace std;
562498b56bSopenharmony_ciusing namespace OHOS::HiviewDFX;
572498b56bSopenharmony_cistatic RegisterFunc g_registerFunc = nullptr;
582498b56bSopenharmony_cistatic LogCallback g_logCallback = nullptr;
592498b56bSopenharmony_cistatic atomic_int g_hiLogGetIdCallCount = 0;
602498b56bSopenharmony_ci// protected by static lock guard
612498b56bSopenharmony_cistatic char g_hiLogLastFatalMessage[MAX_LOG_LEN] = { 0 }; // MAX_lOG_LEN : 1024
622498b56bSopenharmony_ci
632498b56bSopenharmony_ciHILOG_PUBLIC_API
642498b56bSopenharmony_ciextern "C" const char* GetLastFatalMessage()
652498b56bSopenharmony_ci{
662498b56bSopenharmony_ci    return g_hiLogLastFatalMessage;
672498b56bSopenharmony_ci}
682498b56bSopenharmony_ci
692498b56bSopenharmony_ciint HiLogRegisterGetIdFun(RegisterFunc registerFunc)
702498b56bSopenharmony_ci{
712498b56bSopenharmony_ci    if (g_registerFunc != nullptr) {
722498b56bSopenharmony_ci        return -1;
732498b56bSopenharmony_ci    }
742498b56bSopenharmony_ci    g_registerFunc = registerFunc;
752498b56bSopenharmony_ci    return 0;
762498b56bSopenharmony_ci}
772498b56bSopenharmony_ci
782498b56bSopenharmony_civoid HiLogUnregisterGetIdFun(RegisterFunc registerFunc)
792498b56bSopenharmony_ci{
802498b56bSopenharmony_ci    if (g_registerFunc != registerFunc) {
812498b56bSopenharmony_ci        return;
822498b56bSopenharmony_ci    }
832498b56bSopenharmony_ci
842498b56bSopenharmony_ci    g_registerFunc = nullptr;
852498b56bSopenharmony_ci    while (atomic_load(&g_hiLogGetIdCallCount) != 0) {
862498b56bSopenharmony_ci        /* do nothing, just wait current callback return */
872498b56bSopenharmony_ci    }
882498b56bSopenharmony_ci
892498b56bSopenharmony_ci    return;
902498b56bSopenharmony_ci}
912498b56bSopenharmony_ci
922498b56bSopenharmony_civoid LOG_SetCallback(LogCallback callback)
932498b56bSopenharmony_ci{
942498b56bSopenharmony_ci    g_logCallback = callback;
952498b56bSopenharmony_ci}
962498b56bSopenharmony_ci
972498b56bSopenharmony_cistatic uint16_t GetFinalLevel(unsigned int domain, const std::string& tag)
982498b56bSopenharmony_ci{
992498b56bSopenharmony_ci    // Priority: TagLevel > DomainLevel > GlobalLevel
1002498b56bSopenharmony_ci    // LOG_LEVEL_MIN is default Level
1012498b56bSopenharmony_ci#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ ))
1022498b56bSopenharmony_ci    uint16_t tagLevel = GetTagLevel(tag);
1032498b56bSopenharmony_ci    if (tagLevel != LOG_LEVEL_MIN) {
1042498b56bSopenharmony_ci        return tagLevel;
1052498b56bSopenharmony_ci    }
1062498b56bSopenharmony_ci    uint16_t domainLevel = GetDomainLevel(domain);
1072498b56bSopenharmony_ci    if (domainLevel != LOG_LEVEL_MIN) {
1082498b56bSopenharmony_ci        return domainLevel;
1092498b56bSopenharmony_ci    }
1102498b56bSopenharmony_ci    // domain within the range of [DOMAIN_APP_MIN, DOMAIN_APP_MAX] is a js log,
1112498b56bSopenharmony_ci    // if this js log comes from debuggable hap, set the default level.
1122498b56bSopenharmony_ci    if ((domain >= DOMAIN_APP_MIN) && (domain <= DOMAIN_APP_MAX)) {
1132498b56bSopenharmony_ci        static bool isDebuggableHap = IsDebuggableHap();
1142498b56bSopenharmony_ci        if (isDebuggableHap) {
1152498b56bSopenharmony_ci            return LOG_LEVEL_MIN;
1162498b56bSopenharmony_ci        }
1172498b56bSopenharmony_ci    }
1182498b56bSopenharmony_ci    return GetGlobalLevel();
1192498b56bSopenharmony_ci#else
1202498b56bSopenharmony_ci    return LOG_LEVEL_MIN;
1212498b56bSopenharmony_ci#endif
1222498b56bSopenharmony_ci}
1232498b56bSopenharmony_ci
1242498b56bSopenharmony_ci#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ ))
1252498b56bSopenharmony_cistatic int HiLogFlowCtrlProcess(int len, const struct timespec &ts)
1262498b56bSopenharmony_ci{
1272498b56bSopenharmony_ci    static uint32_t processQuota = 0;
1282498b56bSopenharmony_ci    static atomic_int gSumLen = 0;
1292498b56bSopenharmony_ci    static atomic_int gDropped = 0;
1302498b56bSopenharmony_ci    static atomic<LogTimeStamp> gStartTime;
1312498b56bSopenharmony_ci    static LogTimeStamp period(1, 0);
1322498b56bSopenharmony_ci    static std::atomic_flag isFirstFlag = ATOMIC_FLAG_INIT;
1332498b56bSopenharmony_ci    if (!isFirstFlag.test_and_set()) {
1342498b56bSopenharmony_ci        processQuota = GetProcessQuota(GetProgName());
1352498b56bSopenharmony_ci    }
1362498b56bSopenharmony_ci    LogTimeStamp tsStart = atomic_load(&gStartTime);
1372498b56bSopenharmony_ci    LogTimeStamp tsNow(ts);
1382498b56bSopenharmony_ci    tsStart += period;
1392498b56bSopenharmony_ci    /* in statistic period(1 second) */
1402498b56bSopenharmony_ci    if (tsNow > tsStart) { /* new statistic period, return how many lines were dropped */
1412498b56bSopenharmony_ci        int dropped = atomic_exchange_explicit(&gDropped, 0, memory_order_relaxed);
1422498b56bSopenharmony_ci        atomic_store(&gStartTime, tsNow);
1432498b56bSopenharmony_ci        atomic_store(&gSumLen, len);
1442498b56bSopenharmony_ci        return dropped;
1452498b56bSopenharmony_ci    } else {
1462498b56bSopenharmony_ci        uint32_t sumLen = (uint32_t)atomic_load(&gSumLen);
1472498b56bSopenharmony_ci        if (sumLen > processQuota) { /* over quota, -1 means don't print */
1482498b56bSopenharmony_ci            atomic_fetch_add_explicit(&gDropped, 1, memory_order_relaxed);
1492498b56bSopenharmony_ci            return -1;
1502498b56bSopenharmony_ci        } else { /* under quota, 0 means do print */
1512498b56bSopenharmony_ci            atomic_fetch_add_explicit(&gSumLen, len, memory_order_relaxed);
1522498b56bSopenharmony_ci        }
1532498b56bSopenharmony_ci    }
1542498b56bSopenharmony_ci    return 0;
1552498b56bSopenharmony_ci}
1562498b56bSopenharmony_ci
1572498b56bSopenharmony_cistatic bool IsNeedProcFlowCtr(const LogType type)
1582498b56bSopenharmony_ci{
1592498b56bSopenharmony_ci    if (type != LOG_APP) {
1602498b56bSopenharmony_ci        return false;
1612498b56bSopenharmony_ci    }
1622498b56bSopenharmony_ci    //debuggable hap don't perform process flow control
1632498b56bSopenharmony_ci    static bool isDebuggableHap = IsDebuggableHap();
1642498b56bSopenharmony_ci    if (IsProcessSwitchOn() && !isDebuggableHap) {
1652498b56bSopenharmony_ci        return true;
1662498b56bSopenharmony_ci    }
1672498b56bSopenharmony_ci    return false;
1682498b56bSopenharmony_ci}
1692498b56bSopenharmony_ci#else
1702498b56bSopenharmony_cistatic int PrintLog(HilogMsg& header, const char *tag, uint16_t tagLen, const char *fmt, uint16_t fmtLen)
1712498b56bSopenharmony_ci{
1722498b56bSopenharmony_ci    LogContent content = {
1732498b56bSopenharmony_ci        .level = header.level,
1742498b56bSopenharmony_ci        .type = header.type,
1752498b56bSopenharmony_ci        .pid = header.pid,
1762498b56bSopenharmony_ci        .tid = header.tid,
1772498b56bSopenharmony_ci        .domain = header.domain,
1782498b56bSopenharmony_ci        .tv_sec = header.tv_sec,
1792498b56bSopenharmony_ci        .tv_nsec = header.tv_nsec,
1802498b56bSopenharmony_ci        .mono_sec = header.mono_sec,
1812498b56bSopenharmony_ci        .tag = tag,
1822498b56bSopenharmony_ci        .log = fmt,
1832498b56bSopenharmony_ci    };
1842498b56bSopenharmony_ci    LogFormat format = {
1852498b56bSopenharmony_ci        .colorful = false,
1862498b56bSopenharmony_ci        .timeFormat = FormatTime::TIME,
1872498b56bSopenharmony_ci        .timeAccuFormat = FormatTimeAccu::MSEC,
1882498b56bSopenharmony_ci        .year = false,
1892498b56bSopenharmony_ci        .zone = false,
1902498b56bSopenharmony_ci    };
1912498b56bSopenharmony_ci    LogPrintWithFormat(content, format);
1922498b56bSopenharmony_ci    return RET_SUCCESS;
1932498b56bSopenharmony_ci}
1942498b56bSopenharmony_ci#endif
1952498b56bSopenharmony_ci
1962498b56bSopenharmony_cistatic int LogToKmsg(const LogLevel level, const char *tag, const char* info)
1972498b56bSopenharmony_ci{
1982498b56bSopenharmony_ci    static int fd = open("/dev/kmsg", O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
1992498b56bSopenharmony_ci    if (fd < 0) {
2002498b56bSopenharmony_ci        printf("open /dev/kmsg failed, fd=%d. \n", fd);
2012498b56bSopenharmony_ci        return -1;
2022498b56bSopenharmony_ci    }
2032498b56bSopenharmony_ci    char logInfo[MAX_LOG_LEN] = {0};
2042498b56bSopenharmony_ci    if (snprintf_s(logInfo, sizeof(logInfo), sizeof(logInfo) - 1, "<%d>%s: %s\n", level, tag, info) == -1) {
2052498b56bSopenharmony_ci        logInfo[sizeof(logInfo) - 2] = '\n';  // 2 add \n to tail
2062498b56bSopenharmony_ci        logInfo[sizeof(logInfo) - 1] = '\0';
2072498b56bSopenharmony_ci    }
2082498b56bSopenharmony_ci#ifdef __LINUX__
2092498b56bSopenharmony_ci    return TEMP_FAILURE_RETRY(write(fd, logInfo, strlen(logInfo)));
2102498b56bSopenharmony_ci#else
2112498b56bSopenharmony_ci    return write(fd, logInfo, strlen(logInfo));
2122498b56bSopenharmony_ci#endif
2132498b56bSopenharmony_ci}
2142498b56bSopenharmony_ci
2152498b56bSopenharmony_ciint HiLogPrintArgs(const LogType type, const LogLevel level, const unsigned int domain, const char *tag,
2162498b56bSopenharmony_ci    const char *fmt, va_list ap)
2172498b56bSopenharmony_ci{
2182498b56bSopenharmony_ci    if ((type != LOG_APP) && ((domain < DOMAIN_OS_MIN) || (domain > DOMAIN_OS_MAX))) {
2192498b56bSopenharmony_ci        return -1;
2202498b56bSopenharmony_ci    }
2212498b56bSopenharmony_ci    if (!HiLogIsLoggable(domain, tag, level)) {
2222498b56bSopenharmony_ci        return -1;
2232498b56bSopenharmony_ci    }
2242498b56bSopenharmony_ci    if (type == LOG_KMSG) {
2252498b56bSopenharmony_ci        char tmpFmt[MAX_LOG_LEN] = {0};
2262498b56bSopenharmony_ci        // format va_list info to char*
2272498b56bSopenharmony_ci        if (vsnprintfp_s(tmpFmt, sizeof(tmpFmt), sizeof(tmpFmt) - 1, true, fmt, ap) == -1) {
2282498b56bSopenharmony_ci            tmpFmt[sizeof(tmpFmt) - 2] = '\n';  // 2 add \n to tail
2292498b56bSopenharmony_ci            tmpFmt[sizeof(tmpFmt) - 1] = '\0';
2302498b56bSopenharmony_ci        }
2312498b56bSopenharmony_ci        return LogToKmsg(level, tag, tmpFmt);
2322498b56bSopenharmony_ci    }
2332498b56bSopenharmony_ci
2342498b56bSopenharmony_ci    HilogMsg header = {0};
2352498b56bSopenharmony_ci    struct timespec ts = {0};
2362498b56bSopenharmony_ci    (void)clock_gettime(CLOCK_REALTIME, &ts);
2372498b56bSopenharmony_ci    struct timespec ts_mono = {0};
2382498b56bSopenharmony_ci    (void)clock_gettime(CLOCK_MONOTONIC, &ts_mono);
2392498b56bSopenharmony_ci    header.tv_sec = static_cast<uint32_t>(ts.tv_sec);
2402498b56bSopenharmony_ci    header.tv_nsec = static_cast<uint32_t>(ts.tv_nsec);
2412498b56bSopenharmony_ci    header.mono_sec = static_cast<uint32_t>(ts_mono.tv_sec);
2422498b56bSopenharmony_ci
2432498b56bSopenharmony_ci    char buf[MAX_LOG_LEN] = {0};
2442498b56bSopenharmony_ci    char *logBuf = buf;
2452498b56bSopenharmony_ci    int traceBufLen = 0;
2462498b56bSopenharmony_ci    int ret;
2472498b56bSopenharmony_ci    /* print traceid */
2482498b56bSopenharmony_ci    if (g_registerFunc != nullptr) {
2492498b56bSopenharmony_ci        uint64_t chainId = 0;
2502498b56bSopenharmony_ci        uint32_t flag = 0;
2512498b56bSopenharmony_ci        uint64_t spanId = 0;
2522498b56bSopenharmony_ci        uint64_t parentSpanId = 0;
2532498b56bSopenharmony_ci        ret = -1;  /* default value -1: invalid trace id */
2542498b56bSopenharmony_ci        atomic_fetch_add_explicit(&g_hiLogGetIdCallCount, 1, memory_order_relaxed);
2552498b56bSopenharmony_ci        RegisterFunc func = g_registerFunc;
2562498b56bSopenharmony_ci        if (func != nullptr) {
2572498b56bSopenharmony_ci            ret = func(&chainId, &flag, &spanId, &parentSpanId);
2582498b56bSopenharmony_ci        }
2592498b56bSopenharmony_ci        atomic_fetch_sub_explicit(&g_hiLogGetIdCallCount, 1, memory_order_relaxed);
2602498b56bSopenharmony_ci        if (ret == 0) {  /* 0: trace id with span id */
2612498b56bSopenharmony_ci            traceBufLen = snprintf_s(logBuf, MAX_LOG_LEN, MAX_LOG_LEN - 1, "[%llx, %llx, %llx] ",
2622498b56bSopenharmony_ci                (unsigned long long)chainId, (unsigned long long)spanId, (unsigned long long)parentSpanId);
2632498b56bSopenharmony_ci        } else if (ret != -1) {  /* trace id without span id, -1: invalid trace id */
2642498b56bSopenharmony_ci            traceBufLen = snprintf_s(logBuf, MAX_LOG_LEN, MAX_LOG_LEN - 1, "[%llx] ",
2652498b56bSopenharmony_ci                (unsigned long long)chainId);
2662498b56bSopenharmony_ci        }
2672498b56bSopenharmony_ci        if (traceBufLen > 0) {
2682498b56bSopenharmony_ci            logBuf += traceBufLen;
2692498b56bSopenharmony_ci        } else {
2702498b56bSopenharmony_ci            traceBufLen = 0;
2712498b56bSopenharmony_ci        }
2722498b56bSopenharmony_ci    }
2732498b56bSopenharmony_ci
2742498b56bSopenharmony_ci    /* format log string */
2752498b56bSopenharmony_ci#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ ))
2762498b56bSopenharmony_ci    bool debug = IsDebugOn();
2772498b56bSopenharmony_ci    bool priv = (!debug) && IsPrivateSwitchOn();
2782498b56bSopenharmony_ci#else
2792498b56bSopenharmony_ci    bool priv = true;
2802498b56bSopenharmony_ci#endif
2812498b56bSopenharmony_ci
2822498b56bSopenharmony_ci#ifdef __clang__
2832498b56bSopenharmony_ci/* code specific to clang compiler */
2842498b56bSopenharmony_ci#pragma clang diagnostic push
2852498b56bSopenharmony_ci#pragma clang diagnostic ignored "-Wformat-nonliteral"
2862498b56bSopenharmony_ci#elif __GNUC__
2872498b56bSopenharmony_ci/* code for GNU C compiler */
2882498b56bSopenharmony_ci#pragma GCC diagnostic push
2892498b56bSopenharmony_ci#pragma GCC diagnostic ignored "-Wformat-nonliteral"
2902498b56bSopenharmony_ci#endif
2912498b56bSopenharmony_ci    vsnprintfp_s(logBuf, MAX_LOG_LEN - traceBufLen, MAX_LOG_LEN - traceBufLen - 1, priv, fmt, ap);
2922498b56bSopenharmony_ci    LogCallback logCallbackFunc = g_logCallback;
2932498b56bSopenharmony_ci    if (logCallbackFunc != nullptr) {
2942498b56bSopenharmony_ci        logCallbackFunc(type, level, domain, tag, logBuf);
2952498b56bSopenharmony_ci    }
2962498b56bSopenharmony_ci#ifdef __clang__
2972498b56bSopenharmony_ci#pragma clang diagnostic pop
2982498b56bSopenharmony_ci#elif __GNUC__
2992498b56bSopenharmony_ci#pragma GCC diagnostic pop
3002498b56bSopenharmony_ci#endif
3012498b56bSopenharmony_ci
3022498b56bSopenharmony_ci    /* fill header info */
3032498b56bSopenharmony_ci    auto tagLen = strnlen(tag, MAX_TAG_LEN - 1);
3042498b56bSopenharmony_ci    auto logLen = strnlen(buf, MAX_LOG_LEN - 1);
3052498b56bSopenharmony_ci    header.type = type;
3062498b56bSopenharmony_ci    header.level = level;
3072498b56bSopenharmony_ci#ifndef __RECV_MSG_WITH_UCRED_
3082498b56bSopenharmony_ci#if defined(is_ohos) && is_ohos
3092498b56bSopenharmony_ci    header.pid = static_cast<uint32_t>(getprocpid());
3102498b56bSopenharmony_ci#elif not defined(__WINDOWS__)
3112498b56bSopenharmony_ci    header.pid = getpid();
3122498b56bSopenharmony_ci#else
3132498b56bSopenharmony_ci    header.pid = static_cast<uint32_t>(GetCurrentProcessId());
3142498b56bSopenharmony_ci#endif
3152498b56bSopenharmony_ci#endif
3162498b56bSopenharmony_ci#ifdef __WINDOWS__
3172498b56bSopenharmony_ci    header.tid = static_cast<uint32_t>(GetCurrentThreadId());
3182498b56bSopenharmony_ci#elif defined(__MAC__)
3192498b56bSopenharmony_ci    uint64_t tid;
3202498b56bSopenharmony_ci    pthread_threadid_np(NULL, &tid);
3212498b56bSopenharmony_ci    header.tid = static_cast<uint32_t>(tid);
3222498b56bSopenharmony_ci#elif defined(__OHOS__)
3232498b56bSopenharmony_ci    header.tid = static_cast<uint32_t>(getproctid());
3242498b56bSopenharmony_ci#else
3252498b56bSopenharmony_ci    header.tid = static_cast<uint32_t>(syscall(SYS_gettid));
3262498b56bSopenharmony_ci#endif
3272498b56bSopenharmony_ci    header.domain = domain;
3282498b56bSopenharmony_ci
3292498b56bSopenharmony_ci    if (level == LOG_FATAL) {
3302498b56bSopenharmony_ci        static std::mutex fatalMessageBufMutex;
3312498b56bSopenharmony_ci        std::lock_guard<std::mutex> lock(fatalMessageBufMutex);
3322498b56bSopenharmony_ci        (void)memcpy_s(g_hiLogLastFatalMessage, sizeof(g_hiLogLastFatalMessage), buf, sizeof(buf));
3332498b56bSopenharmony_ci    }
3342498b56bSopenharmony_ci
3352498b56bSopenharmony_ci#if not (defined( __WINDOWS__ ) || defined( __MAC__ ) || defined( __LINUX__ ))
3362498b56bSopenharmony_ci    /* flow control */
3372498b56bSopenharmony_ci    if (!debug && IsNeedProcFlowCtr(type)) {
3382498b56bSopenharmony_ci        ret = HiLogFlowCtrlProcess(tagLen + logLen - traceBufLen, ts_mono);
3392498b56bSopenharmony_ci        if (ret < 0) {
3402498b56bSopenharmony_ci            return ret;
3412498b56bSopenharmony_ci        } else if (ret > 0) {
3422498b56bSopenharmony_ci            static const char P_LIMIT_TAG[] = "LOGLIMIT";
3432498b56bSopenharmony_ci            uint16_t level = header.level;
3442498b56bSopenharmony_ci            header.level = LOG_WARN;
3452498b56bSopenharmony_ci            char dropLogBuf[MAX_LOG_LEN] = {0};
3462498b56bSopenharmony_ci            if (snprintf_s(dropLogBuf, MAX_LOG_LEN, MAX_LOG_LEN - 1,
3472498b56bSopenharmony_ci                "==LOGS OVER PROC QUOTA, %d DROPPED==", ret) > 0) {
3482498b56bSopenharmony_ci                HilogWriteLogMessage(&header, P_LIMIT_TAG, strlen(P_LIMIT_TAG) + 1, dropLogBuf,
3492498b56bSopenharmony_ci                    strnlen(dropLogBuf, MAX_LOG_LEN - 1) + 1);
3502498b56bSopenharmony_ci            }
3512498b56bSopenharmony_ci            header.level = level;
3522498b56bSopenharmony_ci        }
3532498b56bSopenharmony_ci    }
3542498b56bSopenharmony_ci    return HilogWriteLogMessage(&header, tag, tagLen + 1, buf, logLen + 1);
3552498b56bSopenharmony_ci#else
3562498b56bSopenharmony_ci    return PrintLog(header, tag, tagLen + 1, buf, logLen + 1);
3572498b56bSopenharmony_ci#endif
3582498b56bSopenharmony_ci}
3592498b56bSopenharmony_ci
3602498b56bSopenharmony_ciint HiLogPrint(LogType type, LogLevel level, unsigned int domain, const char *tag, const char *fmt, ...)
3612498b56bSopenharmony_ci{
3622498b56bSopenharmony_ci    int ret;
3632498b56bSopenharmony_ci    va_list ap;
3642498b56bSopenharmony_ci    va_start(ap, fmt);
3652498b56bSopenharmony_ci    ret = HiLogPrintArgs(type, level, domain, tag, fmt, ap);
3662498b56bSopenharmony_ci    va_end(ap);
3672498b56bSopenharmony_ci    return ret;
3682498b56bSopenharmony_ci}
3692498b56bSopenharmony_ci
3702498b56bSopenharmony_cibool HiLogIsLoggable(unsigned int domain, const char *tag, LogLevel level)
3712498b56bSopenharmony_ci{
3722498b56bSopenharmony_ci    if ((level <= LOG_LEVEL_MIN) || (level >= LOG_LEVEL_MAX) || (tag == nullptr) || (domain >= DOMAIN_OS_MAX)) {
3732498b56bSopenharmony_ci        return false;
3742498b56bSopenharmony_ci    }
3752498b56bSopenharmony_ci    if (level < GetFinalLevel(domain, tag)) {
3762498b56bSopenharmony_ci        return false;
3772498b56bSopenharmony_ci    }
3782498b56bSopenharmony_ci    return true;
3792498b56bSopenharmony_ci}
380