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 "vendor.h"
17
18 #include "faultlogger_client.h"
19 #include "file_util.h"
20 #include "logger.h"
21 #include "string_util.h"
22 #include "time_util.h"
23
24 namespace OHOS {
25 namespace HiviewDFX {
26 DEFINE_LOG_TAG("FreezeDetector");
ReduceRelevanceEvents(std::list<WatchPoint> & list,const FreezeResult & result) const27 bool Vendor::ReduceRelevanceEvents(std::list<WatchPoint>& list, const FreezeResult& result) const
28 {
29 HIVIEW_LOGI("before size=%{public}zu", list.size());
30 if (freezeCommon_ == nullptr) {
31 return false;
32 }
33 if (freezeCommon_->IsSystemResult(result) == false && freezeCommon_->IsApplicationResult(result) == false) {
34 list.clear();
35 return false;
36 }
37
38 // erase if not system event
39 if (freezeCommon_->IsSystemResult(result)) {
40 std::list<WatchPoint>::iterator watchPoint;
41 for (watchPoint = list.begin(); watchPoint != list.end();) {
42 if (freezeCommon_->IsSystemEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
43 watchPoint++;
44 } else {
45 watchPoint = list.erase(watchPoint);
46 }
47 }
48 }
49
50 // erase if not application event
51 if (freezeCommon_->IsApplicationResult(result)) {
52 std::list<WatchPoint>::iterator watchPoint;
53 for (watchPoint = list.begin(); watchPoint != list.end();) {
54 if (freezeCommon_->IsApplicationEvent(watchPoint->GetDomain(), watchPoint->GetStringId())) {
55 watchPoint++;
56 } else {
57 watchPoint = list.erase(watchPoint);
58 }
59 }
60 }
61
62 list.sort();
63 list.unique();
64 HIVIEW_LOGI("after size=%{public}zu", list.size());
65 return list.size() != 0;
66 }
67
GetTimeString(unsigned long long timestamp) const68 std::string Vendor::GetTimeString(unsigned long long timestamp) const
69 {
70 struct tm tm;
71 time_t ts;
72 ts = timestamp / FreezeCommon::MILLISECOND; // ms
73 localtime_r(&ts, &tm);
74 char buf[TIME_STRING_LEN] = {0};
75
76 strftime(buf, TIME_STRING_LEN - 1, "%Y%m%d%H%M%S", &tm);
77 return std::string(buf, strlen(buf));
78 }
79
SendFaultLog(const WatchPoint & watchPoint,const std::string & logPath,const std::string & logName) const80 std::string Vendor::SendFaultLog(const WatchPoint &watchPoint, const std::string& logPath,
81 const std::string& logName) const
82 {
83 if (freezeCommon_ == nullptr) {
84 return "";
85 }
86 std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
87 std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
88 std::string stringId = watchPoint.GetStringId();
89
90 std::string type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())
91 ? APPFREEZE : SYSFREEZE;
92 if (type == SYSFREEZE) {
93 processName = stringId;
94 } else if (processName == "" && packageName != "") {
95 processName = packageName;
96 }
97 if (processName == "" && packageName == "") {
98 processName = stringId;
99 }
100
101 FaultLogInfoInner info;
102 info.time = watchPoint.GetTimestamp();
103 info.id = watchPoint.GetUid();
104 info.pid = watchPoint.GetPid();
105 info.faultLogType = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())
106 ? FaultLogType::APP_FREEZE : FaultLogType::SYS_FREEZE;
107 info.module = processName;
108 info.reason = stringId;
109 info.summary = type + ": " + processName + " " + stringId
110 + " at " + GetTimeString(watchPoint.GetTimestamp()) + "\n";
111 info.logPath = logPath;
112 info.sectionMaps[FreezeCommon::HIREACE_TIME] = watchPoint.GetHitraceTime();
113 info.sectionMaps[FreezeCommon::SYSRQ_TIME] = watchPoint.GetSysrqTime();
114 AddFaultLog(info);
115 return logPath;
116 }
117
DumpEventInfo(std::ostringstream & oss,const std::string & header,const WatchPoint & watchPoint) const118 void Vendor::DumpEventInfo(std::ostringstream& oss, const std::string& header, const WatchPoint& watchPoint) const
119 {
120 uint64_t timestamp = watchPoint.GetTimestamp() / TimeUtil::SEC_TO_MILLISEC;
121 oss << header << std::endl;
122 oss << FreezeCommon::EVENT_DOMAIN << FreezeCommon::COLON << watchPoint.GetDomain() << std::endl;
123 oss << FreezeCommon::EVENT_STRINGID << FreezeCommon::COLON << watchPoint.GetStringId() << std::endl;
124 oss << FreezeCommon::EVENT_TIMESTAMP << FreezeCommon::COLON <<
125 TimeUtil::TimestampFormatToDate(timestamp, "%Y/%m/%d-%H:%M:%S") <<
126 ":" << watchPoint.GetTimestamp() % TimeUtil::SEC_TO_MILLISEC << std::endl;
127 oss << FreezeCommon::EVENT_PID << FreezeCommon::COLON << watchPoint.GetPid() << std::endl;
128 oss << FreezeCommon::EVENT_UID << FreezeCommon::COLON << watchPoint.GetUid() << std::endl;
129 oss << FreezeCommon::EVENT_PACKAGE_NAME << FreezeCommon::COLON << watchPoint.GetPackageName() << std::endl;
130 oss << FreezeCommon::EVENT_PROCESS_NAME << FreezeCommon::COLON << watchPoint.GetProcessName() << std::endl;
131 oss << FreezeCommon::EVENT_MSG << FreezeCommon::COLON << watchPoint.GetMsg() << std::endl;
132 }
133
MergeEventLog(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list,const std::vector<FreezeResult> & result) const134 std::string Vendor::MergeEventLog(
135 const WatchPoint &watchPoint, const std::vector<WatchPoint>& list,
136 const std::vector<FreezeResult>& result) const
137 {
138 if (freezeCommon_ == nullptr) {
139 return "";
140 }
141
142 std::string domain = watchPoint.GetDomain();
143 std::string stringId = watchPoint.GetStringId();
144 std::string timestamp = GetTimeString(watchPoint.GetTimestamp());
145 long uid = watchPoint.GetUid();
146 std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
147 std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
148 std::string msg = watchPoint.GetMsg();
149
150 std::string type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())
151 ? APPFREEZE : SYSFREEZE;
152 if (type == SYSFREEZE) {
153 processName = stringId;
154 } else if (processName == "" && packageName != "") {
155 processName = packageName;
156 }
157 if (processName == "" && packageName == "") {
158 processName = stringId;
159 }
160
161 std::string retPath;
162 std::string logPath;
163 std::string logName;
164 if (freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())) {
165 retPath = FAULT_LOGGER_PATH + APPFREEZE + HYPHEN + processName
166 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
167 logPath = FREEZE_DETECTOR_PATH + APPFREEZE + HYPHEN + processName
168 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
169 logName = APPFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
170 } else {
171 retPath = FAULT_LOGGER_PATH + SYSFREEZE + HYPHEN + processName
172 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
173 logPath = FREEZE_DETECTOR_PATH + SYSFREEZE + HYPHEN + processName
174 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
175 logName = SYSFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
176 }
177
178 if (FileUtil::FileExists(retPath)) {
179 HIVIEW_LOGW("filename: %{public}s is existed, direct use.", retPath.c_str());
180 return retPath;
181 }
182
183 std::ostringstream header;
184 DumpEventInfo(header, TRIGGER_HEADER, watchPoint);
185
186 HIVIEW_LOGI("merging list size %{public}zu", list.size());
187 std::ostringstream body;
188 for (auto node : list) {
189 std::string filePath = node.GetLogPath();
190 if (filePath == "nolog" || filePath == "") {
191 HIVIEW_LOGI("only header, no content:[%{public}s, %{public}s]",
192 node.GetDomain().c_str(), node.GetStringId().c_str());
193 DumpEventInfo(body, HEADER, node);
194 continue;
195 }
196
197 if (FileUtil::FileExists(filePath) == false) {
198 HIVIEW_LOGE("[%{public}s, %{public}s] File:%{public}s does not exist",
199 node.GetDomain().c_str(), node.GetStringId().c_str(), filePath.c_str());
200 return "";
201 }
202
203 HIVIEW_LOGI("merging file:%{public}s.", filePath.c_str());
204
205 std::ifstream ifs(filePath, std::ios::in);
206 if (!ifs.is_open()) {
207 HIVIEW_LOGE("cannot open log file for reading:%{public}s.", filePath.c_str());
208 DumpEventInfo(body, HEADER, node);
209 continue;
210 }
211
212 body << HEADER << std::endl;
213 if (node.GetDomain() == "RELIABILITY" && node.GetStringId() == "STACK") {
214 body << FreezeCommon::EVENT_DOMAIN << "=" << node.GetDomain() << std::endl;
215 body << FreezeCommon::EVENT_STRINGID << "=" << node.GetStringId() << std::endl;
216 body << FreezeCommon::EVENT_TIMESTAMP << "=" << node.GetTimestamp() << std::endl;
217 body << FreezeCommon::EVENT_PID << "=" << watchPoint.GetPid() << std::endl;
218 body << FreezeCommon::EVENT_UID << "=" << watchPoint.GetUid() << std::endl;
219 body << FreezeCommon::EVENT_PACKAGE_NAME << "=" << watchPoint.GetPackageName() << std::endl;
220 body << FreezeCommon::EVENT_PROCESS_NAME << "=" << watchPoint.GetProcessName() << std::endl;
221 body << FreezeCommon::EVENT_MSG << "=" << node.GetMsg() << std::endl;
222 body << std::endl;
223 }
224 body << ifs.rdbuf();
225 ifs.close();
226 }
227
228 int fd = logStore_->CreateLogFile(logName);
229 if (fd < 0) {
230 HIVIEW_LOGE("failed to create log file %{public}s.", logPath.c_str());
231 return "";
232 }
233
234 FileUtil::SaveStringToFd(fd, header.str());
235 FileUtil::SaveStringToFd(fd, body.str());
236 close(fd);
237 return SendFaultLog(watchPoint, logPath, logName);
238 }
239
Init()240 bool Vendor::Init()
241 {
242 if (freezeCommon_ == nullptr) {
243 return false;
244 }
245 logStore_ = std::make_unique<LogStoreEx>(FREEZE_DETECTOR_PATH, true);
246 logStore_->SetMaxSize(MAX_FOLDER_SIZE);
247 logStore_->SetMinKeepingFileNumber(MAX_FILE_NUM);
248 logStore_->Init();
249 return true;
250 }
251 } // namespace HiviewDFX
252 } // namespace OHOS
253