तार्किक रूप से Log4j लॉगर्स को कॉन्फ़िगर करना


189

मैं SLF4J (के साथ) का उपयोग करने की कोशिश कर रहा हूं log4j पहली बार बाइंडिंग के ) ।

मैं 3 अलग-अलग नामांकित लोगों को कॉन्फ़िगर करना चाहूंगा जिन्हें एक लॉगरफैक्ट्री द्वारा लौटाया जा सकता है जो विभिन्न स्तरों पर लॉग इन करेंगे और संदेशों को अलग-अलग ऐपेंडर्स पर धकेलेंगे:

  • लकड़हारा 1 "FileLogger" DEBUG में प्रवेश करता है और करने के लिए अपील करता है DailyRollingFileAppender
  • लकड़हारा 2 "TracingLogger" TRACE + को लॉग करता है और एक को जोड़ता है JmsAppender
  • लकड़हारा 3 "ErrorLogger" ERROR + को लॉग करता है और एक अलग करता है JmsAppender

इसके अलावा मैं उन्हें प्रोग्रामेटिक रूप से कॉन्फ़िगर करना चाहता हूं (जावा में, एक्सएमएल या एक log4j.propertiesफाइल के विपरीत )।

मुझे लगता है कि, आम तौर पर, मैं इन Loggerएस को कुछ बूटस्ट्रैपिंग कोड में एक init()विधि की तरह परिभाषित करता हूं । हालाँकि, क्योंकि मैं उपयोग करना चाहता हूं, इसलिए मैं slf4j-log4jअसमंजस में हूं कि मैं लॉगर को कहां तक ​​परिभाषित कर सकता हूं और उन्हें क्लासपाथ को उपलब्ध करा सकता हूं।

मेरा मानना ​​है कि यह SLF4J के अंतर्निहित उद्देश्य (एक पहलू के रूप में) का उल्लंघन है, क्योंकि SLF4J API का उपयोग करने वाला मेरा कोड कभी नहीं जान पाएगा कि ये लॉगर मौजूद हैं। मेरा कोड सिर्फ SLF4J API के लिए सामान्य कॉल करता है, जो तब उन्हें log4j लॉगर्स पर देता है जो इसे क्लासपाथ पर पाता है।

लेकिन मैं उन लॉग 4j लॉगर को क्लासपाथ पर कैसे कॉन्फ़िगर करूं ... जावा में ?!



3
Log4j 1.x स्वीकार किए जाते हैं जवाब नीचे के लिए 2.x देखने का उपयोग करें logging.apache.org/log4j/2.x/manual/customconfig.html
earcam

जवाबों:


277

आप प्रोग्रामर को Log4j में प्रोग्रामेटिक रूप से जोड़ / हटा सकते हैं:

  ConsoleAppender console = new ConsoleAppender(); //create appender
  //configure the appender
  String PATTERN = "%d [%p|%c|%C{1}] %m%n";
  console.setLayout(new PatternLayout(PATTERN)); 
  console.setThreshold(Level.FATAL);
  console.activateOptions();
  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(console);

  FileAppender fa = new FileAppender();
  fa.setName("FileLogger");
  fa.setFile("mylog.log");
  fa.setLayout(new PatternLayout("%d %-5p [%c{1}] %m%n"));
  fa.setThreshold(Level.DEBUG);
  fa.setAppend(true);
  fa.activateOptions();

  //add appender to any Logger (here is root)
  Logger.getRootLogger().addAppender(fa);
  //repeat with all other desired appenders

मेरा सुझाव है कि आप इसे एक init () में कहीं रख दें, जहाँ आप सुनिश्चित हैं, कि इसे किसी अन्य चीज़ से पहले निष्पादित किया जाएगा। इसके बाद आप रूट लॉगर पर मौजूद सभी मौजूदा एपेंडर्स को हटा सकते हैं

 Logger.getRootLogger().getLoggerRepository().resetConfiguration();

और अपने खुद के जोड़ने के साथ शुरू करो। इस कार्य के लिए आपको पाठ्यक्रम के वर्गपथ में log4j की आवश्यकता है।

