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 "logger.h"
28 #include "log_analyzer.h"
29 #include "string_util.h"
30 #include "sys_event.h"
31 #include "sys_event_dao.h"
32 #include "time_util.h"
33
34 using namespace std;
35 namespace OHOS {
36 namespace HiviewDFX {
37 DEFINE_LOG_TAG("FaultLogDatabase");
38 namespace {
39 static const std::vector<std::string> QUERY_ITEMS =
40 { "time_", "name_", "uid_", "pid_", "MODULE", "REASON", "SUMMARY", "LOG_PATH", "FAULT_TYPE" };
41 static const std::string LOG_PATH_BASE = "/data/log/faultlog/faultlogger/";
ParseFaultLogInfoFromJson(const std::string & jsonStr,FaultLogInfo & info)42 bool ParseFaultLogInfoFromJson(const std::string& jsonStr, FaultLogInfo& info)
43 {
44 auto sysEvent = std::make_unique<SysEvent>("FaultLogDatabase", nullptr, jsonStr);
45 HIVIEW_LOGI("parse FaultLogInfo from %{public}s. 0", jsonStr.c_str());
46 if (sysEvent->ParseJson() < 0) {
47 HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
48 return false;
49 }
50 info.time = static_cast<int64_t>(std::atoll(sysEvent->GetEventValue("HAPPEN_TIME").c_str()));
51 if (info.time == 0) {
52 info.time = sysEvent->GetEventIntValue("HAPPEN_TIME");
53 }
54 info.pid = sysEvent->GetEventIntValue("PID");
55 if (info.pid == 0) {
56 info.pid = sysEvent->GetEventIntValue("pid_");
57 }
58 info.id = sysEvent->GetEventIntValue("UID");
59 if (info.id == 0) {
60 info.id = sysEvent->GetEventIntValue("uid_");
61 }
62 info.faultLogType = std::atoi(sysEvent->GetEventValue("FAULT_TYPE").c_str());
63 info.module = sysEvent->GetEventValue("MODULE");
64 info.reason = sysEvent->GetEventValue("REASON");
65 info.summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
66 info.logPath = LOG_PATH_BASE + GetFaultLogName(info);
67 return true;
68 }
69 }
70
SaveFaultLogInfo(FaultLogInfo & info)71 void FaultLogDatabase::SaveFaultLogInfo(FaultLogInfo& info)
72 {
73 std::lock_guard<std::mutex> lock(mutex_);
74 std::map<std::string, std::string> eventInfos;
75 AnalysisFaultlog(info, eventInfos);
76 HiSysEvent::Write("RELIABILITY", GetFaultNameByType(info.faultLogType, false), HiSysEvent::EventType::FAULT,
77 "FAULT_TYPE", std::to_string(info.faultLogType),
78 "PID", info.pid,
79 "UID", info.id,
80 "MODULE", info.module,
81 "REASON", info.reason,
82 "SUMMARY", info.summary,
83 "LOG_PATH", info.logPath,
84 "VERSION", info.sectionMap.find("VERSION") != info.sectionMap.end() ? info.sectionMap.at("VERSION") : "",
85 "HAPPEN_TIME", std::to_string(info.time),
86 "PNAME", eventInfos["PNAME"].empty() ? "/" : eventInfos["PNAME"],
87 "FIRST_FRAME", eventInfos["FIRST_FRAME"].empty() ? "/" : eventInfos["FIRST_FRAME"],
88 "SECOND_FRAME", eventInfos["SECOND_FRAME"].empty() ? "/" : eventInfos["SECOND_FRAME"],
89 "LAST_FRAME", eventInfos["LAST_FRAME"].empty() ? "/" : eventInfos["LAST_FRAME"],
90 "FINGERPRINT", eventInfos["fingerPrint"].empty() ? "/" : eventInfos["fingerPrint"]
91 );
92 }
93
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum)94 std::list<FaultLogInfo> FaultLogDatabase::GetFaultInfoList(const std::string& module, int32_t id,
95 int32_t faultType, int32_t maxNum)
96 {
97 std::lock_guard<std::mutex> lock(mutex_);
98 std::list<FaultLogInfo> queryResult;
99 auto query = EventStore::SysEventDao::BuildQuery(EventStore::StoreType::FAULT);
100 EventStore::Cond uidCond("UID", EventStore::Op::EQ, id);
101 EventStore::Cond hiviewCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
102 EventStore::Cond condLeft = uidCond.And(hiviewCond);
103 EventStore::Cond condRight("uid_", EventStore::Op::EQ, id);
104 EventStore::Cond condTotal;
105 if (faultType == FaultLogType::CPP_CRASH || faultType == FaultLogType::APP_FREEZE) {
106 condTotal = condLeft;
107 } else if (faultType == FaultLogType::JS_CRASH) {
108 condTotal = condRight;
109 } else {
110 condTotal = condLeft.Or(condRight);
111 }
112 (*query).Select(QUERY_ITEMS).Where(condTotal).Order("time_", false);
113 if (id != 0) {
114 query->And("MODULE", EventStore::Op::EQ, module);
115 }
116
117 if (faultType != 0) {
118 query->And("FAULT_TYPE", EventStore::Op::EQ, faultType);
119 }
120
121 EventStore::ResultSet resultSet = query->Execute(maxNum);
122 while (resultSet.HasNext()) {
123 auto it = resultSet.Next();
124 FaultLogInfo info;
125 if (!ParseFaultLogInfoFromJson(it->jsonExtraInfo_, info)) {
126 HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
127 continue;
128 }
129 queryResult.push_back(info);
130 }
131 return queryResult;
132 }
133
IsFaultExist(int32_t pid,int32_t uid,int32_t faultType)134 bool FaultLogDatabase::IsFaultExist(int32_t pid, int32_t uid, int32_t faultType)
135 {
136 std::lock_guard<std::mutex> lock(mutex_);
137 auto query = EventStore::SysEventDao::BuildQuery(EventStore::StoreType::FAULT);
138 EventStore::Cond pidUpperCond("PID", EventStore::Op::EQ, pid);
139 EventStore::Cond pidLowerCond("pid_", EventStore::Op::EQ, pid);
140 EventStore::Cond uidUpperCond("UID", EventStore::Op::EQ, uid);
141 EventStore::Cond uidLowerCond("uid_", EventStore::Op::EQ, uid);
142 EventStore::Cond hiviewCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
143 EventStore::Cond typeCond("FAULT_TYPE", EventStore::Op::EQ, faultType);
144 EventStore::Cond condLeft = hiviewCond.And(pidUpperCond).And(uidUpperCond).And(typeCond);
145 EventStore::Cond condRight = pidLowerCond.And(uidLowerCond).And(typeCond);
146 EventStore::Cond condTotal;
147 if (faultType == FaultLogType::CPP_CRASH || faultType == FaultLogType::APP_FREEZE) {
148 condTotal = condLeft;
149 } else if (faultType == FaultLogType::JS_CRASH) {
150 condTotal = condRight;
151 } else {
152 condTotal = condLeft.Or(condRight);
153 }
154 (*query).Select(QUERY_ITEMS).Where(condTotal).Order("time_", false);
155 return query->Execute(1).HasNext();
156 }
157 } // namespace HiviewDFX
158 } // namespace OHOS
159