• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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_manager.h"
16 
17 #include <cstdint>
18 #include <memory>
19 #include <mutex>
20 #include <string>
21 #include <vector>
22 
23 #include <fcntl.h>
24 #include <filesystem>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
28 
29 #include "defines.h"
30 #include "file_util.h"
31 #include "log_store_ex.h"
32 #include "hiview_logger.h"
33 #include "time_util.h"
34 
35 #include "faultlog_database.h"
36 #include "faultlog_formatter.h"
37 #include "faultlog_info.h"
38 #include "faultlog_util.h"
39 
40 namespace OHOS {
41 namespace HiviewDFX {
42 namespace {
43 constexpr char DEFAULT_FAULTLOG_FOLDER[] = "/data/log/faultlog/faultlogger/";
44 constexpr int32_t MAX_FAULT_LOG_PER_HAP = 10;
45 }
46 
47 DEFINE_LOG_LABEL(0xD002D11, "FaultLogManager");
CreateLogFileFilter(time_t time,int32_t id,int32_t faultLogType,const std::string & module)48 LogStoreEx::LogFileFilter CreateLogFileFilter(time_t time, int32_t id, int32_t faultLogType, const std::string& module)
49 {
50     LogStoreEx::LogFileFilter filter = [time, id, faultLogType, module](const LogFile &file) {
51         FaultLogInfo info = ExtractInfoFromFileName(file.name_);
52         if (info.time <= time) {
53             return false;
54         }
55 
56         if ((id != -1) && (info.id != id)) {
57             return false;
58         }
59 
60         if ((faultLogType != 0) && (info.faultLogType != faultLogType)) {
61             return false;
62         }
63 
64         if ((!module.empty()) && (info.module != module)) {
65             return false;
66         }
67         return true;
68     };
69     return filter;
70 }
71 
~FaultLogManager()72 FaultLogManager::~FaultLogManager()
73 {
74     if (faultLogDb_ != nullptr) {
75         delete faultLogDb_;
76         faultLogDb_ = nullptr;
77     }
78 }
79 
CreateTempFaultLogFile(time_t time,int32_t id,int32_t faultType,const std::string & module) const80 int32_t FaultLogManager::CreateTempFaultLogFile(time_t time, int32_t id, int32_t faultType,
81     const std::string &module) const
82 {
83     FaultLogInfo info;
84     info.time = time;
85     info.id = id;
86     info.faultLogType = faultType;
87     info.module = module;
88     auto fileName = GetFaultLogName(info);
89     return store_->CreateLogFile(fileName);
90 }
91 
Init()92 void FaultLogManager::Init()
93 {
94     store_ = std::make_unique<LogStoreEx>(DEFAULT_FAULTLOG_FOLDER, true);
95     LogStoreEx::LogFileComparator comparator = [](const LogFile &lhs, const LogFile &rhs) {
96         FaultLogInfo lhsInfo = ExtractInfoFromFileName(lhs.name_);
97         FaultLogInfo rhsInfo = ExtractInfoFromFileName(rhs.name_);
98         return lhsInfo.time > rhsInfo.time;
99     };
100     store_->SetLogFileComparator(comparator);
101     store_->Init();
102     faultLogDb_ = new FaultLogDatabase(looper_);
103 }
104 
SaveFaultLogToFile(FaultLogInfo & info) const105 std::string FaultLogManager::SaveFaultLogToFile(FaultLogInfo &info) const
106 {
107     auto fileName = GetFaultLogName(info);
108     std::string filePath = std::string(DEFAULT_FAULTLOG_FOLDER) + fileName;
109     if (FileUtil::FileExists(filePath)) {
110         HIVIEW_LOGI("logfile %{public}s already exist.", filePath.c_str());
111         return "";
112     }
113     auto fd = store_->CreateLogFile(fileName);
114     if (fd < 0) {
115         if (access(DEFAULT_FAULTLOG_FOLDER, F_OK) != 0) {
116             HIVIEW_LOGE("%{public}s does not exist!!!", DEFAULT_FAULTLOG_FOLDER);
117         }
118         return "";
119     }
120 
121     FaultLogger::WriteDfxLogToFile(fd);
122     FaultLogger::WriteFaultLogToFile(fd, info.faultLogType, info.sectionMap);
123     FaultLogger::WriteLogToFile(fd, info.logPath);
124     if (info.sectionMap.count("HILOG") == 1) {
125         FileUtil::SaveStringToFd(fd, "\nHiLog:\n");
126         FileUtil::SaveStringToFd(fd, info.sectionMap["HILOG"]);
127     }
128     FaultLogger::LimitCppCrashLog(fd, info.faultLogType);
129     close(fd);
130 
131     std::string logFile = info.logPath;
132     if (logFile != "" && FileUtil::FileExists(logFile)) {
133         if (!FileUtil::RemoveFile(logFile)) {
134             HIVIEW_LOGW("remove logFile %{public}s failed.", logFile.c_str());
135         } else {
136             HIVIEW_LOGI("remove logFile %{public}s.", logFile.c_str());
137         }
138     }
139     store_->ClearSameLogFilesIfNeeded(CreateLogFileFilter(0, info.id, info.faultLogType, info.module),
140         MAX_FAULT_LOG_PER_HAP);
141     info.logPath = std::string(DEFAULT_FAULTLOG_FOLDER) + fileName;
142     HIVIEW_LOGI("create log %{public}s", fileName.c_str());
143     return fileName;
144 }
145 
GetFaultInfoList(const std::string & module,int32_t id,int32_t faultType,int32_t maxNum) const146 std::list<FaultLogInfo> FaultLogManager::GetFaultInfoList(const std::string& module,
147     int32_t id, int32_t faultType, int32_t maxNum) const
148 {
149     std::list<FaultLogInfo> ret;
150     if (faultLogDb_ != nullptr) {
151         ret = faultLogDb_->GetFaultInfoList(module, id, faultType, maxNum);
152         HIVIEW_LOGI("Find %{public}zu fault records for uid:%{public}d type:%{public}d",
153             ret.size(), id, faultType);
154     }
155     return ret;
156 }
157 
SaveFaultInfoToRawDb(FaultLogInfo & info) const158 void FaultLogManager::SaveFaultInfoToRawDb(FaultLogInfo& info) const
159 {
160     if (faultLogDb_ != nullptr) {
161         faultLogDb_->SaveFaultLogInfo(info);
162     }
163 }
164 
ReduceLogFileListSize(std::list<std::string> & infoVec,int32_t maxNum) const165 void FaultLogManager::ReduceLogFileListSize(std::list<std::string> &infoVec, int32_t maxNum) const
166 {
167     if ((maxNum < 0) || (infoVec.size() <= static_cast<uint32_t>(maxNum))) {
168         return;
169     }
170 
171     auto begin = infoVec.begin();
172     std::advance(begin, maxNum);
173     infoVec.erase(begin, infoVec.end());
174 }
175 
GetFaultLogFileList(const std::string & module,time_t time,int32_t id,int32_t faultType,int32_t maxNum) const176 std::list<std::string> FaultLogManager::GetFaultLogFileList(const std::string &module, time_t time, int32_t id,
177                                                             int32_t faultType, int32_t maxNum) const
178 {
179     LogStoreEx::LogFileFilter filter = CreateLogFileFilter(time, id, faultType, module);
180     auto vec = store_->GetLogFiles(filter);
181     std::list<std::string> ret;
182     std::transform(vec.begin(), vec.end(), std::back_inserter(ret), [](const LogFile &file) { return file.path_; });
183     ReduceLogFileListSize(ret, maxNum);
184     return ret;
185 }
186 
GetFaultLogContent(const std::string & name,std::string & content) const187 bool FaultLogManager::GetFaultLogContent(const std::string &name, std::string &content) const
188 {
189     auto path = std::string(DEFAULT_FAULTLOG_FOLDER);
190     std::string matchName;
191     for (const auto& entry : std::filesystem::directory_iterator(path)) {
192         std::filesystem::path filePath = entry.path();
193         std::string fileName = filePath.filename().string();
194         if (fileName.find(name) != std::string::npos && matchName.compare(fileName) < 0) {
195             matchName = fileName;
196             continue;
197         }
198     }
199     if (matchName.empty()) {
200         return false;
201     }
202     path = path + matchName;
203     return FileUtil::LoadStringFromFile(path, content);
204 }
205 
IsProcessedFault(int32_t pid,int32_t uid,int32_t faultType)206 bool FaultLogManager::IsProcessedFault(int32_t pid, int32_t uid, int32_t faultType)
207 {
208     if (faultLogDb_ == nullptr) {
209         return false;
210     }
211 
212     return faultLogDb_->IsFaultExist(pid, uid, faultType);
213 }
214 } // namespace HiviewDFX
215 } // namespace OHOS
216