• 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 #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 first200Bytes = 200;
52     constexpr int64_t defaultIntValue = 0;
53     constexpr int decimalBase = 10;
54     info.time = static_cast<int64_t>(strtoll(sysEvent->GetEventValue("HAPPEN_TIME").c_str(), nullptr, decimalBase));
55     if (info.time == defaultIntValue) {
56         info.time = sysEvent->GetEventIntValue("HAPPEN_TIME") != defaultIntValue ?
57                     sysEvent->GetEventIntValue("HAPPEN_TIME") : sysEvent->GetEventIntValue("time_");
58     }
59     info.pid = sysEvent->GetEventIntValue("PID") != defaultIntValue ?
60                sysEvent->GetEventIntValue("PID") : sysEvent->GetEventIntValue("pid_");
61 
62     info.id = sysEvent->GetEventIntValue("UID") != defaultIntValue ?
63               sysEvent->GetEventIntValue("UID") : sysEvent->GetEventIntValue("uid_");
64     info.faultLogType = static_cast<int32_t>(
65         strtoul(sysEvent->GetEventValue("FAULT_TYPE").c_str(), nullptr, decimalBase));
66     info.module = sysEvent->GetEventValue("MODULE");
67     info.reason = sysEvent->GetEventValue("REASON");
68     info.summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
69     info.logPath = LOG_PATH_BASE + GetFaultLogName(info);
70     HIVIEW_LOGI("eventName:%{public}s, time %{public}" PRId64 ", uid %{public}d, pid %{public}d, "
71                 "module: %{public}s, reason: %{public}s",
72                 sysEvent->eventName_.c_str(), info.time, info.id, info.pid,
73                 info.module.c_str(), info.reason.c_str());
74     return true;
75 }
76 }
77 
FaultLogDatabase(const std::shared_ptr<EventLoop> & eventLoop)78 FaultLogDatabase::FaultLogDatabase(const std::shared_ptr<EventLoop>& eventLoop) : eventLoop_(eventLoop) {}
79 
SaveFaultLogInfo(FaultLogInfo & info)80 void FaultLogDatabase::SaveFaultLogInfo(FaultLogInfo& info)
81 {
82     std::lock_guard<std::mutex> lock(mutex_);
83     if (!eventLoop_) {
84         HIVIEW_LOGE("eventLoop_ is not inited.");
85         return;
86     }
87     auto task = [info] () mutable {
88         HiSysEventWrite(
89             HiSysEvent::Domain::RELIABILITY,
90             GetFaultNameByType(info.faultLogType, false),
91             HiSysEvent::EventType::FAULT,
92             "FAULT_TYPE", std::to_string(info.faultLogType),
93             "PID", info.pid,
94             "UID", info.id,
95             "MODULE", info.module,
96             "REASON", info.reason,
97             "SUMMARY", info.summary,
98             "LOG_PATH", info.logPath,
99             "VERSION", info.sectionMap.find("VERSION") != info.sectionMap.end() ? info.sectionMap.at("VERSION") : "",
100             "VERSION_CODE", info.sectionMap.find("VERSION_CODE") != info.sectionMap.end() ?
101                             info.sectionMap.at("VERSION_CODE") : "",
102             "PRE_INSTALL", info.sectionMap["PRE_INSTALL"],
103             "FOREGROUND", info.sectionMap["FOREGROUND"],
104             "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             "PNAME", info.sectionMap["PROCESS_NAME"].empty() ? "/" : info.sectionMap["PROCESS_NAME"],
110             "FIRST_FRAME", info.sectionMap["FIRST_FRAME"].empty() ? "/" : info.sectionMap["FIRST_FRAME"],
111             "SECOND_FRAME", info.sectionMap["SECOND_FRAME"].empty() ? "/" : info.sectionMap["SECOND_FRAME"],
112             "LAST_FRAME", info.sectionMap["LAST_FRAME"].empty() ? "/" : info.sectionMap["LAST_FRAME"],
113             "FINGERPRINT", info.sectionMap["FINGERPRINT"].empty() ? "/" : info.sectionMap["FINGERPRINT"],
114             "STACK", info.sectionMap["STACK"].empty() ? "" : info.sectionMap["STACK"]
115         );
116     };
117     if (info.faultLogType == FaultLogType::CPP_CRASH) {
118         constexpr int delayTime = 2; // Delay for 2 seconds to wait for ffrt log generation
119         eventLoop_->AddTimerEvent(nullptr, nullptr, task, delayTime, false);
120     } else {
121         task();
122     }
123 }
124 
CreateQueries(int32_t faultType,EventStore::Cond upperCaseCond,EventStore::Cond lowerCaseCond)125 std::list<std::shared_ptr<EventStore::SysEventQuery>> CreateQueries(
126     int32_t faultType, EventStore::Cond upperCaseCond, EventStore::Cond lowerCaseCond)
127 {
128     std::list<std::shared_ptr<EventStore::SysEventQuery>> queries;
129     if (faultType == FaultLogType::JS_CRASH || faultType == FaultLogType::ALL) {
130         std::vector<std::string> faultNames = { "JS_ERROR" };
131         std::vector<std::string> domains = { HiSysEvent::Domain::ACE, HiSysEvent::Domain::AAFWK };
132         for (std::string domain : domains) {
133             auto query = EventStore::SysEventDao::BuildQuery(domain, faultNames);
134             if (query == nullptr) {
135                 continue;
136             }
137             query->And(lowerCaseCond);
138             query->Select(QUERY_ITEMS).Order("time_", false);
139             queries.push_back(query);
140         }
141     }
142     if (faultType != FaultLogType::JS_CRASH) {
143         std::string faultName = GetFaultNameByType(faultType, false);
144         std::vector<std::vector<std::string>> faultNames = { {faultName} };
145         if (faultType == FaultLogType::ALL) {
146             faultNames = { {"CPP_CRASH"}, {"APP_FREEZE"}};
147         }
148         for (auto name : faultNames) {
149             auto query = EventStore::SysEventDao::BuildQuery(HiSysEvent::Domain::RELIABILITY, name);
150             if (query == nullptr) {
151                 continue;
152             }
153             query->And(upperCaseCond);
154             query->Select(QUERY_ITEMS).Order("time_", false);
155             queries.push_back(query);
156         }
157     }
158     return queries;
159 }
160 
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum)161 std::list<FaultLogInfo> FaultLogDatabase::GetFaultInfoList(const std::string& module, int32_t id,
162     int32_t faultType, int32_t maxNum)
163 {
164     std::lock_guard<std::mutex> lock(mutex_);
165     std::list<FaultLogInfo> queryResult;
166     if (faultType < FaultLogType::ALL || faultType > FaultLogType::APP_FREEZE) {
167         HIVIEW_LOGE("Unsupported fault type, please check it!");
168         return queryResult;
169     }
170     EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
171     EventStore::Cond uidUpperCond = hiviewUidCond.And("UID", EventStore::Op::EQ, id);
172     EventStore::Cond uidLowerCond("uid_", EventStore::Op::EQ, id);
173     auto queries = CreateQueries(faultType, uidUpperCond, uidLowerCond);
174     for (auto query : queries) {
175         if (id != 0) {
176             query->And("MODULE", EventStore::Op::EQ, module);
177         }
178         EventStore::ResultSet resultSet = query->Execute(maxNum);
179         while (resultSet.HasNext()) {
180             auto it = resultSet.Next();
181             FaultLogInfo info;
182             if (!ParseFaultLogInfoFromJson(it->rawData_, info)) {
183                 HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
184                 continue;
185             }
186             queryResult.push_back(info);
187         }
188     }
189     if (queries.size() > 1) {
190         queryResult.sort(
191             [](const FaultLogInfo& a, const FaultLogInfo& b) {
192             return a.time > b.time;
193         });
194         if (queryResult.size() > static_cast<size_t>(maxNum)) {
195             queryResult.resize(maxNum);
196         }
197     }
198 
199     return queryResult;
200 }
201 
IsFaultExist(int32_t pid,int32_t uid,int32_t faultType)202 bool FaultLogDatabase::IsFaultExist(int32_t pid, int32_t uid, int32_t faultType)
203 {
204     std::lock_guard<std::mutex> lock(mutex_);
205     if (faultType < FaultLogType::ALL || faultType > FaultLogType::RUST_PANIC) {
206         HIVIEW_LOGE("Unsupported fault type, please check it!");
207         return false;
208     }
209     EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
210     EventStore::Cond pidUpperCond = hiviewUidCond.And("PID", EventStore::Op::EQ, pid).
211         And("UID", EventStore::Op::EQ, uid);
212     EventStore::Cond pidLowerCond("pid_", EventStore::Op::EQ, pid);
213     pidLowerCond = pidLowerCond.And("uid_", EventStore::Op::EQ, uid);
214     auto queries = CreateQueries(faultType, pidUpperCond, pidLowerCond);
215     for (auto query : queries) {
216         if (query->Execute(1).HasNext()) {
217             return true;
218         }
219     }
220     return false;
221 }
222 }  // namespace HiviewDFX
223 }  // namespace OHOS
224