• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 "log_print.h"
17 
18 #include <atomic>
19 #include <cstdarg>
20 #include <cstdio>
21 #include <mutex>
22 
23 #include "securec.h"
24 #include "platform_specific.h"
25 #include "hilog/log.h"
26 
27 namespace DistributedDB {
28 Logger *Logger::logHandler = nullptr;
29 const std::string Logger::PRIVATE_TAG = "s{private}";
30 
31 class HiLogger : public Logger {
32 public:
Print(Level level,const std::string & tag,const std::string & msg)33     void Print(Level level, const std::string &tag, const std::string &msg) override
34     {
35         if (msg.empty()) {
36             return;
37         }
38         const std::string format = "%{public}s";
39         OHOS::HiviewDFX::HiLogLabel label = { LOG_CORE, 0xD001630, tag.c_str() }; // log module id.
40         switch (level) {
41             case Level::LEVEL_DEBUG:
42                 (void)OHOS::HiviewDFX::HiLog::Debug(label, format.c_str(), msg.c_str());
43                 break;
44             case Level::LEVEL_INFO:
45                 (void)OHOS::HiviewDFX::HiLog::Info(label, format.c_str(), msg.c_str());
46                 break;
47             case Level::LEVEL_WARN:
48                 (void)OHOS::HiviewDFX::HiLog::Warn(label, format.c_str(), msg.c_str());
49                 break;
50             case Level::LEVEL_ERROR:
51                 (void)OHOS::HiviewDFX::HiLog::Error(label, format.c_str(), msg.c_str());
52                 break;
53             case Level::LEVEL_FATAL:
54                 (void)OHOS::HiviewDFX::HiLog::Fatal(label, format.c_str(), msg.c_str());
55                 break;
56             default:
57                 break;
58         }
59     }
60 };
61 
GetInstance()62 Logger *Logger::GetInstance()
63 {
64     static std::mutex logInstanceLock;
65     static std::atomic<Logger *> logInstance = nullptr;
66     // For Double-Checked Locking, we need check logInstance twice
67     if (logInstance == nullptr) {
68         std::lock_guard<std::mutex> lock(logInstanceLock);
69         if (logInstance == nullptr) {
70             // Here, we new logInstance to print log, if new failed, we can do nothing.
71             logInstance = new (std::nothrow) HiLogger;
72         }
73     }
74     return logInstance;
75 }
76 
RegisterLogger(Logger * logger)77 void Logger::RegisterLogger(Logger *logger)
78 {
79     static std::mutex logHandlerLock;
80     if (logger == nullptr) {
81         return;
82     }
83     if (logHandler == nullptr) {
84         std::lock_guard<std::mutex> lock(logHandlerLock);
85         if (logHandler == nullptr) {
86             logHandler = logger;
87         }
88     }
89 }
90 
Log(Level level,const std::string & tag,const char * func,int line,const char * format,...)91 void Logger::Log(Level level, const std::string &tag, const char *func, int line, const char *format, ...)
92 {
93     (void)func;
94     (void)line;
95     if (format == nullptr) {
96         return;
97     }
98 
99     static const int maxLogLength = 1024;
100     va_list argList;
101     va_start(argList, format);
102     char logBuff[maxLogLength];
103     std::string msg;
104     std::string formatTemp;
105     PreparePrivateLog(format, formatTemp);
106     int bytes = vsnprintf_s(logBuff, maxLogLength, maxLogLength - 1, formatTemp.c_str(), argList);
107     if (bytes < 0) {
108         msg = "log buffer overflow!";
109     } else {
110         msg = logBuff;
111     }
112     va_end(argList);
113     if (logHandler != nullptr) {
114         logHandler->Print(level, tag, msg);
115         return;
116     }
117 
118     Logger::RegisterLogger(Logger::GetInstance());
119     if (logHandler != nullptr) {
120         logHandler->Print(level, tag, msg);
121     }
122 }
123 
PreparePrivateLog(const char * format,std::string & outStrFormat)124 void Logger::PreparePrivateLog(const char *format, std::string &outStrFormat)
125 {
126     outStrFormat = format;
127     std::string::size_type pos = outStrFormat.find(PRIVATE_TAG);
128     if (pos != std::string::npos) {
129         outStrFormat.replace(pos, PRIVATE_TAG.size(), ".3s");
130     }
131 }
132 } // namespace DistributedDB
133