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