1 // Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
2 // Use of this source code is governed by a apache 2.0 license that can be
3 // found in the LICENSE file.
5 #include "common/utils/file_logbackend.h"
7 #include <manifest_parser/utils/logging.h>
10 #include <sys/types.h>
21 constexpr mode_t kDefaultMode640 = S_IRUSR | S_IWUSR | S_IRGRP;
27 FileLogBackend::FileLogBackend(std::string file_path, int rotation_size,
29 : file_path_(std::move(file_path)), rotation_size_(rotation_size),
30 max_rotation_(max_rotation), log_stream_(
31 std::unique_ptr<std::ostringstream>(new std::ostringstream())) {
35 void FileLogBackend::WriteLog(LogLevel level, const std::string& /* tag */,
36 const std::string& logstr) {
37 if (level != LogLevel::LOG_DEBUG)
38 *log_stream_ << GetTimeStamp() << GetPid() << logstr << std::endl;
41 void FileLogBackend::WriteLogToFile() {
42 if (file_path_.empty())
45 int size = GetFileSize(file_path_);
46 if (size > rotation_size_)
50 std::ofstream ofs(file_path_.c_str(), std::ios::app);
51 ofs << log_stream_->str();
54 // clean the log stream
58 if (chmod(file_path_.c_str(), kDefaultMode640) != 0)
59 LOG(ERROR) << "Failed to set permission on log, errno : " << errno;
62 bool FileLogBackend::Rotate() {
63 std::string logdir = GetLogDir();
64 int dirfd = open(logdir.c_str(), O_DIRECTORY);
65 for (int i = max_rotation_; i > 0; i--) {
66 std::string old_log = GetFileName() + "." + std::to_string(i);
69 LOG(ERROR) << "Failed to open dir(" << logdir << "), errno : " << errno;
72 struct stat tmp_buffer;
73 if (fstatat(dirfd, old_log.c_str(), &tmp_buffer, 0) != 0)
76 // the oldest log will be removed
77 if (i == max_rotation_) {
78 if (unlinkat(dirfd, old_log.c_str(), 0) != 0) {
83 std::string new_log = GetFileName() + "." + std::to_string(i + 1);
84 if (renameat(dirfd, old_log.c_str(), dirfd, new_log.c_str()) != 0) {
90 std::string new_log = GetFileName() + ".1";
91 if (renameat(dirfd, file_path_.c_str(), dirfd, new_log.c_str()) != 0) {
100 int FileLogBackend::GetFileSize(const std::string& file_name) {
102 int ret = stat(file_name.c_str(), &sb);
103 return ret == 0 ? sb.st_size : -1;
106 std::string FileLogBackend::GetTimeStamp() {
108 clock_gettime(CLOCK_REALTIME, &ts);
110 time_t seconds = ts.tv_sec;
112 if (!gmtime_r(&seconds, &gmt))
114 int32_t miliseconds = ts.tv_nsec / 1000000;
117 strftime(buf, sizeof(buf), "%Y%m%d.%H%M%S", &gmt);
119 snprintf(timestamp, sizeof(timestamp), "%s.%03dUTC|", buf, miliseconds);
124 std::string FileLogBackend::GetPid() {
125 return std::to_string(getpid()) + "|";
128 std::string FileLogBackend::GetLogDir() {
129 return file_path_.substr(0, file_path_.find_last_of("\\/") + 1);
132 std::string FileLogBackend::GetFileName() {
133 return file_path_.substr(file_path_.find_last_of("\\/") + 1);