• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 "constants.h"
24 #include "decoded/decoded_event.h"
25 #include "faultlog_info.h"
26 #include "faultlog_util.h"
27 #include "hisysevent.h"
28 #include "hitrace/hitracechainc.h"
29 #include "hiview_global.h"
30 #include "hiview_logger.h"
31 #include "log_analyzer.h"
32 #include "string_util.h"
33 #include "sys_event_dao.h"
34 #include "time_util.h"
35 
36 using namespace std;
37 namespace OHOS {
38 namespace HiviewDFX {
39 DEFINE_LOG_LABEL(0xD002D11, "FaultLogDatabase");
40 using namespace FaultLogger;
41 namespace {
42 static const std::vector<std::string> QUERY_ITEMS = {
43     "time_", "name_", "uid_", "pid_", FaultKey::MODULE_NAME, FaultKey::REASON, FaultKey::SUMMARY, FaultKey::LOG_PATH,
44     FaultKey::FAULT_TYPE
45 };
46 }
47 
ParseFaultLogInfoFromJson(std::shared_ptr<EventRaw::RawData> rawData,FaultLogInfo & info)48 bool FaultLogDatabase::ParseFaultLogInfoFromJson(std::shared_ptr<EventRaw::RawData> rawData, FaultLogInfo& info)
49 {
50     if (rawData == nullptr) {
51         HIVIEW_LOGE("raw data of sys event is null.");
52         return false;
53     }
54     auto sysEvent = std::make_unique<SysEvent>("FaultLogDatabase", nullptr, rawData);
55     constexpr string::size_type first200Bytes = 200;
56     constexpr int64_t defaultIntValue = 0;
57     info.time = static_cast<int64_t>
58         (strtoll(sysEvent->GetEventValue(FaultKey::HAPPEN_TIME).c_str(), nullptr, DECIMAL_BASE));
59     if (info.time == defaultIntValue) {
60         info.time = sysEvent->GetEventIntValue(FaultKey::HAPPEN_TIME) != defaultIntValue ?
61                     sysEvent->GetEventIntValue(FaultKey::HAPPEN_TIME) : sysEvent->GetEventIntValue("time_");
62     }
63     info.pid = sysEvent->GetEventIntValue(FaultKey::MODULE_PID) != defaultIntValue ?
64                sysEvent->GetEventIntValue(FaultKey::MODULE_PID) : sysEvent->GetEventIntValue("pid_");
65 
66     info.id = sysEvent->GetEventIntValue(FaultKey::MODULE_UID) != defaultIntValue ?
67               sysEvent->GetEventIntValue(FaultKey::MODULE_UID) : sysEvent->GetEventIntValue("uid_");
68     info.faultLogType = static_cast<int32_t>(
69         strtoul(sysEvent->GetEventValue(FaultKey::FAULT_TYPE).c_str(), nullptr, DECIMAL_BASE));
70     info.module = sysEvent->GetEventValue(FaultKey::MODULE_NAME);
71     info.reason = sysEvent->GetEventValue(FaultKey::REASON);
72     info.summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue(FaultKey::SUMMARY));
73     info.logPath = FAULTLOG_FAULT_LOGGER_FOLDER + GetFaultLogName(info);
74     HIVIEW_LOGI("eventName:%{public}s, time %{public}" PRId64 ", uid %{public}d, pid %{public}d, "
75                 "module: %{public}s, reason: %{public}s",
76                 sysEvent->eventName_.c_str(), info.time, info.id, info.pid,
77                 info.module.c_str(), info.reason.c_str());
78     return true;
79 }
80 
FaultLogDatabase(const std::shared_ptr<EventLoop> & eventLoop)81 FaultLogDatabase::FaultLogDatabase(const std::shared_ptr<EventLoop>& eventLoop) : eventLoop_(eventLoop) {}
82 
SaveFaultLogInfo(FaultLogInfo & info)83 void FaultLogDatabase::SaveFaultLogInfo(FaultLogInfo& info)
84 {
85     std::lock_guard<std::mutex> lock(mutex_);
86     if (!eventLoop_) {
87         HIVIEW_LOGE("eventLoop_ is not inited.");
88         return;
89     }
90     // Get hitrace id which from processdump
91     HiTraceIdStruct hitraceId = HiTraceChainGetId();
92     auto task = [info, hitraceId] () mutable {
93         // Need set hitrace again in async task
94         HiTraceChainSetId(&hitraceId);
95         int result = HiSysEventWrite(HiSysEvent::Domain::RELIABILITY, GetFaultNameByType(info.faultLogType, false),
96             HiSysEvent::EventType::FAULT, FaultKey::FAULT_TYPE, std::to_string(info.faultLogType),
97             FaultKey::MODULE_PID, info.pid, FaultKey::MODULE_UID, info.id, FaultKey::MODULE_NAME, info.module,
98             FaultKey::REASON, info.reason, FaultKey::SUMMARY, info.summary, FaultKey::LOG_PATH, info.logPath,
99             FaultKey::MODULE_VERSION, info.sectionMap.find(FaultKey::MODULE_VERSION) != info.sectionMap.end() ?
100                 info.sectionMap.at(FaultKey::MODULE_VERSION) : "",
101             FaultKey::VERSION_CODE, info.sectionMap.find(FaultKey::VERSION_CODE) != info.sectionMap.end() ?
102                             info.sectionMap.at(FaultKey::VERSION_CODE) : "",
103             FaultKey::PRE_INSTALL, info.sectionMap[FaultKey::PRE_INSTALL],
104             FaultKey::FOREGROUND, info.sectionMap[FaultKey::FOREGROUND], FaultKey::HAPPEN_TIME, info.time,
105             "HITRACE_TIME", info.sectionMap.find("HITRACE_TIME") != info.sectionMap.end() ?
106                             info.sectionMap.at("HITRACE_TIME") : "",
107             "SYSRQ_TIME", info.sectionMap.find("SYSRQ_TIME") != info.sectionMap.end() ?
108                           info.sectionMap.at("SYSRQ_TIME") : "",
109             "FG", info.sectionMap.find("INVAILED_HILOG_TIME") != info.sectionMap.end() ?
110                             (info.sectionMap.at("INVAILED_HILOG_TIME") == "true" ? 1 : -1) : 0,
111             FaultKey::P_NAME, info.sectionMap["PROCESS_NAME"].empty() ? "/" : info.sectionMap["PROCESS_NAME"],
112             FaultKey::FIRST_FRAME, info.sectionMap[FaultKey::FIRST_FRAME].empty() ?
113                 "/" : info.sectionMap[FaultKey::FIRST_FRAME],
114             FaultKey::SECOND_FRAME, info.sectionMap[FaultKey::SECOND_FRAME].empty() ?
115                 "/" : info.sectionMap[FaultKey::SECOND_FRAME],
116             FaultKey::LAST_FRAME, info.sectionMap[FaultKey::LAST_FRAME].empty() ?
117                 "/" : info.sectionMap[FaultKey::LAST_FRAME],
118             FaultKey::FINGERPRINT, info.sectionMap[FaultKey::FINGERPRINT].empty() ?
119                 "/" : info.sectionMap[FaultKey::FINGERPRINT],
120             FaultKey::STACK, info.sectionMap[FaultKey::STACK].empty() ? "" : info.sectionMap[FaultKey::STACK],
121             FaultKey::TELEMETRY_ID, info.sectionMap[FaultKey::TELEMETRY_ID].empty() ?
122                 "" : info.sectionMap[FaultKey::TELEMETRY_ID],
123             FaultKey::TRACE_NAME, info.sectionMap[FaultKey::TRACE_NAME].empty() ?
124                 "" : info.sectionMap[FaultKey::TRACE_NAME]);
125         std::string eventName = GetFaultNameByType(info.faultLogType, false);
126         HIVIEW_LOGI("SaveFaultLogInfo for event: %{public}s, and result = %{public}d", eventName.c_str(), result);
127         HiTraceChainClearId();
128     };
129     if (info.faultLogType == FaultLogType::CPP_CRASH) {
130         constexpr int delayTime = 2; // Delay for 2 seconds to wait for ffrt log generation
131         eventLoop_->AddTimerEvent(nullptr, nullptr, task, delayTime, false);
132     } else {
133         task();
134     }
135 }
136 
CreateJsQueries(int32_t faultType,EventStore::Cond upperCaseCond,EventStore::Cond lowerCaseCond)137 std::list<std::shared_ptr<EventStore::SysEventQuery>> CreateJsQueries(int32_t faultType, EventStore::Cond upperCaseCond,
138     EventStore::Cond lowerCaseCond)
139 {
140     std::list<std::shared_ptr<EventStore::SysEventQuery>> queries;
141     if (faultType == FaultLogType::JS_CRASH || faultType == FaultLogType::ALL) {
142         std::vector<std::string> faultNames = { "JS_ERROR" };
143         std::vector<std::string> domains = { HiSysEvent::Domain::ACE, HiSysEvent::Domain::AAFWK };
144         for (std::string domain : domains) {
145             auto query = EventStore::SysEventDao::BuildQuery(domain, faultNames);
146             if (query == nullptr) {
147                 continue;
148             }
149             query->And(lowerCaseCond);
150             query->Select(QUERY_ITEMS).Order("time_", false);
151             queries.push_back(query);
152         }
153     }
154     return queries;
155 }
156 
CreateQueries(int32_t faultType,EventStore::Cond upperCaseCond,EventStore::Cond lowerCaseCond)157 std::list<std::shared_ptr<EventStore::SysEventQuery>> CreateQueries(
158     int32_t faultType, EventStore::Cond upperCaseCond, EventStore::Cond lowerCaseCond)
159 {
160     auto queries = CreateJsQueries(faultType, upperCaseCond, lowerCaseCond);
161     if (faultType != FaultLogType::JS_CRASH) {
162         std::string faultName = GetFaultNameByType(faultType, false);
163         std::vector<std::vector<std::string>> faultNames = { {faultName} };
164         if (faultType == FaultLogType::ALL) {
165             faultNames = { {"CPP_CRASH"}, {"APP_FREEZE"}};
166         }
167         for (auto name : faultNames) {
168             auto query = EventStore::SysEventDao::BuildQuery(HiSysEvent::Domain::RELIABILITY, name);
169             if (query == nullptr) {
170                 continue;
171             }
172             query->And(upperCaseCond);
173             query->Select(QUERY_ITEMS).Order("time_", false);
174             queries.push_back(query);
175         }
176     }
177     return queries;
178 }
179 
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum)180 std::list<FaultLogInfo> FaultLogDatabase::GetFaultInfoList(const std::string& module, int32_t id,
181     int32_t faultType, int32_t maxNum)
182 {
183     std::lock_guard<std::mutex> lock(mutex_);
184     std::list<FaultLogInfo> queryResult;
185     if (faultType < FaultLogType::ALL || faultType > FaultLogType::APP_FREEZE) {
186         HIVIEW_LOGE("Unsupported fault type, please check it!");
187         return queryResult;
188     }
189     EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
190     EventStore::Cond uidUpperCond = hiviewUidCond.And(FaultKey::MODULE_UID, EventStore::Op::EQ, id);
191     EventStore::Cond uidLowerCond("uid_", EventStore::Op::EQ, id);
192     auto queries = CreateQueries(faultType, uidUpperCond, uidLowerCond);
193     for (auto query : queries) {
194         if (id != 0) {
195             query->And(FaultKey::MODULE_NAME, EventStore::Op::EQ, module);
196         }
197         EventStore::ResultSet resultSet = query->Execute(maxNum);
198         while (resultSet.HasNext()) {
199             auto it = resultSet.Next();
200             FaultLogInfo info;
201             if (!ParseFaultLogInfoFromJson(it->rawData_, info)) {
202                 HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
203                 continue;
204             }
205             queryResult.push_back(info);
206         }
207     }
208     if (queries.size() > 1) {
209         queryResult.sort(
210             [](const FaultLogInfo& a, const FaultLogInfo& b) {
211             return a.time > b.time;
212         });
213         if (queryResult.size() > static_cast<size_t>(maxNum)) {
214             queryResult.resize(maxNum);
215         }
216     }
217 
218     return queryResult;
219 }
220 
IsFaultExist(int32_t pid,int32_t uid,int32_t faultType)221 bool FaultLogDatabase::IsFaultExist(int32_t pid, int32_t uid, int32_t faultType)
222 {
223     std::lock_guard<std::mutex> lock(mutex_);
224     if (faultType < FaultLogType::ALL || faultType > FaultLogType::RUST_PANIC) {
225         HIVIEW_LOGE("Unsupported fault type, please check it!");
226         return false;
227     }
228     EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
229     EventStore::Cond pidUpperCond = hiviewUidCond.And(FaultKey::MODULE_PID, EventStore::Op::EQ, pid).
230         And(FaultKey::MODULE_UID, EventStore::Op::EQ, uid);
231     EventStore::Cond pidLowerCond("pid_", EventStore::Op::EQ, pid);
232     pidLowerCond = pidLowerCond.And("uid_", EventStore::Op::EQ, uid);
233     auto queries = CreateQueries(faultType, pidUpperCond, pidLowerCond);
234     for (auto query : queries) {
235         if (query->Execute(1).HasNext()) {
236             return true;
237         }
238     }
239     return false;
240 }
241 }  // namespace HiviewDFX
242 }  // namespace OHOS
243