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 AddFaultLog(info);
113 return logPath;
114 }
115
DumpEventInfo(std::ostringstream & oss,const std::string & header,const WatchPoint & watchPoint) const116 void Vendor::DumpEventInfo(std::ostringstream& oss, const std::string& header, const WatchPoint& watchPoint) const
117 {
118 uint64_t timestamp = watchPoint.GetTimestamp() / TimeUtil::SEC_TO_MILLISEC;
119 oss << header << std::endl;
120 oss << FreezeCommon::EVENT_DOMAIN << FreezeCommon::COLON << watchPoint.GetDomain() << std::endl;
121 oss << FreezeCommon::EVENT_STRINGID << FreezeCommon::COLON << watchPoint.GetStringId() << std::endl;
122 oss << FreezeCommon::EVENT_TIMESTAMP << FreezeCommon::COLON <<
123 TimeUtil::TimestampFormatToDate(timestamp, "%Y/%m/%d-%H:%M:%S") <<
124 ":" << watchPoint.GetTimestamp() % TimeUtil::SEC_TO_MILLISEC << std::endl;
125 oss << FreezeCommon::EVENT_PID << FreezeCommon::COLON << watchPoint.GetPid() << std::endl;
126 oss << FreezeCommon::EVENT_UID << FreezeCommon::COLON << watchPoint.GetUid() << std::endl;
127 oss << FreezeCommon::EVENT_PACKAGE_NAME << FreezeCommon::COLON << watchPoint.GetPackageName() << std::endl;
128 oss << FreezeCommon::EVENT_PROCESS_NAME << FreezeCommon::COLON << watchPoint.GetProcessName() << std::endl;
129 oss << FreezeCommon::EVENT_MSG << FreezeCommon::COLON << watchPoint.GetMsg() << std::endl;
130 }
131
MergeEventLog(const WatchPoint & watchPoint,const std::vector<WatchPoint> & list,const std::vector<FreezeResult> & result) const132 std::string Vendor::MergeEventLog(
133 const WatchPoint &watchPoint, const std::vector<WatchPoint>& list,
134 const std::vector<FreezeResult>& result) const
135 {
136 if (freezeCommon_ == nullptr) {
137 return "";
138 }
139
140 std::string domain = watchPoint.GetDomain();
141 std::string stringId = watchPoint.GetStringId();
142 std::string timestamp = GetTimeString(watchPoint.GetTimestamp());
143 long uid = watchPoint.GetUid();
144 std::string packageName = StringUtil::TrimStr(watchPoint.GetPackageName());
145 std::string processName = StringUtil::TrimStr(watchPoint.GetProcessName());
146 std::string msg = watchPoint.GetMsg();
147
148 std::string type = freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())
149 ? APPFREEZE : SYSFREEZE;
150 if (type == SYSFREEZE) {
151 processName = stringId;
152 } else if (processName == "" && packageName != "") {
153 processName = packageName;
154 }
155 if (processName == "" && packageName == "") {
156 processName = stringId;
157 }
158
159 std::string retPath;
160 std::string logPath;
161 std::string logName;
162 if (freezeCommon_->IsApplicationEvent(watchPoint.GetDomain(), watchPoint.GetStringId())) {
163 retPath = FAULT_LOGGER_PATH + APPFREEZE + HYPHEN + processName
164 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
165 logPath = FREEZE_DETECTOR_PATH + APPFREEZE + HYPHEN + processName
166 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
167 logName = APPFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
168 } else {
169 retPath = FAULT_LOGGER_PATH + SYSFREEZE + HYPHEN + processName
170 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp;
171 logPath = FREEZE_DETECTOR_PATH + SYSFREEZE + HYPHEN + processName
172 + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
173 logName = SYSFREEZE + HYPHEN + processName + HYPHEN + std::to_string(uid) + HYPHEN + timestamp + POSTFIX;
174 }
175
176 if (FileUtil::FileExists(retPath)) {
177 HIVIEW_LOGW("filename: %{public}s is existed, direct use.", retPath.c_str());
178 return retPath;
179 }
180
181 std::ostringstream header;
182 DumpEventInfo(header, TRIGGER_HEADER, watchPoint);
183
184 HIVIEW_LOGI("merging list size %{public}zu", list.size());
185 std::ostringstream body;
186 for (auto node : list) {
187 std::string filePath = node.GetLogPath();
188 HIVIEW_LOGI("merging file:%{public}s.", filePath.c_str());
189
190 if (filePath == "nolog" || filePath == "" || FileUtil::FileExists(filePath) == false) {
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 std::ifstream ifs(filePath, std::ios::in);
198 if (!ifs.is_open()) {
199 HIVIEW_LOGE("cannot open log file for reading:%{public}s.", filePath.c_str());
200 DumpEventInfo(body, HEADER, node);
201 continue;
202 }
203
204 body << HEADER << std::endl;
205 if (node.GetDomain() == "RELIABILITY" && node.GetStringId() == "STACK") {
206 body << FreezeCommon::EVENT_DOMAIN << "=" << node.GetDomain() << std::endl;
207 body << FreezeCommon::EVENT_STRINGID << "=" << node.GetStringId() << std::endl;
208 body << FreezeCommon::EVENT_TIMESTAMP << "=" << node.GetTimestamp() << std::endl;
209 body << FreezeCommon::EVENT_PID << "=" << watchPoint.GetPid() << std::endl;
210 body << FreezeCommon::EVENT_UID << "=" << watchPoint.GetUid() << std::endl;
211 body << FreezeCommon::EVENT_PACKAGE_NAME << "=" << watchPoint.GetPackageName() << std::endl;
212 body << FreezeCommon::EVENT_PROCESS_NAME << "=" << watchPoint.GetProcessName() << std::endl;
213 body << FreezeCommon::EVENT_MSG << "=" << node.GetMsg() << std::endl;
214 body << std::endl;
215 }
216 body << ifs.rdbuf();
217 ifs.close();
218 }
219
220 int fd = logStore_->CreateLogFile(logName);
221 if (fd < 0) {
222 HIVIEW_LOGE("failed to create log file %{public}s.", logPath.c_str());
223 return "";
224 }
225
226 FileUtil::SaveStringToFd(fd, header.str());
227 FileUtil::SaveStringToFd(fd, body.str());
228 close(fd);
229 return SendFaultLog(watchPoint, logPath, logName);
230 }
231
Init()232 bool Vendor::Init()
233 {
234 if (freezeCommon_ == nullptr) {
235 return false;
236 }
237 logStore_ = std::make_unique<LogStoreEx>(FREEZE_DETECTOR_PATH, true);
238 logStore_->SetMaxSize(MAX_FOLDER_SIZE);
239 logStore_->SetMinKeepingFileNumber(MAX_FILE_NUM);
240 logStore_->Init();
241 return true;
242 }
243 } // namespace HiviewDFX
244 } // namespace OHOS
245