• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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