/* * Copyright (c) 2013-2015, dennis wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef FILE_APPENDER_H #define FILE_APPENDER_H #include #include #include #include #include #include "klogger/interface/logger.h" #include "mode.h" #include "util.h" #include #include #include #include #ifdef max #undef max #endif class LoggerImpl; using namespace klogger; /** * 文件添加器 */ class FileAppender : public Appender { public: /** * 构造 * @param impl_ptr Logger * @param name 添加器名字 * @param attribute 添加器配置 */ FileAppender(LoggerImpl *impl_ptr, const std::string &name, const std::string &attribute); virtual ~FileAppender(); virtual void write(int level, const char *format, ...); virtual void setLevel(int level); virtual int getLevel(); virtual void destroy(); virtual void reload(const std::string &attribute); virtual void show_level(bool flag); virtual void show_name(bool flag); virtual void detach() { _impl = nullptr; } private: /** * 解析配置字符串 * @param attribute 配置字符串 */ void parseAttribute(const std::string &attribute); /** * 取得配置值 * @param name 配置键名称 * @param attribute 配置 * @return 配置值 */ std::string getAttribute(const std::string &name, const std::string &attribute); /** * 写日志行 * @param level 日志等级字符串 * @param format 日志格式 * @param va_ptr 可变参数宏 */ void write(const std::string &level, const char *format, va_list va_ptr); /** * 写日志行, JSON格式 * @param level 日志等级字符串 * @param format 日志格式 * @param va_ptr 可变参数宏 */ void write_json(const std::string &level, const char *format, va_list va_ptr); /** * 打开日志文件 */ void open(); /** * 获取最大文件大小 */ int getMaxSize(const std::string &str); private: FILE *_fp{nullptr}; ///< 日志文件描述符 std::string _file{"%y%m%d.log"}; ///< 日志文件名称 std::string _path{"."}; ///< 日志目录名称 std::string _mode{"day"}; ///< 日志模式 std::string _line{"[%y%m%d-%H:%M:%S:%U]"}; ///< 日志行前缀 std::string _name{"[anony]"}; ///< 添加器在日志行中显示的名称 std::string _realName{"anony"}; ///< 添加器名称 bool _flush{false}; ///< flush标志 bool _async{true}; ///< 异步标志 volatile bool _running{false}; ///< 线程运行标志 LoggerImpl *_impl{nullptr}; ///< Logger实现类 Mode _logMode; ///< 日志模式 Pattern _pattern; ///< 日志行前缀匹配器 std::mutex _fpLock; ///< 多线程锁 int _level{Logger::MIN}; ///< 日志等级 int _size{0}; ///< 日志文件长度 int _maxSize{std::numeric_limits::max()}; ///< 单个日志文件最大长度 int _index{0}; ///< 日志文件索引 bool _useLastFile{true}; ///< 是否使用上一个未达到最大长度的日志文件 bool _same_log_count{false}; ///< 相同日志追加数量 enum class Format { TXT = 1, ///< 文本 JSON, ///< JSON格式 }; Format _format{Format::TXT}; ///< 日志文本格式 static const std::size_t BUF_LEN = 1024 * 1024 * 10; ///< 单条日志最大长度 using LogMap = std::unordered_map; LogMap log_map_; ///< 历史日志 bool show_log_level_{true}; bool show_log_name_{true}; private: struct LogLine { std::unique_ptr log; ///< 日志行 int prefix_size{0}; ///< 前缀长度 }; using LogList = std::list; LogList _logList; ///< 日志行队列 std::thread _worker; ///< 写入线程 }; #endif // FILE_APPENDER_H