1 /*
2 * Copyright (c) 2021 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
16 #include "kmsg_parser.h"
17 #include "hilog/log.h"
18
19 #include <cstdlib>
20 #include <cinttypes>
21 #include <iostream>
22 #include <string>
23 #include <thread>
24 #include <chrono>
25 #include <fstream>
26 #include <regex>
27 #include <sys/time.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #include <string_view>
32
33 namespace OHOS {
34 namespace HiviewDFX {
35 using namespace std::chrono;
36 using namespace std::literals;
37
38 constexpr int DEC = 10;
39 constexpr int USEC_LEN = 6;
40
41 // Avoid name collision between sys/syslog.h and our log_c.h
42 #undef LOG_FATAL
43 #undef LOG_ERR
44 #undef LOG_WARN
45 #undef LOG_INFO
46 #undef LOG_DEBUG
47
48 using Priority = enum {
49 PV0 = 0,
50 PV1,
51 PV2,
52 PV3,
53 PV4,
54 PV5,
55 PV6
56 };
57
58 // Log levels are different in syslog.h and hilog log_c.h
KmsgLevelMap(uint16_t prio)59 static uint16_t KmsgLevelMap(uint16_t prio)
60 {
61 uint16_t level;
62 switch (prio) {
63 case Priority::PV0:
64 case Priority::PV1:
65 case Priority::PV2:
66 level = LOG_FATAL;
67 break;
68 case Priority::PV3:
69 level = LOG_ERROR;
70 break;
71 case Priority::PV4:
72 case Priority::PV5:
73 level = LOG_WARN;
74 break;
75 case Priority::PV6:
76 level = LOG_INFO;
77 break;
78 default:
79 level = LOG_DEBUG;
80 break;
81 }
82 return level;
83 }
84
85 /*
86 *Extract log level and usec time from the raw kernel logs
87 *raw log format: 6,5972,232898993226,-;hungtask_base whitelist[1]-appspawn-255
88 *6 -> logLevel; 232898993226 -> usec
89 */
ParseHeader(std::string & str,uint8_t & level,std::string & tag)90 static void ParseHeader(std::string& str, uint8_t& level, std::string& tag)
91 {
92 std::string levelStr;
93 std::string usecStr;
94 std::size_t pos = str.find(',');
95 if (pos != std::string::npos) {
96 levelStr = str.substr(0, pos);
97 level = strtoul(levelStr.c_str(), nullptr, DEC);
98 } else {
99 return;
100 }
101 pos = str.find(',', pos + 1);
102 if (pos == std::string::npos) {
103 return;
104 }
105 size_t usecBeginPos = pos + 1;
106 pos = str.find(',', usecBeginPos);
107 if (pos != std::string::npos) {
108 usecStr = str.substr(usecBeginPos, pos - usecBeginPos);
109 str.erase(0, pos + 1);
110 }
111 if (usecStr.length() < (USEC_LEN + 1)) {
112 usecStr = std::string(USEC_LEN + 1 - usecStr.length(), '0') + usecStr;
113 }
114 usecStr.insert(usecStr.length() - USEC_LEN, ".");
115 tag = "<" + levelStr + ">" + " [" + usecStr + "]";
116 }
117
ParseKmsg(const std::vector<char> & kmsgBuffer)118 std::optional<HilogMsgWrapper> KmsgParser::ParseKmsg(const std::vector<char>& kmsgBuffer)
119 {
120 std::string kmsgStr(kmsgBuffer.data());
121 std::string tagStr = "";
122 uint8_t mLevel = 0;
123 ParseHeader(kmsgStr, mLevel, tagStr);
124 size_t tagLen = tagStr.size();
125 // Now build HilogMsg and insert it into buffer
126 auto len = kmsgStr.size() + 1;
127 auto msgLen = sizeof(HilogMsg) + tagLen + len + 1;
128 HilogMsgWrapper msgWrap((std::vector<char>(msgLen, '\0')));
129 HilogMsg& msg = msgWrap.GetHilogMsg();
130 msg.len = msgLen;
131 msg.tag_len = tagLen + 1;
132 msg.type = LOG_KMSG;
133 msg.level = KmsgLevelMap(mLevel);
134 struct timespec ts = {0};
135 (void)clock_gettime(CLOCK_REALTIME, &ts);
136 msg.tv_sec = static_cast<uint32_t>(ts.tv_sec);
137 msg.tv_nsec = static_cast<uint32_t>(ts.tv_nsec);
138 if (strncpy_s(msg.tag, tagLen + 1, tagStr.c_str(), tagLen) != 0) {
139 return {};
140 }
141 if (strncpy_s(CONTENT_PTR((&msg)), MAX_LOG_LEN, kmsgStr.c_str(), len) != 0) {
142 return {};
143 }
144 return msgWrap;
145 }
146 } // namespace HiviewDFX
147 } // namespace OHOS
148