1020a203aSopenharmony_ci/*
2020a203aSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
3020a203aSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4020a203aSopenharmony_ci * you may not use this file except in compliance with the License.
5020a203aSopenharmony_ci * You may obtain a copy of the License at
6020a203aSopenharmony_ci *
7020a203aSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8020a203aSopenharmony_ci *
9020a203aSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10020a203aSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11020a203aSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12020a203aSopenharmony_ci * See the License for the specific language governing permissions and
13020a203aSopenharmony_ci * limitations under the License.
14020a203aSopenharmony_ci */
15020a203aSopenharmony_ci#include "faultlog_database.h"
16020a203aSopenharmony_ci
17020a203aSopenharmony_ci#include <algorithm>
18020a203aSopenharmony_ci#include <cinttypes>
19020a203aSopenharmony_ci#include <list>
20020a203aSopenharmony_ci#include <mutex>
21020a203aSopenharmony_ci#include <string>
22020a203aSopenharmony_ci
23020a203aSopenharmony_ci#include "faultlog_info.h"
24020a203aSopenharmony_ci#include "faultlog_util.h"
25020a203aSopenharmony_ci#include "hisysevent.h"
26020a203aSopenharmony_ci#include "hiview_global.h"
27020a203aSopenharmony_ci#include "hiview_logger.h"
28020a203aSopenharmony_ci#include "log_analyzer.h"
29020a203aSopenharmony_ci#include "string_util.h"
30020a203aSopenharmony_ci#include "sys_event_dao.h"
31020a203aSopenharmony_ci#include "time_util.h"
32020a203aSopenharmony_ci
33020a203aSopenharmony_ci#include "decoded/decoded_event.h"
34020a203aSopenharmony_ci
35020a203aSopenharmony_ciusing namespace std;
36020a203aSopenharmony_cinamespace OHOS {
37020a203aSopenharmony_cinamespace HiviewDFX {
38020a203aSopenharmony_ciDEFINE_LOG_LABEL(0xD002D11, "FaultLogDatabase");
39020a203aSopenharmony_cinamespace {
40020a203aSopenharmony_cistatic const std::vector<std::string> QUERY_ITEMS = {
41020a203aSopenharmony_ci    "time_", "name_", "uid_", "pid_", "MODULE", "REASON", "SUMMARY", "LOG_PATH", "FAULT_TYPE"
42020a203aSopenharmony_ci};
43020a203aSopenharmony_cistatic const std::string LOG_PATH_BASE = "/data/log/faultlog/faultlogger/";
44020a203aSopenharmony_cibool ParseFaultLogInfoFromJson(std::shared_ptr<EventRaw::RawData> rawData, FaultLogInfo& info)
45020a203aSopenharmony_ci{
46020a203aSopenharmony_ci    if (rawData == nullptr) {
47020a203aSopenharmony_ci        HIVIEW_LOGE("raw data of sys event is null.");
48020a203aSopenharmony_ci        return false;
49020a203aSopenharmony_ci    }
50020a203aSopenharmony_ci    auto sysEvent = std::make_unique<SysEvent>("FaultLogDatabase", nullptr, rawData);
51020a203aSopenharmony_ci    constexpr string::size_type FIRST_200_BYTES = 200;
52020a203aSopenharmony_ci    HIVIEW_LOGI("parse FaultLogInfo from %{public}s.", sysEvent->AsJsonStr().substr(0, FIRST_200_BYTES).c_str());
53020a203aSopenharmony_ci    constexpr int64_t DEFAULT_INT_VALUE = 0;
54020a203aSopenharmony_ci    info.time = static_cast<int64_t>(std::atoll(sysEvent->GetEventValue("HAPPEN_TIME").c_str()));
55020a203aSopenharmony_ci    if (info.time == DEFAULT_INT_VALUE) {
56020a203aSopenharmony_ci        info.time = sysEvent->GetEventIntValue("HAPPEN_TIME") != DEFAULT_INT_VALUE?
57020a203aSopenharmony_ci                    sysEvent->GetEventIntValue("HAPPEN_TIME") : sysEvent->GetEventIntValue("time_");
58020a203aSopenharmony_ci    }
59020a203aSopenharmony_ci    info.pid = sysEvent->GetEventIntValue("PID") != DEFAULT_INT_VALUE ?
60020a203aSopenharmony_ci               sysEvent->GetEventIntValue("PID") : sysEvent->GetEventIntValue("pid_");
61020a203aSopenharmony_ci
62020a203aSopenharmony_ci    info.id = sysEvent->GetEventIntValue("UID") != DEFAULT_INT_VALUE ?
63020a203aSopenharmony_ci              sysEvent->GetEventIntValue("UID") : sysEvent->GetEventIntValue("uid_");
64020a203aSopenharmony_ci    info.faultLogType = std::atoi(sysEvent->GetEventValue("FAULT_TYPE").c_str());
65020a203aSopenharmony_ci    info.module = sysEvent->GetEventValue("MODULE");
66020a203aSopenharmony_ci    info.reason = sysEvent->GetEventValue("REASON");
67020a203aSopenharmony_ci    info.summary = StringUtil::UnescapeJsonStringValue(sysEvent->GetEventValue("SUMMARY"));
68020a203aSopenharmony_ci    info.logPath = LOG_PATH_BASE + GetFaultLogName(info);
69020a203aSopenharmony_ci    return true;
70020a203aSopenharmony_ci}
71020a203aSopenharmony_ci}
72020a203aSopenharmony_ci
73020a203aSopenharmony_ciFaultLogDatabase::FaultLogDatabase(const std::shared_ptr<EventLoop>& eventLoop) : eventLoop_(eventLoop) {}
74020a203aSopenharmony_ci
75020a203aSopenharmony_civoid FaultLogDatabase::SaveFaultLogInfo(FaultLogInfo& info)
76020a203aSopenharmony_ci{
77020a203aSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
78020a203aSopenharmony_ci    if (info.faultLogType == FaultLogType::SYS_FREEZE) {
79020a203aSopenharmony_ci        AnalysisFaultlog(info, info.parsedLogInfo);
80020a203aSopenharmony_ci        for (const auto& logInfo : info.parsedLogInfo) {
81020a203aSopenharmony_ci            info.sectionMap[logInfo.first] = logInfo.second;
82020a203aSopenharmony_ci        }
83020a203aSopenharmony_ci        info.parsedLogInfo.clear();
84020a203aSopenharmony_ci    }
85020a203aSopenharmony_ci    if (!eventLoop_) {
86020a203aSopenharmony_ci        HIVIEW_LOGE("eventLoop_ is not inited.");
87020a203aSopenharmony_ci        return;
88020a203aSopenharmony_ci    }
89020a203aSopenharmony_ci    auto task = [info] () mutable {
90020a203aSopenharmony_ci        HiSysEventWrite(
91020a203aSopenharmony_ci            HiSysEvent::Domain::RELIABILITY,
92020a203aSopenharmony_ci            GetFaultNameByType(info.faultLogType, false),
93020a203aSopenharmony_ci            HiSysEvent::EventType::FAULT,
94020a203aSopenharmony_ci            "FAULT_TYPE", std::to_string(info.faultLogType),
95020a203aSopenharmony_ci            "PID", info.pid,
96020a203aSopenharmony_ci            "UID", info.id,
97020a203aSopenharmony_ci            "MODULE", info.module,
98020a203aSopenharmony_ci            "REASON", info.reason,
99020a203aSopenharmony_ci            "SUMMARY", info.summary,
100020a203aSopenharmony_ci            "LOG_PATH", info.logPath,
101020a203aSopenharmony_ci            "VERSION", info.sectionMap.find("VERSION") != info.sectionMap.end() ? info.sectionMap.at("VERSION") : "",
102020a203aSopenharmony_ci            "PRE_INSTALL", info.sectionMap["PRE_INSTALL"],
103020a203aSopenharmony_ci            "FOREGROUND", info.sectionMap["FOREGROUND"],
104020a203aSopenharmony_ci            "HAPPEN_TIME", info.time,
105020a203aSopenharmony_ci            "HITRACE_TIME", info.sectionMap.find("HITRACE_TIME") != info.sectionMap.end() ?
106020a203aSopenharmony_ci                            info.sectionMap.at("HITRACE_TIME") : "",
107020a203aSopenharmony_ci            "SYSRQ_TIME", info.sectionMap.find("SYSRQ_TIME") != info.sectionMap.end() ?
108020a203aSopenharmony_ci                          info.sectionMap.at("SYSRQ_TIME") : "",
109020a203aSopenharmony_ci            "PNAME", info.sectionMap["PROCESS_NAME"].empty() ? "/" : info.sectionMap["PROCESS_NAME"],
110020a203aSopenharmony_ci            "FIRST_FRAME", info.sectionMap["FIRST_FRAME"].empty() ? "/" : info.sectionMap["FIRST_FRAME"],
111020a203aSopenharmony_ci            "SECOND_FRAME", info.sectionMap["SECOND_FRAME"].empty() ? "/" : info.sectionMap["SECOND_FRAME"],
112020a203aSopenharmony_ci            "LAST_FRAME", info.sectionMap["LAST_FRAME"].empty() ? "/" : info.sectionMap["LAST_FRAME"],
113020a203aSopenharmony_ci            "FINGERPRINT", info.sectionMap["fingerPrint"].empty() ? "/" : info.sectionMap["fingerPrint"],
114020a203aSopenharmony_ci            "STACK", info.sectionMap["STACK"].empty() ? "" : info.sectionMap["STACK"]
115020a203aSopenharmony_ci        );
116020a203aSopenharmony_ci    };
117020a203aSopenharmony_ci    constexpr int delayTime = 2;
118020a203aSopenharmony_ci    eventLoop_->AddTimerEvent(nullptr, nullptr, task, delayTime, false);
119020a203aSopenharmony_ci}
120020a203aSopenharmony_ci
121020a203aSopenharmony_cistd::list<std::shared_ptr<EventStore::SysEventQuery>> CreateQueries(
122020a203aSopenharmony_ci    int32_t faultType, EventStore::Cond upperCaseCond, EventStore::Cond lowerCaseCond)
123020a203aSopenharmony_ci{
124020a203aSopenharmony_ci    std::list<std::shared_ptr<EventStore::SysEventQuery>> queries;
125020a203aSopenharmony_ci    if (faultType == FaultLogType::JS_CRASH || faultType == FaultLogType::ALL) {
126020a203aSopenharmony_ci        std::vector<std::string> faultNames = { "JS_ERROR" };
127020a203aSopenharmony_ci        std::vector<std::string> domains = { HiSysEvent::Domain::ACE, HiSysEvent::Domain::AAFWK };
128020a203aSopenharmony_ci        for (std::string domain : domains) {
129020a203aSopenharmony_ci            auto query = EventStore::SysEventDao::BuildQuery(domain, faultNames);
130020a203aSopenharmony_ci            if (query == nullptr) {
131020a203aSopenharmony_ci                continue;
132020a203aSopenharmony_ci            }
133020a203aSopenharmony_ci            query->And(lowerCaseCond);
134020a203aSopenharmony_ci            query->Select(QUERY_ITEMS).Order("time_", false);
135020a203aSopenharmony_ci            queries.push_back(query);
136020a203aSopenharmony_ci        }
137020a203aSopenharmony_ci    }
138020a203aSopenharmony_ci    if (faultType != FaultLogType::JS_CRASH) {
139020a203aSopenharmony_ci        std::string faultName = GetFaultNameByType(faultType, false);
140020a203aSopenharmony_ci        std::vector<std::vector<std::string>> faultNames = { {faultName} };
141020a203aSopenharmony_ci        if (faultType == FaultLogType::ALL) {
142020a203aSopenharmony_ci            faultNames = { {"CPP_CRASH"}, {"APP_FREEZE"}};
143020a203aSopenharmony_ci        }
144020a203aSopenharmony_ci        for (auto name : faultNames) {
145020a203aSopenharmony_ci            auto query = EventStore::SysEventDao::BuildQuery(HiSysEvent::Domain::RELIABILITY, name);
146020a203aSopenharmony_ci            if (query == nullptr) {
147020a203aSopenharmony_ci                continue;
148020a203aSopenharmony_ci            }
149020a203aSopenharmony_ci            query->And(upperCaseCond);
150020a203aSopenharmony_ci            query->Select(QUERY_ITEMS).Order("time_", false);
151020a203aSopenharmony_ci            queries.push_back(query);
152020a203aSopenharmony_ci        }
153020a203aSopenharmony_ci    }
154020a203aSopenharmony_ci    return queries;
155020a203aSopenharmony_ci}
156020a203aSopenharmony_ci
157020a203aSopenharmony_cistd::list<FaultLogInfo> FaultLogDatabase::GetFaultInfoList(const std::string& module, int32_t id,
158020a203aSopenharmony_ci    int32_t faultType, int32_t maxNum)
159020a203aSopenharmony_ci{
160020a203aSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
161020a203aSopenharmony_ci    std::list<FaultLogInfo> queryResult;
162020a203aSopenharmony_ci    if (faultType < FaultLogType::ALL || faultType > FaultLogType::APP_FREEZE) {
163020a203aSopenharmony_ci        HIVIEW_LOGE("Unsupported fault type, please check it!");
164020a203aSopenharmony_ci        return queryResult;
165020a203aSopenharmony_ci    }
166020a203aSopenharmony_ci    EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
167020a203aSopenharmony_ci    EventStore::Cond uidUpperCond = hiviewUidCond.And("UID", EventStore::Op::EQ, id);
168020a203aSopenharmony_ci    EventStore::Cond uidLowerCond("uid_", EventStore::Op::EQ, id);
169020a203aSopenharmony_ci    auto queries = CreateQueries(faultType, uidUpperCond, uidLowerCond);
170020a203aSopenharmony_ci    for (auto query : queries) {
171020a203aSopenharmony_ci        if (id != 0) {
172020a203aSopenharmony_ci            query->And("MODULE", EventStore::Op::EQ, module);
173020a203aSopenharmony_ci        }
174020a203aSopenharmony_ci        EventStore::ResultSet resultSet = query->Execute(maxNum);
175020a203aSopenharmony_ci        while (resultSet.HasNext()) {
176020a203aSopenharmony_ci            auto it = resultSet.Next();
177020a203aSopenharmony_ci            FaultLogInfo info;
178020a203aSopenharmony_ci            if (!ParseFaultLogInfoFromJson(it->rawData_, info)) {
179020a203aSopenharmony_ci                HIVIEW_LOGI("Failed to parse FaultLogInfo from queryResult.");
180020a203aSopenharmony_ci                continue;
181020a203aSopenharmony_ci            }
182020a203aSopenharmony_ci            queryResult.push_back(info);
183020a203aSopenharmony_ci        }
184020a203aSopenharmony_ci    }
185020a203aSopenharmony_ci    if (queries.size() > 1) {
186020a203aSopenharmony_ci        queryResult.sort(
187020a203aSopenharmony_ci            [](const FaultLogInfo& a, const FaultLogInfo& b) {
188020a203aSopenharmony_ci            return a.time > b.time;
189020a203aSopenharmony_ci        });
190020a203aSopenharmony_ci        if (queryResult.size() > static_cast<size_t>(maxNum)) {
191020a203aSopenharmony_ci            queryResult.resize(maxNum);
192020a203aSopenharmony_ci        }
193020a203aSopenharmony_ci    }
194020a203aSopenharmony_ci
195020a203aSopenharmony_ci    return queryResult;
196020a203aSopenharmony_ci}
197020a203aSopenharmony_ci
198020a203aSopenharmony_cibool FaultLogDatabase::IsFaultExist(int32_t pid, int32_t uid, int32_t faultType)
199020a203aSopenharmony_ci{
200020a203aSopenharmony_ci    std::lock_guard<std::mutex> lock(mutex_);
201020a203aSopenharmony_ci    if (faultType < FaultLogType::ALL || faultType > FaultLogType::RUST_PANIC) {
202020a203aSopenharmony_ci        HIVIEW_LOGE("Unsupported fault type, please check it!");
203020a203aSopenharmony_ci        return false;
204020a203aSopenharmony_ci    }
205020a203aSopenharmony_ci    EventStore::Cond hiviewUidCond("uid_", EventStore::Op::EQ, static_cast<int64_t>(getuid()));
206020a203aSopenharmony_ci    EventStore::Cond pidUpperCond = hiviewUidCond.And("PID", EventStore::Op::EQ, pid).
207020a203aSopenharmony_ci        And("UID", EventStore::Op::EQ, uid);
208020a203aSopenharmony_ci    EventStore::Cond pidLowerCond("pid_", EventStore::Op::EQ, pid);
209020a203aSopenharmony_ci    pidLowerCond = pidLowerCond.And("uid_", EventStore::Op::EQ, uid);
210020a203aSopenharmony_ci    auto queries = CreateQueries(faultType, pidUpperCond, pidLowerCond);
211020a203aSopenharmony_ci    for (auto query : queries) {
212020a203aSopenharmony_ci        if (query->Execute(1).HasNext()) {
213020a203aSopenharmony_ci            return true;
214020a203aSopenharmony_ci        }
215020a203aSopenharmony_ci    }
216020a203aSopenharmony_ci    return false;
217020a203aSopenharmony_ci}
218020a203aSopenharmony_ci}  // namespace HiviewDFX
219020a203aSopenharmony_ci}  // namespace OHOS
220