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