टिप्पणी:
आप किसी भी Logger.getLogger(...)आप को जोड़ने के लिए ले सकते हैं जैसे कि परिशिष्ट। मैंने बस रूट लकड़हारा लिया क्योंकि यह सभी चीजों में सबसे नीचे है और अन्य श्रेणियों में अन्य ऐपेंडरों के माध्यम से पारित होने तक सब कुछ संभाल लेगा (जब तक कि एडिटिविटी फ्लैग सेट करके अन्यथा कॉन्फ़िगर नहीं किया जाता)।

यदि आपको यह जानने की जरूरत है कि लॉगिंग कैसे काम करती है और यह कैसे तय किया जाता है कि लॉग कहां लिखे गए हैं तो इस बारे में अधिक जानकारी के लिए इस मैनुअल को पढ़ें
संक्षेप में:

  Logger fizz = LoggerFactory.getLogger("com.fizz")

आपको "com.fizz" श्रेणी के लिए एक लकड़हारा देगा।
उपर्युक्त उदाहरण के लिए इसका अर्थ है कि इसके साथ लॉग की गई हर चीज को रूट लॉगर पर कंसोल और फ़ाइल परिशिष्ट में भेजा जाएगा।
यदि आप Logger.getLogger ("com.fizz") में एक परिशिष्ट जोड़ते हैं। addAppender (newAppender) तो लॉगिंग से संलग्‍न हो fizzजाएगा और परिशिष्ट को मूल लकड़हारा और से जोड़ा जाएगा newAppender
आप कॉन्फ़िगरेशन के साथ लकड़हारे नहीं बनाते हैं, आप बस अपने सिस्टम में सभी संभावित श्रेणियों के लिए हैंडलर प्रदान करते हैं।


2
धन्यवाद ओर्स! त्वरित प्रश्न - मैंने देखा कि आप एपेंडरों को रूट लॉगर में जोड़ रहे हैं। क्या इसका कोई कारण है?
IAmYourFaja

और, अधिक महत्वपूर्ण बात, मुझे यह निर्दिष्ट करने की आवश्यकता होगी कि कौन सा लकड़हारा SLF4J के लकड़हारा से पुनः प्राप्त करने के लिए। क्या log4j के रूट लॉगर के लिए SLF4J पूछना संभव है?
IAmYourFaja

3
@AdamTannon आप किसी भी Logger.getLogger (...) को पसंद कर सकते हैं। मैंने सिर्फ रूट लकड़हारा लिया क्योंकि यह सभी चीजों में सबसे नीचे है और अन्य श्रेणियों में अन्य ऐपेंडरों के माध्यम से पारित होने तक सब कुछ संभाल लेगा (जब तक कि अन्यथा कॉन्फ़िगर नहीं किया जाता है)। लकड़हारा पदानुक्रम देखें
oers

@AdamTannon आप log4j रूट लकड़हारा पाने के लिए sl4j कारखाने का उपयोग नहीं कर सकते। SL4j एक लॉगिंग मुखौटा है। आपको इसमें से कुछ विशेष log4j नहीं मिलेगा।
oers

2
oers - मैं आपकी अद्भुत प्रतिक्रिया की सराहना करता हूं, लेकिन मैं यहां सभी बिंदुओं को नहीं जोड़ रहा हूं। क्या आप एक नया लकड़हारा (मूल लकड़हारा नहीं) को जोड़ने के लिए अपने उदाहरण को संशोधित कर सकते हैं, जो एक बार सिस्टम में जोड़ा जाता है, वह किसी अन्य वर्ग के लिए उपलब्ध होगा जो इसके लिए पूछता है? उदाहरण के लिए, एक लकड़हारा, जिसे सामान्य रूप से एक्सेस किया जाता है, कहते हैं, Logger fizz = LoggerFactory.getLogger("com.fizz");धन्यवाद!
IAmYourFaja

47

ऐसा लगता है कि आप "दोनों छोर" (उपभोक्ता अंत और कॉन्फ़िगरेशन एंड) से लॉग 4 जे का उपयोग करने की कोशिश कर रहे हैं।

यदि आप slf4j एपीआई के खिलाफ कोड करना चाहते हैं, लेकिन समय से पहले निर्धारित करें (और प्रोग्रामेटिक रूप से) log4j लॉगर का कॉन्फ़िगरेशन जो क्लासपाथ वापस आ जाएगा, तो आपको बिल्कुल किसी प्रकार का लॉगिंग अनुकूलन करना होगा जो आलसी निर्माण का उपयोग करता है।

