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 #include "faultlog_database.h"
16
17 #include <algorithm>
18 #include <cinttypes>
19 #include <list>
20 #include <mutex>
21 #include <string>
22
23 #include "faultlog_info.h"
24 #include "faultlog_util.h"
25 #include "hisysevent.h"
26 #include "hiview_global.h"
27 #include "hiview_logger.h"
28 #include "log_analyzer.h"
29 #include "string_util.h"
30 #include "sys_event_dao.h"
31 #include "time_util.h"
32
33 #include "decoded/decoded_event.h"
34
35 using namespace std;
36 namespace OHOS {
37 namespace HiviewDFX {
38 DEFINE_LOG_LABEL(0xD002D11, "FaultLogDatabase");
39 namespace {
40 static const std::vector<std::string> QUERY_ITEMS = {
41 "time_", "name_", "uid_", "pid_", "MODULE", "REASON", "SUMMARY", "LOG_PATH", "FAULT_TYPE"
42 };
43 static const std::string LOG_PATH_BASE = "/data/log/faultlog/faultlogger/";
ParseFaultLogInfoFromJson(std::shared_ptr<EventRaw::RawData> rawData,FaultLogInfo & info)44 bool ParseFaultLogInfoFromJson(std::shared_ptr<EventRaw::RawData> rawData, FaultLogInfo& info)
45 {
46 if (rawData == nullptr) {
47 HIVIEW_LOGE("raw data of sys event is null.");
48 return false;
49 }
50 auto sysEvent = std::make_unique<SysEvent>("FaultLogDatabase", nullptr, rawData);
51 constexpr string::size_type FIRST_200_BYTES = 200;
52 HIVIEW_LOGI("parse FaultLogInfo from %{public}s.", sysEvent->AsJsonStr().substr(0, FIRST_200_BYTES).c_str());
53 constexpr int64_t DEFAULT_INT_VALUE = 0;
54 info.time = static_cast<int64_t>(std::atoll(sysEvent->GetEventValue("HAPPEN_TIME").c_str()));
55 if (info.time == DEFAULT_INT_VALUE) {
56 info.time = sysEvent->GetEventIntValue("HAPPEN_TIME") != DEFAULT_INT_VALUE?
57 sysEvent->GetEventIntValue("HAPPEN_TIME") : sysEvent->GetEventIntValue("time_");
58 }
59 info.pid = sysEvent->GetEventIntValue("PID") != DEFAULT_INT_VALUE ?
60 sysEvent->GetEventIntValue("PID") : sysEvent->GetEventIntValue("pid_");
61
62 info.id = sysEvent->GetEventIntValue("UID") != DEFAULT_INT_VALUE ?
63 sysEvent->GetEventIntValue("UID") : sysEvent->GetEventIntValue("uid_");
64 info.faultLogType = std::atoi(sysEvent->GetEventValue("FAULT_TYPE").c_str());
65 info.module = sysEvent->GetEventValue("MODULE");
66 info.reason = sysEvent->GetEventValue("REASON");
67 info.summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
68 info.logPath = LOG_PATH_BASE + GetFaultLogName(info);
69 return true;
70 }
71 }
72
FaultLogDatabase(const std::shared_ptr<EventLoop> & eventLoop)73 FaultLogDatabase::FaultLogDatabase(const std::shared_ptr<EventLoop>& eventLoop) : eventLoop_(eventLoop) {}
74
SaveFaultLogInfo(FaultLogInfo & info)75 void FaultLogDatabase::SaveFaultLogInfo(FaultLogInfo& info)
76 {
77 std::lock_guard<std::mutex> lock(mutex_);
78 if (info.faultLogType == FaultLogType::SYS_FREEZE) {
79 AnalysisFaultlog(info, info.parsedLogInfo);
80 for (const auto& logInfo : info.parsedLogInfo) {
81 info.sectionMap[logInfo.first] = logInfo.second;
82 }
83 info.parsedLogInfo.clear();
84 }
85 if (!eventLoop_) {
86 HIVIEW_LOGE("eventLoop_ is not inited.");
87 return;
88 }
89 auto task = [info] () mutable {
90 HiSysEventWrite(
91 HiSysEvent::Domain::RELIABILITY,
92 GetFaultNameByType(info.faultLogType, false),
93 HiSysEvent::EventType::FAULT,
94 "FAULT_TYPE", std::to_string(info.faultLogType),
95 "PID", info.pid,
96 "UID", info.id,
97 "MODULE", info.module,
98 "REASON", info.reason,
99 "SUMMARY", info.summary,
100 "LOG_PATH", info.logPath,
101 "VERSION", info.sectionMap.find("VERSION") != info.sectionMap.end() ? info.sectionMap.at("VERSION") : "",
102 "VERSION_CODE", info.sectionMap.find("VERSION_CODE") != info.sectionMap.end() ?
103 info.sectionMap.at("VERSION_CODE") : "",
104 "PRE_INSTALL", info.sectionMap["PRE_INSTALL"],
105 "FOREGROUND", info.sectionMap["FOREGROUND"],
106 "HAPPEN_TIME", info.time,
107 "HITRACE_TIME", info.sectionMap.find("HITRACE_TIME") != info.sectionMap.end() ?
108 info.sectionMap.at("HITRACE_TIME") : "",
109 "SYSRQ_TIME", info.sectionMap.find("SYSRQ_TIME") != info.sectionMap.end() ?
110 info.sectionMap.at("SYSRQ_TIME") : "",
111 "PNAME", info.sectionMap["PROCESS_NAME"].empty() ? "/" : info.sectionMap["PROCESS_NAME"],
112 "FIRST_FRAME", info.sectionMap["FIRST_FRAME"].empty() ? "/" : info.sectionMap["FIRST_FRAME"],
113 "SECOND_FRAME", info.sectionMap["SECOND_FRAME"].empty() ? "/" : info.sectionMap["SECOND_FRAME"],
114 "LAST_FRAME", info.sectionMap["LAST_FRAME"].empty() ? "/" : info.sectionMap["LAST_FRAME"],
115 "FINGERPRINT", info.sectionMap["FINGERPRINT"].empty() ? "/" : info.sectionMap["FINGERPRINT"],
116 "STACK", info.sectionMap["STACK"].empty() ? "" : info.sectionMap["STACK"]
117 );
118 };
119 constexpr int delayTime = 2;
120 eventLoop_->AddTimerEvent(nullptr, nullptr, task, delayTime, false);
121 }
122
CreateQueries(int32_t faultType,EventStore::Cond upperCaseCond,EventStore::Cond lowerCaseCond)123 std::list<std::shared_ptr<EventStore::SysEventQuery>> CreateQueries(
124 int32_t faultType, EventStore::Cond upperCaseCond, EventStore::Cond lowerCaseCond)
125 {
126 std::list<std::shared_ptr<EventStore::SysEventQuery>> queries;
127 if (faultType == FaultLogType::JS_CRASH || faultType == FaultLogType::ALL) {
128 std::vector<std::string> faultNames = { "JS_ERROR" };
129 std::vector<std::string> domains = { HiSysEvent::Domain::ACE, HiSysEvent::Domain::AAFWK };
130 for (std::string domain : domains) {
131 auto query = EventStore::SysEventDao::BuildQuery(domain, faultNames);
132 if (query == nullptr) {
133 continue;
134 }
135 query->And(lowerCaseCond);
136 query->Select(QUERY_ITEMS).Order("time_", false);
137 queries.push_back(query);
138 }
139 }
140 if (faultType != FaultLogType::JS_CRASH) {
141 std::string faultName = GetFaultNameByType(faultType, false);
142 std::vector<std::vector<std::string>> faultNames = { {faultName} };
143 if (faultType == FaultLogType::ALL) {
144 faultNames = { {"CPP_CRASH"}, {"APP_FREEZE"}};
145 }
146 for (auto name : faultNames) {
147 auto query = EventStore::SysEventDao::BuildQuery(HiSysEvent::Domain::RELIABILITY, name);
148 if (query == nullptr) {
149 continue;
150 }
151 query->And(upperCaseCond);
152 query->Select(QUERY_ITEMS).Order("time_", false);
153 queries.push_back(query);
154 }
155 }
156 return queries;
157 }
158
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum)159 std::list<FaultLogInfo> FaultLogDatabase::GetFaultInfoList(const std::string& module, int32_t id,
160 int32_t faultType, int32_t maxNum)
161 {
162 std::lock_guard<std::mutex> lock(mutex_);
163 std::list<FaultLogInfo> queryResult;
164 if (faultType < FaultLogType::ALL || faultType > FaultLogType::APP_FREEZE) {
165 HIVIEW_LOGE("Unsupported fault type, please check it!");
166 return queryResult;
167 }
168 EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
169 EventStore::Cond uidUpperCond = hiviewUidCond.And("UID", EventStore::Op::EQ, id);
170 EventStore::Cond uidLowerCond("uid_", EventStore::Op::EQ, id);
171 auto queries = CreateQueries(faultType, uidUpperCond, uidLowerCond);
172 for (auto query : queries) {
173 if (id != 0) {
174 query->And("MODULE", EventStore::Op::EQ, module);
175 }
176 EventStore::ResultSet resultSet = query->Execute(maxNum);
177 while (resultSet.HasNext()) {
178 auto it = resultSet.Next();
179 FaultLogInfo info;
180 if (!ParseFaultLogInfoFromJson(it->rawData_, info)) {
181 HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
182 continue;
183 }
184 queryResult.push_back(info);
185 }
186 }
187 if (queries.size() > 1) {
188 queryResult.sort(
189 [](const FaultLogInfo& a, const FaultLogInfo& b) {
190 return a.time > b.time;
191 });
192 if (queryResult.size() > static_cast<size_t>(maxNum)) {
193 queryResult.resize(maxNum);
194 }
195 }
196
197 return queryResult;
198 }
199
IsFaultExist(int32_t pid,int32_t uid,int32_t faultType)200 bool FaultLogDatabase::IsFaultExist(int32_t pid, int32_t uid, int32_t faultType)
201 {
202 std::lock_guard<std::mutex> lock(mutex_);
203 if (faultType < FaultLogType::ALL || faultType > FaultLogType::RUST_PANIC) {
204 HIVIEW_LOGE("Unsupported fault type, please check it!");
205 return false;
206 }
207 EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
208 EventStore::Cond pidUpperCond = hiviewUidCond.And("PID", EventStore::Op::EQ, pid).
209 And("UID", EventStore::Op::EQ, uid);
210 EventStore::Cond pidLowerCond("pid_", EventStore::Op::EQ, pid);
211 pidLowerCond = pidLowerCond.And("uid_", EventStore::Op::EQ, uid);
212 auto queries = CreateQueries(faultType, pidUpperCond, pidLowerCond);
213 for (auto query : queries) {
214 if (query->Execute(1).HasNext()) {
215 return true;
216 }
217 }
218 return false;
219 }
220 } // namespace HiviewDFX
221 } // namespace OHOS
222