12498b56bSopenharmony_ci/* 22498b56bSopenharmony_ci * Copyright (c) 2022 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 <sys/time.h> 162498b56bSopenharmony_ci#include <iomanip> 172498b56bSopenharmony_ci#include <map> 182498b56bSopenharmony_ci#include <securec.h> 192498b56bSopenharmony_ci#include <hilog/log.h> 202498b56bSopenharmony_ci 212498b56bSopenharmony_ci#include "hilog_common.h" 222498b56bSopenharmony_ci#include "log_utils.h" 232498b56bSopenharmony_ci#include "log_print.h" 242498b56bSopenharmony_ci 252498b56bSopenharmony_cinamespace OHOS { 262498b56bSopenharmony_cinamespace HiviewDFX { 272498b56bSopenharmony_ciusing namespace std; 282498b56bSopenharmony_ci 292498b56bSopenharmony_cistatic constexpr int COLOR_BLUE = 75; 302498b56bSopenharmony_cistatic constexpr int COLOR_DEFAULT = 231; 312498b56bSopenharmony_cistatic constexpr int COLOR_GREEN = 40; 322498b56bSopenharmony_cistatic constexpr int COLOR_ORANGE = 166; 332498b56bSopenharmony_cistatic constexpr int COLOR_RED = 196; 342498b56bSopenharmony_cistatic constexpr int COLOR_YELLOW = 226; 352498b56bSopenharmony_cistatic constexpr int TM_YEAR_BASE = 1900; 362498b56bSopenharmony_cistatic constexpr int DT_WIDTH = 2; 372498b56bSopenharmony_cistatic constexpr long long NS2US = 1000LL; 382498b56bSopenharmony_cistatic constexpr long long NS2MS = 1000000LL; 392498b56bSopenharmony_cistatic constexpr int MONO_WIDTH = 8; 402498b56bSopenharmony_cistatic constexpr int EPOCH_WIDTH = 10; 412498b56bSopenharmony_cistatic constexpr int MSEC_WIDTH = 3; 422498b56bSopenharmony_cistatic constexpr int USEC_WIDTH = 6; 432498b56bSopenharmony_cistatic constexpr int NSEC_WIDTH = 9; 442498b56bSopenharmony_cistatic constexpr int PID_WIDTH = 5; 452498b56bSopenharmony_cistatic constexpr int DOMAIN_WIDTH = 5; 462498b56bSopenharmony_cistatic constexpr int DOMAIN_SHORT_MASK = 0xFFFFF; 472498b56bSopenharmony_cistatic constexpr int PREFIX_LEN = 42; 482498b56bSopenharmony_ci 492498b56bSopenharmony_cistatic inline int GetColor(uint16_t level) 502498b56bSopenharmony_ci{ 512498b56bSopenharmony_ci switch (LogLevel(level)) { 522498b56bSopenharmony_ci case LOG_DEBUG: return COLOR_BLUE; 532498b56bSopenharmony_ci case LOG_INFO: return COLOR_GREEN; 542498b56bSopenharmony_ci case LOG_WARN: return COLOR_ORANGE; 552498b56bSopenharmony_ci case LOG_ERROR: return COLOR_RED; 562498b56bSopenharmony_ci case LOG_FATAL: return COLOR_YELLOW; 572498b56bSopenharmony_ci default: return COLOR_DEFAULT; 582498b56bSopenharmony_ci } 592498b56bSopenharmony_ci} 602498b56bSopenharmony_ci 612498b56bSopenharmony_cistatic inline const char* GetLogTypePrefix(uint16_t type) 622498b56bSopenharmony_ci{ 632498b56bSopenharmony_ci switch (LogType(type)) { 642498b56bSopenharmony_ci case LOG_APP: return "A"; 652498b56bSopenharmony_ci case LOG_INIT: return "I"; 662498b56bSopenharmony_ci case LOG_CORE: return "C"; 672498b56bSopenharmony_ci case LOG_KMSG: return "K"; 682498b56bSopenharmony_ci case LOG_ONLY_PRERELEASE: return "P"; 692498b56bSopenharmony_ci default: return " "; 702498b56bSopenharmony_ci } 712498b56bSopenharmony_ci} 722498b56bSopenharmony_ci 732498b56bSopenharmony_cistatic inline uint32_t ShortDomain(uint32_t d) 742498b56bSopenharmony_ci{ 752498b56bSopenharmony_ci return (d) & DOMAIN_SHORT_MASK; 762498b56bSopenharmony_ci} 772498b56bSopenharmony_ci 782498b56bSopenharmony_cistatic void PrintLogPrefix(const LogContent& content, const LogFormat& format, std::ostream& out) 792498b56bSopenharmony_ci{ 802498b56bSopenharmony_ci // 1. print day & time 812498b56bSopenharmony_ci if (format.timeFormat == FormatTime::TIME) { 822498b56bSopenharmony_ci struct tm tl; 832498b56bSopenharmony_ci time_t time = content.tv_sec; 842498b56bSopenharmony_ci#if (defined( __WINDOWS__ )) 852498b56bSopenharmony_ci if (localtime_s(&tl, &time) != 0) { 862498b56bSopenharmony_ci return; 872498b56bSopenharmony_ci } 882498b56bSopenharmony_ci#else 892498b56bSopenharmony_ci if (localtime_r(&time, &tl) == nullptr) { 902498b56bSopenharmony_ci return; 912498b56bSopenharmony_ci } 922498b56bSopenharmony_ci if (format.zone) { 932498b56bSopenharmony_ci out << tl.tm_zone << " "; 942498b56bSopenharmony_ci } 952498b56bSopenharmony_ci#endif 962498b56bSopenharmony_ci if (format.year) { 972498b56bSopenharmony_ci out << (tl.tm_year + TM_YEAR_BASE) << "-"; 982498b56bSopenharmony_ci } 992498b56bSopenharmony_ci out << setfill('0'); 1002498b56bSopenharmony_ci out << setw(DT_WIDTH) << (tl.tm_mon + 1) << "-" << setw(DT_WIDTH) << tl.tm_mday << " "; 1012498b56bSopenharmony_ci out << setw(DT_WIDTH) << tl.tm_hour << ":" << setw(DT_WIDTH) << tl.tm_min << ":"; 1022498b56bSopenharmony_ci out << setw(DT_WIDTH) << tl.tm_sec; 1032498b56bSopenharmony_ci } else if (format.timeFormat == FormatTime::MONOTONIC) { 1042498b56bSopenharmony_ci out << setfill(' '); 1052498b56bSopenharmony_ci out << setw(MONO_WIDTH) << content.mono_sec; 1062498b56bSopenharmony_ci } else if (format.timeFormat == FormatTime::EPOCH) { 1072498b56bSopenharmony_ci out << setfill(' '); 1082498b56bSopenharmony_ci out << setw(EPOCH_WIDTH) << content.tv_sec; 1092498b56bSopenharmony_ci } else { 1102498b56bSopenharmony_ci out << "Invalid time format" << endl; 1112498b56bSopenharmony_ci return; 1122498b56bSopenharmony_ci } 1132498b56bSopenharmony_ci // 1.1 print msec/usec/nsec 1142498b56bSopenharmony_ci out << "."; 1152498b56bSopenharmony_ci out << setfill('0'); 1162498b56bSopenharmony_ci if (format.timeAccuFormat == FormatTimeAccu::MSEC) { 1172498b56bSopenharmony_ci out << setw(MSEC_WIDTH) << (content.tv_nsec / NS2MS); 1182498b56bSopenharmony_ci } else if (format.timeAccuFormat == FormatTimeAccu::USEC) { 1192498b56bSopenharmony_ci out << setw(USEC_WIDTH) << (content.tv_nsec / NS2US); 1202498b56bSopenharmony_ci } else if (format.timeAccuFormat == FormatTimeAccu::NSEC) { 1212498b56bSopenharmony_ci out << setw(NSEC_WIDTH) << content.tv_nsec; 1222498b56bSopenharmony_ci } else { 1232498b56bSopenharmony_ci out << "Invalid time accuracy format" << endl; 1242498b56bSopenharmony_ci return; 1252498b56bSopenharmony_ci } 1262498b56bSopenharmony_ci // The kmsg logs are taken from /proc/kmsg, cannot obtain pid, tid or domain information 1272498b56bSopenharmony_ci // The kmsg log printing format: 08-06 16:51:04.945 <6> [4294.967295] hungtask_base whitelist[0]-init-1 1282498b56bSopenharmony_ci if (content.type != LOG_KMSG) { 1292498b56bSopenharmony_ci out << setfill(' '); 1302498b56bSopenharmony_ci // 2. print pid/tid 1312498b56bSopenharmony_ci out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid; 1322498b56bSopenharmony_ci // 3. print level 1332498b56bSopenharmony_ci out << " " << LogLevel2ShortStr(content.level) << " "; 1342498b56bSopenharmony_ci // 4. print log type 1352498b56bSopenharmony_ci out << GetLogTypePrefix(content.type); 1362498b56bSopenharmony_ci // 5. print domain 1372498b56bSopenharmony_ci out << setfill('0'); 1382498b56bSopenharmony_ci out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec; 1392498b56bSopenharmony_ci // 5. print tag & log 1402498b56bSopenharmony_ci out << "/" << content.tag << ": "; 1412498b56bSopenharmony_ci } else { 1422498b56bSopenharmony_ci out << " " << content.tag << " "; 1432498b56bSopenharmony_ci } 1442498b56bSopenharmony_ci} 1452498b56bSopenharmony_ci 1462498b56bSopenharmony_cistatic void AdaptWrap(const LogContent& content, const LogFormat& format, std::ostream& out) 1472498b56bSopenharmony_ci{ 1482498b56bSopenharmony_ci if (format.wrap) { 1492498b56bSopenharmony_ci out << setfill(' '); 1502498b56bSopenharmony_ci out << std::setw(PREFIX_LEN + StringToWstring(content.tag).length()) << " "; 1512498b56bSopenharmony_ci } else { 1522498b56bSopenharmony_ci PrintLogPrefix(content, format, out); 1532498b56bSopenharmony_ci } 1542498b56bSopenharmony_ci} 1552498b56bSopenharmony_ci 1562498b56bSopenharmony_civoid LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out) 1572498b56bSopenharmony_ci{ 1582498b56bSopenharmony_ci // set colorful log 1592498b56bSopenharmony_ci if (format.colorful) { 1602498b56bSopenharmony_ci out << "\x1B[38;5;" << GetColor(content.level) << "m"; 1612498b56bSopenharmony_ci } 1622498b56bSopenharmony_ci 1632498b56bSopenharmony_ci const char *pHead = content.log; 1642498b56bSopenharmony_ci const char *pScan = content.log; 1652498b56bSopenharmony_ci // not print prefix if log is empty string or start with \n 1662498b56bSopenharmony_ci if (*pScan != '\0' && *pScan != '\n') { 1672498b56bSopenharmony_ci PrintLogPrefix(content, format, out); 1682498b56bSopenharmony_ci } 1692498b56bSopenharmony_ci // split the log content by '\n', and add log prefix(datetime, pid, tid....) to each new line 1702498b56bSopenharmony_ci while (*pScan != '\0') { 1712498b56bSopenharmony_ci if (*pScan == '\n') { 1722498b56bSopenharmony_ci char tmp[MAX_LOG_LEN]; 1732498b56bSopenharmony_ci int len = static_cast<int>(pScan - pHead); 1742498b56bSopenharmony_ci errno_t ret = memcpy_s(tmp, MAX_LOG_LEN - 1, pHead, len); 1752498b56bSopenharmony_ci if (ret != EOK) { 1762498b56bSopenharmony_ci break; 1772498b56bSopenharmony_ci } 1782498b56bSopenharmony_ci tmp[(MAX_LOG_LEN - 1) > len ? len : (MAX_LOG_LEN -1)] = '\0'; 1792498b56bSopenharmony_ci if (tmp[0] != '\0') { 1802498b56bSopenharmony_ci out << tmp << endl; 1812498b56bSopenharmony_ci } 1822498b56bSopenharmony_ci pHead = pScan + 1; 1832498b56bSopenharmony_ci if (pHead[0] != '\0' && pHead[0] != '\n') { 1842498b56bSopenharmony_ci AdaptWrap(content, format, out); 1852498b56bSopenharmony_ci } 1862498b56bSopenharmony_ci } 1872498b56bSopenharmony_ci pScan++; 1882498b56bSopenharmony_ci } 1892498b56bSopenharmony_ci if (pHead[0] != '\0') { 1902498b56bSopenharmony_ci out << pHead; 1912498b56bSopenharmony_ci } 1922498b56bSopenharmony_ci 1932498b56bSopenharmony_ci // restore color 1942498b56bSopenharmony_ci if (format.colorful) { 1952498b56bSopenharmony_ci out << "\x1B[0m"; 1962498b56bSopenharmony_ci } 1972498b56bSopenharmony_ci if (pHead[0] != '\0') { 1982498b56bSopenharmony_ci out << endl; 1992498b56bSopenharmony_ci } 2002498b56bSopenharmony_ci return; 2012498b56bSopenharmony_ci} 2022498b56bSopenharmony_ci} // namespace HiviewDFX 2032498b56bSopenharmony_ci} // namespace OHOS