• 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 "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