public class YourLoggingWrapper {
    private static boolean loggingIsInitialized = false;

    public YourLoggingWrapper() {
        // ...blah
    }

    public static void debug(String debugMsg) {
        log(LogLevel.Debug, debugMsg);
    }

    // Same for all other log levels your want to handle.
    // You mentioned TRACE and ERROR.

    private static void log(LogLevel level, String logMsg) {
        if(!loggingIsInitialized)
            initLogging();

        org.slf4j.Logger slf4jLogger = org.slf4j.LoggerFactory.getLogger("DebugLogger");

        switch(level) {
        case: Debug:
            logger.debug(logMsg);
            break;
        default:
            // whatever
        }
    }

    // log4j logging is lazily constructed; it gets initialized
    // the first time the invoking app calls a log method
    private static void initLogging() {
        loggingIsInitialized = true;

        org.apache.log4j.Logger debugLogger = org.apache.log4j.LoggerFactory.getLogger("DebugLogger");

        // Now all the same configuration code that @oers suggested applies...
        // configure the logger, configure and add its appenders, etc.
        debugLogger.addAppender(someConfiguredFileAppender);
    }

इस दृष्टिकोण के साथ, आपको इस बारे में चिंता करने की आवश्यकता नहीं है कि आपके लॉग 4j लॉगर्स कहां / कब कॉन्फ़िगर किए गए हैं। पहली बार जब क्लासपाथ ने उनके लिए पूछा, तो वे आलसी निर्माण करते हैं, वापस पास हुए और एसएलएफ 4 जे के माध्यम से उपलब्ध कराए गए। उम्मीद है कि इस मदद की!


2
बिल्कुल सही किया! एक सहायक उदाहरण के लिए बहुत बहुत धन्यवाद! @ ओर्स - मुझे सही दिशा में आगे बढ़ाने की कोशिश करने के लिए धन्यवाद - मैं आपको आपके समर्पण के लिए ग्रीन चेक देने जा रहा हूं, लेकिन ज़ारवे को इनाम देना होगा क्योंकि यह वही था जो मैं देख रहा था। फिर से सभी को धन्यवाद!
IAYYourFaja

4

उस स्थिति में जब आपने log4j गुणों में एक परिशिष्ट को परिभाषित किया है और इसे प्रोग्रामेटिक रूप से अपडेट करना चाहते हैं, log4j गुणों में नाम सेट करें और इसे नाम से प्राप्त करें।

यहाँ एक उदाहरण log4j.properties प्रविष्टि है:

log4j.appender.stdout.Name=console
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.Threshold=INFO

इसे अद्यतन करने के लिए, निम्नलिखित करें:

((ConsoleAppender) Logger.getRootLogger().getAppender("console")).setThreshold(Level.DEBUG);

1

यदि कोई जावा में प्रोग्राम लॉग 4j2 को कॉन्फ़िगर करने के लिए आता है, तो यह लिंक मदद कर सकता है: ( https://www.studytonight.com/post/log4j2-programmatic-configuration-in-java-class )

यहाँ सांत्वना परिशिष्ट को कॉन्फ़िगर करने के लिए मूल कोड है:

ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();

builder.setStatusLevel(Level.DEBUG);
// naming the logger configuration
builder.setConfigurationName("DefaultLogger");

// create a console appender
AppenderComponentBuilder appenderBuilder = builder.newAppender("Console", "CONSOLE")
                .addAttribute("target", ConsoleAppender.Target.SYSTEM_OUT);
// add a layout like pattern, json etc
appenderBuilder.add(builder.newLayout("PatternLayout")
                .addAttribute("pattern", "%d %p %c [%t] %m%n"));
RootLoggerComponentBuilder rootLogger = builder.newRootLogger(Level.DEBUG);
rootLogger.add(builder.newAppenderRef("Console"));

builder.add(appenderBuilder);
builder.add(rootLogger);
Configurator.reconfigure(builder.build());

यह डिफ़ॉल्ट रूटलेगर को फिर से कॉन्फ़िगर करेगा और एक नया ऐपेंडर भी बनाएगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.