• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/logger_output.h"
17 
18 #include <chrono>
19 #include <ctime>
20 #include <fstream>
21 #include <iomanip>
22 #include <string_view>
23 
24 #include <base/containers/string_view.h>
25 #include <base/namespace.h>
26 #include <core/namespace.h>
27 
28 #include "log/logger.h"
29 
30 namespace LoggerUtils {
31 namespace {
32 constexpr int MS_WIDTH = 3;
33 } // namespace
34 
GetFilename(BASE_NS::string_view path)35 BASE_NS::string_view GetFilename(BASE_NS::string_view path)
36 {
37     if (auto const pos = path.find_last_of("\\/"); pos != BASE_NS::string_view::npos) {
38         return path.substr(pos + 1);
39     }
40     return path;
41 }
42 
PrintTimeStamp(std::ostream & outputStream)43 void PrintTimeStamp(std::ostream& outputStream)
44 {
45     const auto now = std::chrono::system_clock::now();
46     const auto time = std::chrono::system_clock::to_time_t(now);
47     const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) -
48                     std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
49 
50     outputStream << std::put_time(std::localtime(&time), "%D %H:%M:%S.");
51     outputStream << std::right << std::setfill('0') << std::setw(MS_WIDTH) << ms.count() << std::setfill(' ');
52 }
53 } // namespace LoggerUtils
54 
55 CORE_BEGIN_NAMESPACE()
56 using BASE_NS::string_view;
57 
58 class FileOutput final : public ILogger::IOutput {
59 public:
FileOutput(const string_view filePath)60     explicit FileOutput(const string_view filePath) : IOutput(), outputStream_(filePath.data(), std::ios::app) {}
61 
Write(ILogger::LogLevel logLevel,const string_view filename,int linenumber,const string_view message)62     void Write(
63         ILogger::LogLevel logLevel, const string_view filename, int linenumber, const string_view message) override
64     {
65         if (outputStream_.is_open()) {
66             auto& outputStream = outputStream_;
67 
68             LoggerUtils::PrintTimeStamp(outputStream);
69             const auto levelString = Logger::GetLogLevelName(logLevel, true);
70             outputStream << ' ' << std::string_view(levelString.data(), levelString.size());
71 
72             if (!filename.empty()) {
73                 outputStream << " (" << std::string_view(filename.data(), filename.size()) << ':' << linenumber
74                              << "): ";
75             } else {
76                 outputStream << ": ";
77             }
78 
79             outputStream << std::string_view(message.data(), message.size()) << std::endl;
80         }
81     }
82 
83 protected:
Destroy()84     void Destroy() override
85     {
86         delete this;
87     }
88 
89 private:
90     std::ofstream outputStream_;
91 };
92 
CreateLoggerFileOutput(const string_view filename)93 ILogger::IOutput::Ptr CreateLoggerFileOutput(const string_view filename)
94 {
95     return ILogger::IOutput::Ptr { new FileOutput(filename) };
96 }
97 CORE_END_NAMESPACE()
98