Add FileLogBackend class 89/213189/2
authorSangyoon Jang <jeremy.jang@samsung.com>
Mon, 2 Sep 2019 10:39:12 +0000 (19:39 +0900)
committerSangyoon Jang <jeremy.jang@samsung.com>
Tue, 3 Sep 2019 09:15:22 +0000 (09:15 +0000)
FileLogBackend is custom logbackend class.

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/manifest-parser/+/213188

Change-Id: I48ddcfa63cc0dce04cf81137e1c4a9e4323cb5b6
Signed-off-by: Sangyoon Jang <jeremy.jang@samsung.com>
src/common/app_installer.cc
src/common/utils/file_logbackend.cc [new file with mode: 0644]
src/common/utils/file_logbackend.h [new file with mode: 0644]

index 0fd7b2a..c131b0d 100644 (file)
@@ -14,6 +14,7 @@
 #include "common/pkgmgr_interface.h"
 #include "common/pkgmgr_signal.h"
 #include "common/step/configuration/step_fail.h"
+#include "common/utils/file_logbackend.h"
 
 namespace {
 
@@ -122,9 +123,10 @@ AppInstaller::Result AppInstaller::Run() {
   unsigned total_steps = steps_.size();
   unsigned current_step = 1;
 
-  ::utils::LogCore::GetCore().SetFileName(kLogFileName);
-  ::utils::LogCore::GetCore().SetRotationSize(kLogRotationSize);
-  ::utils::LogCore::GetCore().SetMaximumRotation(kLogMaximumRotation);
+  std::shared_ptr<utils::FileLogBackend> failure_logger =
+      std::shared_ptr<utils::FileLogBackend>(new utils::FileLogBackend(
+            kLogFileName, kLogRotationSize, kLogMaximumRotation));
+  ::utils::LogCore::GetCore().AddLogBackend(failure_logger);
 
   for (; it != itEnd; ++it, ++current_step) {
     status = SafeExecute(*it, &Step::precheck, "precheck");
@@ -150,7 +152,7 @@ AppInstaller::Result AppInstaller::Run() {
         ret = Result::UNDO_ERROR;
       }
     } while (it-- != itStart);
-    ::utils::LogCore::GetCore().WriteLog();
+    failure_logger->WriteLogToFile();
   } else {
     do {
       if (it == itEnd)
diff --git a/src/common/utils/file_logbackend.cc b/src/common/utils/file_logbackend.cc
new file mode 100644 (file)
index 0000000..389cc09
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#include "common/utils/file_logbackend.h"
+
+#include <manifest_parser/utils/logging.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+
+namespace utils {
+
+FileLogBackend::FileLogBackend(std::string file_name, int rotation_size,
+    int max_rotation)
+    : file_name_(std::move(file_name)), rotation_size_(rotation_size),
+      max_rotation_(max_rotation), log_stream_(
+          std::unique_ptr<std::ostringstream>(new std::ostringstream())) {
+}
+
+
+void FileLogBackend::WriteLog(LogLevel level, const std::string& /* tag */,
+    const std::string& logstr) {
+  if (level != LogLevel::LOG_DEBUG)
+    *log_stream_ << GetTimeStamp() << GetPid() << logstr << std::endl;
+}
+
+void FileLogBackend::WriteLogToFile() {
+  if (file_name_.empty())
+    return;
+
+  int size = GetFileSize(file_name_);
+  if (size > rotation_size_)
+    Rotate();
+
+  std::ofstream ofs(file_name_.c_str(), std::ios::app);
+  ofs << log_stream_->str();
+  ofs.close();
+
+  // clean the log stream
+  log_stream_->str("");
+  log_stream_->clear();
+}
+
+void FileLogBackend::Rotate() {
+  for (int i = max_rotation_; i > 0; i--) {
+    std::string old_log = file_name_ + "." + std::to_string(i);
+    // the oldest log will be removed
+    if (i == max_rotation_) {
+      std::remove(old_log.c_str());
+    } else {
+      std::string new_log = file_name_ + "." + std::to_string(i + 1);
+      std::rename(old_log.c_str(), new_log.c_str());
+    }
+  }
+  std::string new_log = file_name_ + ".1";
+  std::rename(file_name_.c_str(), new_log.c_str());
+}
+
+int FileLogBackend::GetFileSize(const std::string& file_name) {
+  struct stat sb;
+  int ret = stat(file_name.c_str(), &sb);
+  return ret == 0 ? sb.st_size : -1;
+}
+
+std::string FileLogBackend::GetTimeStamp() {
+  struct timespec ts;
+  clock_gettime(CLOCK_REALTIME, &ts);
+
+  time_t seconds = ts.tv_sec;
+  struct tm gmt;
+  if (!gmtime_r(&seconds, &gmt))
+    return "[]";
+  int32_t miliseconds = ts.tv_nsec / 1000000;
+
+  char buf[32];
+  strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &gmt);
+  char timestamp[32];
+  snprintf(timestamp, sizeof(timestamp), "[%s.%03d UTC]", buf, miliseconds);
+
+  return timestamp;
+}
+
+std::string FileLogBackend::GetPid() {
+  return "[" + std::to_string(getpid()) + "]";
+}
+
+}  // namespace utils
diff --git a/src/common/utils/file_logbackend.h b/src/common/utils/file_logbackend.h
new file mode 100644 (file)
index 0000000..ce44943
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+// Use of this source code is governed by a apache 2.0 license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_UTILS_FILE_LOGBACKEND_H_
+#define COMMON_UTILS_FILE_LOGBACKEND_H_
+
+#include <manifest_parser/utils/logging.h>
+
+#include <memory>
+#include <sstream>
+#include <string>
+
+namespace utils {
+
+class FileLogBackend : public ILogBackend {
+ public:
+  FileLogBackend(std::string file_name, int rotation_size, int max_rotation);
+  void WriteLog(LogLevel level, const std::string& tag,
+      const std::string& logstr) override;
+  void WriteLogToFile();
+
+ private:
+  void Rotate();
+  int GetFileSize(const std::string& file_name);
+  std::string GetTimeStamp();
+  std::string GetPid();
+
+  std::string file_name_;
+  int rotation_size_;
+  int max_rotation_;
+  std::unique_ptr<std::ostringstream> log_stream_;
+};
+
+}  // namespace utils
+
+#endif  // COMMON_UTILS_FILE_LOGBACKEND_H_