1 /*
2 * Copyright (c) 2025 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 "event_logger_util.h"
16
17 #include <vector>
18
19 #include "hiview_logger.h"
20 #include "file_util.h"
21 #include "time_util.h"
22 #include "string_util.h"
23 #include "log_file.h"
24
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace {
28 static const int LOG_MAP_SIZE = 2;
29 static const int INDEX_OF_TYPE = 0;
30 static const int INDEX_OF_MOUDLE = 1;
31 static const int INDEX_OF_UID = 2;
32 static const int INDEX_OF_TIME = 3;
33 static const uint32_t INDEX_OF_TIMESTAMP = 4;
34 static const uint32_t FREEZE_VECTOR_SIZE = 5;
35 static constexpr time_t FORTYEIGHT_HOURS = 48 * 60 * 60;
36 static const size_t FREEZE_FILE_NAME_SIZE = 6;
37 static const int FREEZE_UID_INDEX = 4;
38 static constexpr const char* const APPFREEZE = "appfreeze";
39 static constexpr const char* const SYSFREEZE = "sysfreeze";
40 static constexpr const char* const SYSWARNING = "syswarning";
41 static constexpr const char* const EVENT_PID = "PID";
42 static constexpr const char* const EVENT_REASON = "STRINGID";
43 static constexpr const char* const EVENT_TIMESTAMP = "TIMESTAMP";
44 static constexpr const char* const FREEZE_PREFIX[] = {
45 APPFREEZE, SYSFREEZE, SYSWARNING
46 };
47 static constexpr const char* const FREEZE_LOG_SEQUENCE[] = {
48 EVENT_PID, EVENT_REASON
49 };
50 static constexpr const char* const FREEZE_DETECTOR_PATH = "/data/log/faultlog/freeze/";
51 } // namespace
52
53 DEFINE_LOG_LABEL(0xD002D01, "EventLogger-EventLoggerUtil");
54
GetFileLastAccessTimeStamp(const std::string & fileName)55 time_t GetFileLastAccessTimeStamp(const std::string& fileName)
56 {
57 struct stat fileInfo;
58 if (stat(fileName.c_str(), &fileInfo) != 0) {
59 HIVIEW_LOGI("get log info failed, errno:%{public}d, fileName:%{public}s",
60 errno, fileName.c_str());
61 return 0;
62 }
63 return fileInfo.st_atime;
64 }
65
ExtractInfoFromFileName(const std::string & fileName)66 FaultLogInfoInner ExtractInfoFromFileName(const std::string& fileName)
67 {
68 FaultLogInfoInner info;
69 std::vector<std::string> splitStr;
70
71 StringUtil::SplitStr(fileName, "-", splitStr);
72 if (splitStr.size() == FREEZE_VECTOR_SIZE) {
73 std::string type = splitStr[INDEX_OF_TYPE];
74 info.faultLogType = (type == APPFREEZE) ? FaultLogType::APP_FREEZE : ((type == SYSFREEZE) ?
75 FaultLogType::SYS_FREEZE : FaultLogType::SYS_WARNING);
76 info.summary = type + ": ";
77 info.module = splitStr[INDEX_OF_MOUDLE];
78 StringUtil::ConvertStringTo<uint32_t>(splitStr[INDEX_OF_UID], info.id);
79 info.sectionMaps[EVENT_TIMESTAMP] = splitStr[INDEX_OF_TIME];
80 std::string timeStamp = splitStr[INDEX_OF_TIMESTAMP].substr(0, splitStr[INDEX_OF_TIMESTAMP].find(".log"));
81 StringUtil::ConvertStringTo<uint64_t>(timeStamp, info.time);
82 }
83 return info;
84 }
85
ParseFaultLogInfoFromFile(const std::string & path,const std::string & fileName)86 FaultLogInfoInner ParseFaultLogInfoFromFile(const std::string &path, const std::string &fileName)
87 {
88 FaultLogInfoInner info = ExtractInfoFromFileName(fileName);
89 info.logPath = path;
90 std::ifstream logFile(path);
91 std::string line;
92 while (std::getline(logFile, line)) {
93 if (!logFile.good() || info.sectionMaps.size() == LOG_MAP_SIZE) {
94 break;
95 }
96 if (line.empty()) {
97 continue;
98 }
99 for (auto &item : FREEZE_LOG_SEQUENCE) {
100 std::string sectionHead = std::string(item);
101 if (line.find(sectionHead) == std::string::npos) {
102 continue;
103 }
104 info.sectionMaps[sectionHead] = line.substr(line.find_first_of(":") + 1);
105 }
106 }
107
108 info.reason = info.sectionMaps[EVENT_REASON];
109 int32_t pid = 0;
110 StringUtil::ConvertStringTo<int32_t>(info.sectionMaps[EVENT_PID], pid);
111 info.pid = pid;
112 info.summary += info.module + " " + info.reason + " at " + info.sectionMaps[EVENT_TIMESTAMP];
113 HIVIEW_LOGI("log info, pid:%{public}u, id:%{public}u, module:%{public}s, time:%{public}" PRIu64
114 ", summary:%{public}s", info.pid, info.id, info.module.c_str(), info.time, info.summary.c_str());
115 return info;
116 }
117
StartBootScan()118 void StartBootScan()
119 {
120 std::vector<std::string> files;
121 time_t now = time(nullptr);
122 FileUtil::GetDirFiles(FREEZE_DETECTOR_PATH, files);
123 for (const auto& file : files) {
124 // if file type is not freeze, skip!
125 std::string fileName = FileUtil::ExtractFileName(file);
126 std::string type = fileName.substr(0, fileName.find("-"));
127 if (std::find(std::begin(FREEZE_PREFIX), std::end(FREEZE_PREFIX), type) == std::end(FREEZE_PREFIX)) {
128 HIVIEW_LOGI("Skip this file:%{public}s type:%{public}s that the type is not appfreeze sysfreeze "
129 "syswarning.", file.c_str(), type.c_str());
130 continue;
131 }
132 time_t lastAccessTime = GetFileLastAccessTimeStamp(file);
133 if (now - lastAccessTime > FORTYEIGHT_HOURS) {
134 HIVIEW_LOGI("Skip this file(%{public}s) that were created 48 hours ago.", file.c_str());
135 continue;
136 }
137 auto info = ParseFaultLogInfoFromFile(file, fileName);
138 HIVIEW_LOGI("Boot scan file: %{public}s.", file.c_str());
139 AddFaultLog(info);
140 }
141 }
142
GetUidFromFileName(const std::string & fileName)143 int32_t GetUidFromFileName(const std::string& fileName)
144 {
145 std::vector<std::string> splitStr;
146 StringUtil::SplitStr(fileName, "-", splitStr);
147 int32_t id = 0;
148 if (splitStr.size() == FREEZE_FILE_NAME_SIZE) {
149 StringUtil::ConvertStringTo<int32_t>(splitStr[FREEZE_UID_INDEX], id);
150 }
151 return id;
152 }
153
CreateLogFileFilter(int32_t id,const std::string & filePrefix)154 LogStoreEx::LogFileFilter CreateLogFileFilter(int32_t id, const std::string& filePrefix)
155 {
156 LogStoreEx::LogFileFilter filter = [id, filePrefix](const LogFile &file) {
157 if (file.name_.find(filePrefix) == std::string::npos) {
158 return false;
159 }
160 int fileId = GetUidFromFileName(file.name_);
161 if (fileId != id) {
162 return false;
163 }
164
165 return true;
166 };
167 return filter;
168 }
169 } // namespace HiviewDFX
170 } // namespace OHOS
171