/* * 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 HTTP_APPENDER_H #define HTTP_APPENDER_H #ifndef RUST_WRAPPER #include #include #include #include #include "knet/knet.h" #include "klogger/interface/logger.h" #include "mode.h" #include "scope_lock.h" #include "util.h" class LoggerImpl; class Log_; using namespace klogger; class HttpAppender : public Appender { public: HttpAppender(LoggerImpl *impl, const std::string &name, const std::string &attribute); virtual ~HttpAppender(); 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; } public: /** * 增加连接池计数 */ void addChan(); /** * 减少连接池计数 */ void subChan(); 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); /** * 线程循环 */ void run(); /** * 线程函数 */ #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) static void write_thread(void *params); #else static void *write_thread(void *params); #endif // _WIN32 /** * 发送HTTP日志 * @param log 日志 */ void doHttpWrite(char *log); /** * 解析主机地址 */ void resolveHost(); /** * 启动日志线程 */ void startThread(); /** * 终止线程 */ void stopThread(); private: /** * 连接器回调 */ static void connetor_cb(kchannel_ref_t *channel, knet_channel_cb_event_e e); /** * 从日志队列取一条日志 */ static char *popLog(HttpAppender *ap); /** * 放一条日志到日志队列 */ static void pushLog(HttpAppender *ap, char *log); /** * 发送HTTP POST协议 */ static int postLog(kstream_t *stream, HttpAppender *ap, const char *log); /** * 处理管道关闭 */ static void doChanClose(kchannel_ref_t *channel); /** * 处理管道连接成功 */ static void doChanConnect(kchannel_ref_t *channel); private: std::string _line; ///< 日志行前缀 std::string _realName; ///< 添加器名称 std::string _name; ///< 添加器在日志行中显示的名称 std::string _method; ///< HTTP method LoggerImpl *_impl; ///< Logger实现类 Pattern _pattern; ///< 日志行前缀匹配器 std::string _host; ///< HTTP服务器主机 std::string _uri; ///< WEB目录 std::string _ip; ///< HTTP服务器IP地址 RecursiveLock _logLock; ///< 发送链表锁 int _poolSize; ///< 最大连接数量 int _port; ///< HTTP服务器端口 volatile bool _running; ///< 线程运行标志 int _level; ///< 日志等级 private: friend class Log_; typedef std::vector ChannelVector; typedef std::list LogList; int _chanCount; ///< 短连接数量 LogList _logList; ///< 日志队列 kloop_t *_loop; ///< 网络事件循环 /** * 线程ID */ #if defined(_WIN32) || defined(WIN32) || defined(_WIN64) HANDLE _tid; #else pthread_t _tid; #endif // _WIN32 }; class Log_ { public: Log_(HttpAppender *appender, char *line) { _ap = appender; _log = line; _posted = false; } ~Log_() {} inline void delLog() { delete[] _log; _log = 0; } inline char *getLog() { return _log; } inline void repush() { _ap->pushLog(_ap, _log); } inline bool isPosted() { return _posted; } inline void setPosted(bool flag) { _posted = flag; } inline HttpAppender *getAppender() { return _ap; } inline void subChan() { _ap->subChan(); } inline void addChan() { _ap->addChan(); } private: Log_(const Log_ &); private: HttpAppender *_ap; ///< HttpAppender char *_log; ///< 日志 bool _posted; ///< 是否已经发送 }; #endif // !RUST_WRAPPER #endif // HTTP_APPENDER_H