代码之家  ›  专栏  ›  技术社区  ›  greywolf82

配置带有log4cxx的自定义和动态附加程序

  •  1
  • greywolf82  · 技术社区  · 6 年前

    我想在代码中为记录器创建一个appender,但同时我想在属性文件上进行配置。我正在以这种方式创建附加程序:

    class Foo {
    private:
        LoggerPtr logger;
    public:
        Foo(int id) {
            logger = LoggerPtr(Logger::getLogger("foo." + std::to_string(id)));
            RollingFileAppender* appender = new RollingFileAppender();
            appender->setAppend(true);
            appender->setMaxFileSize("1MB");
            appender->setMaxBackupIndex(1);
            appender->setFile("foo." + std::to_string(id) + ".log");
            PatternLayout* layOut = new PatternLayout();
            layOut->setConversionPattern(
                    "%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n");
            appender->setLayout(LayoutPtr(layOut));
            appender->setName("fooAppender");
            Pool p;
            appender->activateOptions(p);
            logger->addAppender(AppenderPtr(appender));
            logger->setAdditivity(false);
        }
        const LoggerPtr& getLogger() const {
            return logger;
        }
    };
    

    这里的目标是为每个 Foo 类,由于数字是动态的,所以我无法在属性文件中创建记录器(也许我可以从0到2*1024*1024,但这太疯狂了)。为了实现这个目标,我需要几个附加程序,但是我希望在属性文件中有类似的内容:

    log4j.appender.foo=org.apache.log4j.RollingFileAppender
    log4j.appender.foo.MaxFileSize=50MB
    log4j.appender.foo.MaxBackupIndex=1
    log4j.appender.foo.layout=org.apache.log4j.PatternLayout
    log4j.appender.foo.layout.ConversionPattern=%p %t %c - %m%n
    

    是否可以让自定义附加程序继续从属性文件读取配置?

    1 回复  |  直到 6 年前
        1
  •  1
  •   greywolf82    6 年前

    我回答自己。所需:您需要创建一个新的自定义appender,并在第一级记录器中将其设置为appender,而不是在代码中克隆appender。另外,在自定义附加程序中,您可以管理延迟的文件创建,以便在没有日志的情况下不再有空文件;)代码如下:

    class MyLogger {
    private:
        MyLogger() {
        }
    public:
        static void cloneParentLogger(const std::string& parentName,
                const std::string& parentAppenderName, LoggerPtr& child,
                const std::string& childName) {
            std::string newName = parentName + "." + childName;
            LoggerPtr loggerMst = LoggerPtr(Logger::getLogger(parentName));
            Appender* app = loggerMst->getAppender(parentAppenderName);
            app->close();
            AppenderPtr newAppender = app->getClass().newInstance();
            if (newAppender->instanceof(FileAppender::getStaticClass())) {
                Appender* p = newAppender;
                reinterpret_cast<FileAppender*>(p)->setFile(newName + ".log");
            }
            child = LoggerPtr(Logger::getLogger(newName));
            newAppender->setName(childName);
            newAppender->setLayout(app->getLayout());
            Pool p;
            newAppender->activateOptions(p);
            child->addAppender(newAppender);
            child->setAdditivity(false);
        }
    };
    class Foo {
    private:
        LoggerPtr logger;
    public:
        Foo(int id) {
            MyLogger::cloneParentLogger("foo", "R1", logger, std::to_string(id));
        }
        const LoggerPtr& getLogger() const {
            return logger;
        }
    };
    

    属性文件

    # Set root logger level to DEBUG and its only appender to A1.
    log4j.rootLogger=DEBUG
    
    log4j.logger.foo=DEBUG, R1
    
    log4j.appender.R1=DelayedRollingFileAppender
    log4j.appender.R1.MaxFileSize=50MB
    log4j.appender.R1.MaxBackupIndex=1
    log4j.appender.R1.layout=org.apache.log4j.PatternLayout
    log4j.appender.R1.layout.ConversionPattern=%p %t %c - %m%n
    

    具有延迟文件创建的自定义附加程序:

    #ifndef DELAYEDROLLINGFILEAPPENDER_H_
    #define DELAYEDROLLINGFILEAPPENDER_H_
    
    #include <log4cxx/rollingfileappender.h>
    #include <log4cxx/helpers/object.h>
    #include <log4cxx/helpers/pool.h>
    #include <log4cxx/helpers/classregistration.h>
    #include <log4cxx/logstring.h>
    
    namespace log4cxx {
    
    class DelayedRollingFileAppender: public RollingFileAppender {
    private:
        bool firstAppend;
        LogString file;
        bool app;
        bool bufferedIo;
        size_t bufferSize;
    public:
        //DECLARE_LOG4CXX_OBJECT(DelayedRollingFileAppender)
        class ClazzDelayedRollingFileAppender: public helpers::Class {
        public:
            ClazzDelayedRollingFileAppender() :
                    helpers::Class() {
            }
            virtual ~ClazzDelayedRollingFileAppender() {
            }
            virtual LogString getName() const {
                return LOG4CXX_STR("DelayedRollingFileAppender");
            }
            virtual helpers::ObjectPtr newInstance() const {
                return new DelayedRollingFileAppender();
            }
        };
        virtual const helpers::Class& getClass() const;
        static const helpers::Class& getStaticClass();
        static const helpers::ClassRegistration& registerClass();
    
        DelayedRollingFileAppender();
        virtual ~DelayedRollingFileAppender();
        virtual void append(const spi::LoggingEventPtr& event,
                helpers::Pool& pool1);
        virtual void setFile(const LogString& file, bool append, bool bufferedIO,
                size_t bufferSize, helpers::Pool& p);
    };
    
    } /* namespace log4cxx */
    
    #endif /* DELAYEDROLLINGFILEAPPENDER_H_ */
    

    Cpp文件:

    #include "DelayedRollingFileAppender.h"
    
    #include <log4cxx/writerappender.h>
    #include <log4cxx/helpers/fileoutputstream.h>
    #include <log4cxx/helpers/bufferedwriter.h>
    
    namespace log4cxx {
    
    using namespace helpers;
    
    //IMPLEMENT_LOG4CXX_OBJECT(DelayedRollingFileAppender)
    const ::log4cxx::helpers::Class& DelayedRollingFileAppender::getClass() const {
        return getStaticClass();
    }
    const ::log4cxx::helpers::Class& DelayedRollingFileAppender::getStaticClass() {
        static ClazzDelayedRollingFileAppender theClass;
        return theClass;
    }
    const helpers::ClassRegistration& DelayedRollingFileAppender::registerClass() {
        static helpers::ClassRegistration classReg(
                DelayedRollingFileAppender::getStaticClass);
        return classReg;
    }
    
    namespace classes {
    const ::log4cxx::helpers::ClassRegistration& DelayedRollingFileAppenderRegistration =
            DelayedRollingFileAppender::registerClass();
    }
    
    DelayedRollingFileAppender::DelayedRollingFileAppender() {
        firstAppend = true;
        this->app = false;
        this->bufferSize = 0;
        this->bufferedIo = false;
    }
    
    DelayedRollingFileAppender::~DelayedRollingFileAppender() {
    }
    
    void DelayedRollingFileAppender::append(const spi::LoggingEventPtr& event,
            helpers::Pool& pool1) {
        if (firstAppend) {
            firstAppend = false;
            FileAppender::setFile(file, app, bufferedIo, bufferSize, pool1);
        }
        WriterAppender::append(event, pool1);
    }
    
    void DelayedRollingFileAppender::setFile(const LogString& file, bool append,
            bool bufferedIO, size_t bufferSize, helpers::Pool& p) {
        this->file = file;
        this->app = append;
        this->bufferSize = bufferSize;
        this->bufferedIo = bufferedIO;
    
        OutputStreamPtr outStream;
        try {
            outStream = new FileOutputStream("/dev/null", false);
        } catch (IOException& ex) {
            throw;
        }
    
        WriterPtr newWriter(createWriter(outStream));
    
        if (bufferedIo) {
            newWriter = new BufferedWriter(newWriter, bufferSize);
        }
        setWriter(newWriter);
    }
    
    } /* namespace log4cxx */