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