0676f889abe50f448ccfd69163fd030700e4626f
[platform/core/appfw/app-installers.git] / src / common / utils / file_logbackend.cc
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.
4
5 #include "common/utils/file_logbackend.h"
6
7 #include <manifest_parser/utils/logging.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
11
12 #include <fstream>
13 #include <memory>
14 #include <sstream>
15 #include <string>
16 #include <utility>
17
18 namespace {
19
20 constexpr mode_t kDefaultMode640 = S_IRUSR | S_IWUSR | S_IRGRP;
21
22 }  // namespace
23
24 namespace utils {
25
26 FileLogBackend::FileLogBackend(std::string file_name, int rotation_size,
27     int max_rotation)
28     : file_name_(std::move(file_name)), rotation_size_(rotation_size),
29       max_rotation_(max_rotation), log_stream_(
30           std::unique_ptr<std::ostringstream>(new std::ostringstream())) {
31 }
32
33
34 void FileLogBackend::WriteLog(LogLevel level, const std::string& /* tag */,
35     const std::string& logstr) {
36   if (level != LogLevel::LOG_DEBUG)
37     *log_stream_ << GetTimeStamp() << GetPid() << logstr << std::endl;
38 }
39
40 void FileLogBackend::WriteLogToFile() {
41   if (file_name_.empty())
42     return;
43
44   int size = GetFileSize(file_name_);
45   if (size > rotation_size_)
46     if (!Rotate())
47       return;
48
49   std::ofstream ofs(file_name_.c_str(), std::ios::app);
50   ofs << log_stream_->str();
51   ofs.close();
52
53   // clean the log stream
54   log_stream_->str("");
55   log_stream_->clear();
56
57   if (chmod(file_name_.c_str(), kDefaultMode640) != 0)
58     LOG(ERROR) << "Failed to set permission on log, errno : " << errno;
59 }
60
61 bool FileLogBackend::Rotate() {
62   for (int i = max_rotation_; i > 0; i--) {
63     std::string old_log = file_name_ + "." + std::to_string(i);
64
65     struct stat tmp_buffer;
66     if (stat(old_log.c_str(), &tmp_buffer) != 0)
67       continue;
68
69     // the oldest log will be removed
70     if (i == max_rotation_) {
71       if (std::remove(old_log.c_str()) != 0)
72         return false;
73     } else {
74       std::string new_log = file_name_ + "." + std::to_string(i + 1);
75       if (std::rename(old_log.c_str(), new_log.c_str()) != 0)
76         return false;
77     }
78   }
79   std::string new_log = file_name_ + ".1";
80   if (std::rename(file_name_.c_str(), new_log.c_str()) != 0)
81     return false;
82
83   return true;
84 }
85
86 int FileLogBackend::GetFileSize(const std::string& file_name) {
87   struct stat sb;
88   int ret = stat(file_name.c_str(), &sb);
89   return ret == 0 ? sb.st_size : -1;
90 }
91
92 std::string FileLogBackend::GetTimeStamp() {
93   struct timespec ts;
94   clock_gettime(CLOCK_REALTIME, &ts);
95
96   time_t seconds = ts.tv_sec;
97   struct tm gmt;
98   if (!gmtime_r(&seconds, &gmt))
99     return "|";
100   int32_t miliseconds = ts.tv_nsec / 1000000;
101
102   char buf[32];
103   strftime(buf, sizeof(buf), "%Y%m%d.%H%M%S", &gmt);
104   char timestamp[32];
105   snprintf(timestamp, sizeof(timestamp), "%s.%03dUTC|", buf, miliseconds);
106
107   return timestamp;
108 }
109
110 std::string FileLogBackend::GetPid() {
111   return std::to_string(getpid()) + "|";
112 }
113
114 }  // namespace utils