• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <sys/time.h>
16 #include <iomanip>
17 #include <map>
18 #include <securec.h>
19 #include <hilog/log.h>
20 
21 #include "hilog_common.h"
22 #include "log_utils.h"
23 #include "log_print.h"
24 
25 namespace OHOS {
26 namespace HiviewDFX {
27 using namespace std;
28 
29 static constexpr int COLOR_BLUE = 75;
30 static constexpr int COLOR_DEFAULT = 231;
31 static constexpr int COLOR_GREEN = 40;
32 static constexpr int COLOR_ORANGE = 166;
33 static constexpr int COLOR_RED = 196;
34 static constexpr int COLOR_YELLOW = 226;
35 static constexpr int TM_YEAR_BASE = 1900;
36 static constexpr int DT_WIDTH = 2;
37 static constexpr long long NS2US = 1000LL;
38 static constexpr long long NS2MS = 1000000LL;
39 static constexpr int MONO_WIDTH = 8;
40 static constexpr int EPOCH_WIDTH = 10;
41 static constexpr int MSEC_WIDTH = 3;
42 static constexpr int USEC_WIDTH = 6;
43 static constexpr int NSEC_WIDTH = 9;
44 static constexpr int PID_WIDTH = 5;
45 static constexpr int DOMAIN_WIDTH = 5;
46 static constexpr int DOMAIN_SHORT_MASK = 0xFFFFF;
47 
GetColor(uint16_t level)48 static inline int GetColor(uint16_t level)
49 {
50     switch (LogLevel(level)) {
51         case LOG_DEBUG: return COLOR_BLUE;
52         case LOG_INFO: return COLOR_GREEN;
53         case LOG_WARN: return COLOR_ORANGE;
54         case LOG_ERROR: return COLOR_RED;
55         case LOG_FATAL: return COLOR_YELLOW;
56         default: return COLOR_DEFAULT;
57     }
58 }
59 
GetLogTypePrefix(uint16_t type)60 static inline const char* GetLogTypePrefix(uint16_t type)
61 {
62     switch (LogType(type)) {
63         case LOG_APP: return "A";
64         case LOG_INIT: return "I";
65         case LOG_CORE: return "C";
66         case LOG_KMSG: return "K";
67         case LOG_ONLY_PRERELEASE: return "P";
68         default: return " ";
69     }
70 }
71 
ShortDomain(uint32_t d)72 static inline uint32_t ShortDomain(uint32_t d)
73 {
74     return (d) & DOMAIN_SHORT_MASK;
75 }
76 
PrintLogPrefix(const LogContent & content,const LogFormat & format,std::ostream & out)77 static void PrintLogPrefix(const LogContent& content, const LogFormat& format, std::ostream& out)
78 {
79     // 1. print day & time
80     if (format.timeFormat == FormatTime::TIME) {
81         struct tm tl;
82         time_t time = content.tv_sec;
83 #if (defined( __WINDOWS__ ))
84         if (localtime_s(&tl, &time) != 0) {
85             return;
86         }
87 #else
88         if (localtime_r(&time, &tl) == nullptr) {
89             return;
90         }
91         if (format.zone) {
92             out << tl.tm_zone << " ";
93         }
94 #endif
95         if (format.year) {
96             out << (tl.tm_year + TM_YEAR_BASE) << "-";
97         }
98         out << setfill('0');
99         out << setw(DT_WIDTH) << (tl.tm_mon + 1) << "-" << setw(DT_WIDTH) << tl.tm_mday << " ";
100         out << setw(DT_WIDTH) << tl.tm_hour << ":" << setw(DT_WIDTH) << tl.tm_min << ":";
101         out << setw(DT_WIDTH) << tl.tm_sec;
102     } else if (format.timeFormat == FormatTime::MONOTONIC) {
103         out << setfill(' ');
104         out << setw(MONO_WIDTH) << content.mono_sec;
105     } else if (format.timeFormat == FormatTime::EPOCH) {
106         out << setfill(' ');
107         out << setw(EPOCH_WIDTH) << content.tv_sec;
108     } else {
109         out << "Invalid time format" << endl;
110         return;
111     }
112     // 1.1 print msec/usec/nsec
113     out << ".";
114     out << setfill('0');
115     if (format.timeAccuFormat == FormatTimeAccu::MSEC) {
116         out << setw(MSEC_WIDTH) << (content.tv_nsec / NS2MS);
117     } else if (format.timeAccuFormat == FormatTimeAccu::USEC) {
118         out << setw(USEC_WIDTH) << (content.tv_nsec / NS2US);
119     } else if (format.timeAccuFormat == FormatTimeAccu::NSEC) {
120         out << setw(NSEC_WIDTH) << content.tv_nsec;
121     } else {
122         out << "Invalid time accuracy format" << endl;
123         return;
124     }
125     // The kmsg logs are taken from /proc/kmsg, cannot obtain pid, tid or domain information
126     // The kmsg log printing format: 08-06 16:51:04.945 <6> [4294.967295] hungtask_base whitelist[0]-init-1
127     if (content.type != LOG_KMSG) {
128         out << setfill(' ');
129         // 2. print pid/tid
130         out << " " << setw(PID_WIDTH) << content.pid << " " << setw(PID_WIDTH) << content.tid;
131         // 3. print level
132         out << " " << LogLevel2ShortStr(content.level) << " ";
133         // 4. print log type
134         out << GetLogTypePrefix(content.type);
135         // 5. print domain
136         out << setfill('0');
137         out << hex << setw(DOMAIN_WIDTH) << ShortDomain(content.domain) << dec;
138         // 5. print tag & log
139         out << "/" << content.tag << ": ";
140     } else {
141         out << " " << content.tag << " ";
142     }
143 }
144 
LogPrintWithFormat(const LogContent & content,const LogFormat & format,std::ostream & out)145 void LogPrintWithFormat(const LogContent& content, const LogFormat& format, std::ostream& out)
146 {
147     // set colorful log
148     if (format.colorful) {
149         out << "\x1B[38;5;" << GetColor(content.level) << "m";
150     }
151 
152     const char *pHead = content.log;
153     const char *pScan = content.log;
154     // split the log content by '\n', and add log prefix(datetime, pid, tid....) to each new line
155     while (*pScan != '\0') {
156         if (*pScan == '\n') {
157             char tmp[MAX_LOG_LEN];
158             int len = static_cast<int>(pScan - pHead);
159             errno_t ret = memcpy_s(tmp, MAX_LOG_LEN - 1, pHead, len);
160             if (ret != EOK) {
161                 break;
162             }
163             tmp[(MAX_LOG_LEN - 1) > len ? len : (MAX_LOG_LEN -1)] = '\0';
164             if (tmp[0] != '\0') {
165                 PrintLogPrefix(content, format, out);
166                 out << tmp << endl;
167             }
168             pHead = pScan + 1;
169         }
170         pScan++;
171     }
172     if (pHead[0] != '\0') {
173         PrintLogPrefix(content, format, out);
174         out << pHead;
175     }
176 
177     // restore color
178     if (format.colorful) {
179         out << "\x1B[0m";
180     }
181     if (pHead[0] != '\0') {
182         out << endl;
183     }
184     return;
185 }
186 } // namespace HiviewDFX
187 } // namespace OHOS