18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "log/logger_output.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <chrono>
198bf80f4bSopenharmony_ci#include <ctime>
208bf80f4bSopenharmony_ci#include <fstream>
218bf80f4bSopenharmony_ci#include <iomanip>
228bf80f4bSopenharmony_ci#include <string_view>
238bf80f4bSopenharmony_ci
248bf80f4bSopenharmony_ci#include <base/containers/string_view.h>
258bf80f4bSopenharmony_ci#include <base/namespace.h>
268bf80f4bSopenharmony_ci#include <core/namespace.h>
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ci#include "log/logger.h"
298bf80f4bSopenharmony_ci
308bf80f4bSopenharmony_cinamespace LoggerUtils {
318bf80f4bSopenharmony_ciBASE_NS::string_view GetFilename(BASE_NS::string_view path)
328bf80f4bSopenharmony_ci{
338bf80f4bSopenharmony_ci    if (auto const pos = path.find_last_of("\\/"); pos != BASE_NS::string_view::npos) {
348bf80f4bSopenharmony_ci        return path.substr(pos + 1);
358bf80f4bSopenharmony_ci    }
368bf80f4bSopenharmony_ci    return path;
378bf80f4bSopenharmony_ci}
388bf80f4bSopenharmony_ci
398bf80f4bSopenharmony_civoid PrintTimeStamp(std::ostream& outputStream)
408bf80f4bSopenharmony_ci{
418bf80f4bSopenharmony_ci    const auto now = std::chrono::system_clock::now();
428bf80f4bSopenharmony_ci    const auto time = std::chrono::system_clock::to_time_t(now);
438bf80f4bSopenharmony_ci    const auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) -
448bf80f4bSopenharmony_ci                    std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch());
458bf80f4bSopenharmony_ci
468bf80f4bSopenharmony_ci    outputStream << std::put_time(std::localtime(&time), "%D %H:%M:%S.");
478bf80f4bSopenharmony_ci    outputStream << std::right << std::setfill('0') << std::setw(3) // 3: alignment
488bf80f4bSopenharmony_ci                 << ms.count() << std::setfill(' ');
498bf80f4bSopenharmony_ci}
508bf80f4bSopenharmony_ci} // namespace LoggerUtils
518bf80f4bSopenharmony_ci
528bf80f4bSopenharmony_ciCORE_BEGIN_NAMESPACE()
538bf80f4bSopenharmony_ciusing BASE_NS::string_view;
548bf80f4bSopenharmony_ci
558bf80f4bSopenharmony_ciclass FileOutput final : public ILogger::IOutput {
568bf80f4bSopenharmony_cipublic:
578bf80f4bSopenharmony_ci    explicit FileOutput(const string_view filePath) : IOutput(), outputStream_(filePath.data(), std::ios::app) {}
588bf80f4bSopenharmony_ci
598bf80f4bSopenharmony_ci    void Write(
608bf80f4bSopenharmony_ci        ILogger::LogLevel logLevel, const string_view filename, int linenumber, const string_view message) override
618bf80f4bSopenharmony_ci    {
628bf80f4bSopenharmony_ci        if (outputStream_.is_open()) {
638bf80f4bSopenharmony_ci            auto& outputStream = outputStream_;
648bf80f4bSopenharmony_ci
658bf80f4bSopenharmony_ci            LoggerUtils::PrintTimeStamp(outputStream);
668bf80f4bSopenharmony_ci            const auto levelString = Logger::GetLogLevelName(logLevel, true);
678bf80f4bSopenharmony_ci            outputStream << ' ' << std::string_view(levelString.data(), levelString.size());
688bf80f4bSopenharmony_ci
698bf80f4bSopenharmony_ci            if (!filename.empty()) {
708bf80f4bSopenharmony_ci                outputStream << " (" << std::string_view(filename.data(), filename.size()) << ':' << linenumber
718bf80f4bSopenharmony_ci                             << "): ";
728bf80f4bSopenharmony_ci            } else {
738bf80f4bSopenharmony_ci                outputStream << ": ";
748bf80f4bSopenharmony_ci            }
758bf80f4bSopenharmony_ci
768bf80f4bSopenharmony_ci            outputStream << std::string_view(message.data(), message.size()) << std::endl;
778bf80f4bSopenharmony_ci        }
788bf80f4bSopenharmony_ci    }
798bf80f4bSopenharmony_ci
808bf80f4bSopenharmony_ciprotected:
818bf80f4bSopenharmony_ci    void Destroy() override
828bf80f4bSopenharmony_ci    {
838bf80f4bSopenharmony_ci        delete this;
848bf80f4bSopenharmony_ci    }
858bf80f4bSopenharmony_ci
868bf80f4bSopenharmony_ciprivate:
878bf80f4bSopenharmony_ci    std::ofstream outputStream_;
888bf80f4bSopenharmony_ci};
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_ciILogger::IOutput::Ptr CreateLoggerFileOutput(const string_view filename)
918bf80f4bSopenharmony_ci{
928bf80f4bSopenharmony_ci    return ILogger::IOutput::Ptr { new FileOutput(filename) };
938bf80f4bSopenharmony_ci}
948bf80f4bSopenharmony_ciCORE_END_NAMESPACE()
95