* Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "hhlog.h"
static constexpr int FILE_MODE = 0644;
HHLogger::~HHLogger()
{
stop_.store(true);
if (logSaver_.joinable()) {
logSaver_.join();
}
if (fd_ >= 0) {
close(fd_);
}
}
int HHLogger::InitLogger(const int logLevel, const std::string& logFile)
{
logLevel_ = logLevel;
if (UpdateTimer() != 0) {
return -1;
}
constexpr enum RingBuffer::MemAlignShift memAlign {RingBuffer::MemAlignShift::W_ALIGN_SHIFT};
buf_.reset(new RingBuffer {SizeConsts::RING_BUF_SIZE, memAlign});
if (buf_ == nullptr or (not (*buf_))) {
return -1;
}
if (logFile.compare("stdout") == 0) {
if (fcntl(STDOUT_FILENO, F_GETFL) != 0) {
fd_ = open("/dev/stdout", O_WRONLY);
} else {
fd_ = STDOUT_FILENO;
}
if (fd_ < 0) {
return -1;
}
return 0;
}
auto fileName = GetLogFileName();
if (fileName.length() == 0) {
return -1;
}
fd_ = open(fileName.c_str(), O_WRONLY | O_CREAT, FILE_MODE);
if (fd_ < 0) {
return -1;
}
unlink(logFile.c_str());
if (link(fileName.c_str(), logFile.c_str()) != 0) {
return -1;
}
return 0;
}
int HHLogger::Start(const int logLevel, const std::string& logFile)
{
if (logLevel == HHLOG_NONE) {
HHLOGD(true, "hhlog level is NONE!");
return 0;
}
#if defined(HH_LOGGER_DEBUG) || defined(HH_LOGGER_INFO) || defined(HH_LOGGER_WARN) || \
defined(HH_LOGGER_ERROR) || defined(HH_LOGGER_FATAL)
if (InitLogger(logLevel, logFile) != 0) {
return -1;
}
#endif
return 0;
}
std::string HHLogger::GetLogFileName() const
{
auto timer = timer_.load();
time_t now = (time_t) timer.tv_sec;
struct tm* tmPtr {nullptr};
tmPtr = localtime(&now);
if (tmPtr == nullptr) {
return "";
}
std::stringstream ss;
constexpr int yearStart {1900};
constexpr int monthStart {1};
ss << "/data/local/tmp/";
ss << std::to_string(tmPtr->tm_year + yearStart) << ".";
ss << std::to_string(tmPtr->tm_mon + monthStart) << ".";
ss << std::to_string(tmPtr->tm_mday) << "_";
ss << std::to_string(tmPtr->tm_hour) << ".";
ss << std::to_string(tmPtr->tm_min) << ".";
ss << std::to_string(tmPtr->tm_sec) << ".hhlog";
return ss.str();
}
std::string HHLogger::GetFormatTime() const
{
auto timer = timer_.load();
time_t now = (time_t) timer.tv_sec;
struct tm* tmPtr {nullptr};
tmPtr = localtime(&now);
if (tmPtr == nullptr) {
return "";
}
std::stringstream ss;
constexpr int yearStart {1900};
constexpr int monthStart {1};
ss << std::to_string(tmPtr->tm_year + yearStart) << "-";
ss << std::to_string(tmPtr->tm_mon + monthStart) << "-";
ss << std::to_string(tmPtr->tm_mday) << " ";
ss << std::to_string(tmPtr->tm_hour) << ":";
ss << std::to_string(tmPtr->tm_min) << ":";
ss << std::to_string(tmPtr->tm_sec);
return ss.str();
}
int HHLogger::UpdateTimer()
{
struct timeval timer;
int ret = gettimeofday(&timer, nullptr);
if (ret != 0) {
return -1;
}
timer_.store(timer);
return 0;
}
int HHLogger::SaveLog()
{
while (true) {
if (UpdateTimer() != 0) {
return -1;
}
auto dataSize = buf_->GetDataSize();
if (stop_.load() and (dataSize == 0)) {
return 0;
}
if (dataSize) {
ssize_t ret = buf_->Write(fd_, dataSize);
if (ret <= 0) {
stop_.store(true);
return -1;
}
}
}
return 0;
}