• 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 "dfx_log_dump.h"
17 #include <fstream>
18 #include <unistd.h>
19 #include <sys/time.h>
20 #include "securec.h"
21 
22 namespace {
23 constexpr int32_t FILE_MAX = 100;
24 constexpr int32_t FILE_LINE_MAX = 50000;
25 }
26 namespace OHOS {
27 namespace Media {
GetInstance()28 DfxLogDump &DfxLogDump::GetInstance()
29 {
30     static DfxLogDump dfxLogDump;
31     return dfxLogDump;
32 }
33 
DfxLogDump()34 DfxLogDump::DfxLogDump()
35 {
36     thread_ = std::make_unique<std::thread>(&DfxLogDump::TaskProcessor, this);
37 }
38 
~DfxLogDump()39 DfxLogDump::~DfxLogDump()
40 {
41     {
42         std::unique_lock<std::mutex> lock(mutex_);
43         isExit_ = true;
44         cond_.notify_all();
45     }
46     if (thread_ != nullptr && thread_->joinable()) {
47         thread_->join();
48     }
49 }
50 
AddNewLog(const char * level,const OHOS::HiviewDFX::HiLogLabel & label,std::string & logStr)51 static void AddNewLog(const char *level, const OHOS::HiviewDFX::HiLogLabel &label, std::string &logStr)
52 {
53     struct timeval time = {};
54     (void)gettimeofday(&time, nullptr);
55     int64_t second = time.tv_sec % 60;
56     int64_t allMinute = time.tv_sec / 60;
57     int64_t minute = allMinute % 60;
58     int64_t hour = allMinute / 60 % 24;
59     int64_t mSecond = time.tv_usec / 1000;
60 
61     logStr += std::to_string(hour);
62     logStr += ":";
63     logStr += std::to_string(minute);
64     logStr += ":";
65     logStr += std::to_string(second);
66     logStr += ":";
67     logStr += std::to_string(mSecond);
68     logStr += " ";
69     logStr += level;
70     logStr += " pid:";
71     logStr += std::to_string(getpid());
72     logStr += " tid:";
73     logStr += std::to_string(gettid());
74     logStr += " ";
75     logStr += label.tag;
76     logStr += ":";
77 }
78 
SaveLog(const char * level,const OHOS::HiviewDFX::HiLogLabel & label,const char * fmt,...)79 void DfxLogDump::SaveLog(const char *level, const OHOS::HiviewDFX::HiLogLabel &label, const char *fmt, ...)
80 {
81     std::unique_lock<std::mutex> lock(mutex_);
82     if (!isEnable_) {
83         return;
84     }
85     std::string temp = "";
86     std::string fmtStr = fmt;
87     int32_t srcPos = 0;
88     auto dtsPos = fmtStr.find("{public}", srcPos);
89     const int32_t pubLen = 8;
90     while (dtsPos != std::string::npos) {
91         temp += fmtStr.substr(srcPos, dtsPos - srcPos);
92         srcPos = static_cast<int32_t>(dtsPos) + pubLen;
93         dtsPos = fmtStr.find("{public}", srcPos);
94     }
95     temp += fmtStr.substr(srcPos);
96 
97     va_list ap;
98     va_start(ap, fmt);
99     constexpr uint8_t maxLogLen = 255;
100     char logBuf[maxLogLen];
101     auto ret = vsnprintf_s(logBuf, maxLogLen, maxLogLen - 1, temp.c_str(), ap);
102     va_end(ap);
103 
104     AddNewLog(level, label, logString_);
105     if (ret < 0) {
106         logString_ += "dump log error";
107     } else {
108         logString_ += logBuf;
109     }
110     logString_ += "\n";
111     lineCount_++;
112     if (lineCount_ >= FILE_LINE_MAX) {
113         cond_.notify_all();
114     }
115 }
116 
UpdateCheckEnable()117 void DfxLogDump::UpdateCheckEnable()
118 {
119     std::string file = "/data/media/log/check.config";
120     std::ofstream ofStream(file);
121     if (!ofStream.is_open()) {
122         isEnable_ = false;
123         return;
124     }
125     ofStream.close();
126     isEnable_ = true;
127 }
128 
TaskProcessor()129 void DfxLogDump::TaskProcessor()
130 {
131     while (true) {
132         std::string temp;
133         int32_t lineCount = 0;
134         {
135             std::unique_lock<std::mutex> lock(mutex_);
136             if (isExit_) {
137                 return;
138             }
139             static constexpr int32_t timeout = 60; // every 1 minute have a log
140             cond_.wait_for(lock, std::chrono::seconds(timeout),
141                 [this] {
142                     UpdateCheckEnable();
143                     return isExit_ || isDump_ || lineCount_ >= FILE_LINE_MAX || !logString_.empty();
144             });
145             isDump_ = false;
146             lineCount = lineCount_;
147             lineCount_ = lineCount_ >= FILE_LINE_MAX ? 0 : lineCount_;
148             swap(logString_, temp);
149         }
150 
151         std::string file = "/data/media/log/";
152         file += std::to_string(getpid());
153         file += "_hilog_media.log";
154         file += std::to_string(fileCount_);
155         std::ofstream ofStream;
156         if (isNewFile_) {
157             ofStream.open(file, std::ios::out | std::ios::trunc);
158         } else {
159             ofStream.open(file, std::ios::out | std::ios::app);
160         }
161         if (!ofStream.is_open()) {
162             continue;
163         }
164         isNewFile_ = false;
165         if (lineCount >= FILE_LINE_MAX) {
166             isNewFile_ = true;
167             fileCount_++;
168             fileCount_ = fileCount_ > FILE_MAX ? 0 : fileCount_;
169         }
170         ofStream.write(temp.c_str(), temp.size());
171         ofStream.close();
172     }
173 }
174 } // namespace Media
175 } // namespace OHOS