• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 
16 #include "running_status_logger.h"
17 
18 #include <algorithm>
19 #include <cerrno>
20 #include <chrono>
21 #include <vector>
22 
23 #include "file_util.h"
24 #include "hiview_global.h"
25 #include "logger.h"
26 #include "time_util.h"
27 
28 namespace OHOS {
29 namespace HiviewDFX {
30 DEFINE_LOG_TAG("HiView-RunningStatusLogger");
31 namespace {
32 constexpr size_t BUF_SIZE = 2000;
33 char errMsg[BUF_SIZE] = { 0 };
34 }
35 
Log(const std::string & logInfo)36 void RunningStatusLogger::Log(const std::string& logInfo)
37 {
38     {
39         std::lock_guard<std::mutex> lock(writingMutex);
40         logWritingTasks.emplace(logInfo, [this] (const std::string& logInfo) {
41             std::string destFile = this->GetLogWroteDestFile(logInfo);
42             HIVIEW_LOGD("writing \"%{public}s\" into %{public}s.", logInfo.c_str(), destFile.c_str());
43             if (!FileUtil::SaveStringToFile(destFile, logInfo + "\n", false)) {
44                 strerror_r(errno, errMsg, BUF_SIZE);
45                 HIVIEW_LOGE("failed to persist log to file, error=%{public}d, msg=%{public}s",
46                     errno, errMsg);
47             }
48             this->ImmediateWrite(true);
49         });
50         if (inWriting.load(std::memory_order_acquire)) {
51             return;
52         }
53     }
54     ImmediateWrite();
55 }
56 
FormatTimeStamp(bool simpleMode)57 std::string RunningStatusLogger::FormatTimeStamp(bool simpleMode)
58 {
59     time_t lt;
60     (void)time(&lt);
61     std::string format { simpleMode ? "%Y%m%d" : "%Y/%m/%d %H:%M:%S" };
62     return TimeUtil::TimestampFormatToDate(lt, format);
63 }
64 
GenerateNewestFileName(const std::string & suffix)65 std::string RunningStatusLogger::GenerateNewestFileName(const std::string& suffix)
66 {
67     std::string newFileName = GetLogDir() + "runningstatus_" + FormatTimeStamp(true) + suffix;
68     HIVIEW_LOGD("create new log file: %{public}s.", newFileName.c_str());
69     return newFileName;
70 }
71 
GetLogDir()72 std::string RunningStatusLogger::GetLogDir()
73 {
74     std::string workPath = HiviewGlobal::GetInstance()->GetHiViewDirectory(
75         HiviewContext::DirectoryType::WORK_DIRECTORY);
76     if (workPath.back() != '/') {
77         workPath = workPath + "/";
78     }
79     std::string logDestDir = workPath + "sys_event/";
80     if (!FileUtil::FileExists(logDestDir)) {
81         if (FileUtil::ForceCreateDirectory(logDestDir, FileUtil::FILE_PERM_770)) {
82             HIVIEW_LOGD("create listener log directory %{public}s succeed.", logDestDir.c_str());
83         } else {
84             logDestDir = workPath;
85             HIVIEW_LOGW("create listener log directory %{public}s failed, use default directory %{public}s.",
86                 logDestDir.c_str(), workPath.c_str());
87         }
88     }
89     return logDestDir;
90 }
91 
GetLogWroteDestFile(const std::string & content)92 std::string RunningStatusLogger::GetLogWroteDestFile(const std::string& content)
93 {
94     std::vector<std::string> allLogFiles;
95     FileUtil::GetDirFiles(GetLogDir(), allLogFiles);
96     if (allLogFiles.empty()) {
97         return GenerateNewestFileName("_01");
98     }
99     sort(allLogFiles.begin(), allLogFiles.end());
100     std::vector<std::string>::size_type logFileCntLimit = 10; // max count of log file exist is limited to be 10
101     if (allLogFiles.back().find(FormatTimeStamp(true)) == std::string::npos) {
102         if ((allLogFiles.size() == logFileCntLimit) && !FileUtil::RemoveFile(allLogFiles.front())) {
103             strerror_r(errno, errMsg, BUF_SIZE);
104             HIVIEW_LOGE("failed to delete oldest log file, error=%{public}d, msg=%{public}s",
105                 errno, errMsg);
106         }
107         return GenerateNewestFileName("_01");
108     }
109     std::uintmax_t singleLogFileSizeLimit = 2 * 1024 * 1024; // size of each log file is limited to 2M
110     if (FileUtil::GetFileSize(allLogFiles.back()) + content.size() < singleLogFileSizeLimit) {
111         return allLogFiles.back();
112     }
113     std::string newestFileName = allLogFiles.back();
114     auto lastUnderLinePos = newestFileName.find_last_of("_");
115     int index = 0;
116     int decimal = 10;
117     while (++lastUnderLinePos < newestFileName.size()) {
118         index *= decimal;
119         index += static_cast<int>(newestFileName.at(lastUnderLinePos) - '0');
120     }
121     index += 1;
122     if ((allLogFiles.size() == logFileCntLimit) && !FileUtil::RemoveFile(allLogFiles.front())) {
123         strerror_r(errno, errMsg, BUF_SIZE);
124         HIVIEW_LOGE("failed to delete oldest log file, error=%{public}d, msg=%{public}s",
125             errno, errMsg);
126     }
127     return GenerateNewestFileName(std::string(((index < decimal) ? "_0" : "_")).append(std::to_string(index)));
128 }
129 
ImmediateWrite(bool needPop)130 void RunningStatusLogger::ImmediateWrite(bool needPop)
131 {
132     this->inWriting = true;
133     LogWritingTask curTask;
134     {
135         std::lock_guard<std::mutex> lock(writingMutex);
136         if (needPop && !logWritingTasks.empty()) {
137             logWritingTasks.pop();
138         }
139         if (logWritingTasks.empty()) {
140             this->inWriting = false;
141             return;
142         }
143         curTask = logWritingTasks.front();
144     }
145     curTask.second(curTask.first);
146 }
147 } // namespace HiviewDFX
148 } // namespace OHOS