লগব্যাকের জন্য প্রোগ্রামগতভাবে রুট লগিং স্তর কীভাবে পরিবর্তন করবেন


144

আমার কাছে নিম্নলিখিত লগব্যাক.এক্সএমএল ফাইল রয়েছে:

<configuration debug="true"> 

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> 
<encoder>
  <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

<root level="debug">
  <appender-ref ref="STDOUT" />
</root>
</configuration>

এখন, একটি নির্দিষ্ট ইভেন্ট সংঘটিত হওয়ার পরে, আমি প্রোগ্রামগতভাবে ডিবাগ থেকে ত্রুটিতে রুট লগার স্তরটি পরিবর্তন করতে চাই । আমি পরিবর্তনশীল বিকল্প ব্যবহার করতে পারি না, কোডের মধ্যে এটি করা আমার পক্ষে বাধ্যতামূলক।

এটা কিভাবে করা যাবে ? ধন্যবাদ।

উত্তর:


235

এটা চেষ্টা কর:

import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

Logger root = (Logger)LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.setLevel(Level.INFO);

নোট করুন যে আপনি আপনার কনফিগার ফাইলটি পর্যায়ক্রমে স্ক্যান করতে লগব্যাকটি বলতে পারেন:

<configuration scan="true" scanPeriod="30 seconds" > 
  ...
</configuration> 

64
এটি লক্ষ করা উচিত যে slf4j এর উদ্দেশ্য হ'ল লগিংয়ের কাঠামোটি বিমূর্ত করা, তবে সেই প্রথম পদ্ধতিটি লগিং ফ্রেমওয়ার্কটিকে সরাসরি উল্লেখ করে তা সরিয়ে দেয়।
টিম গৌটিয়ার

3
আপনি যদি এটি করেন এবং ক্লাসকাস্টএক্সেপশন পান তবে ক্লাসপথে একাধিক এসএলএফ 4 জে বাইন্ডিং থাকার কারণে এটি সম্ভবত। লগ আউটপুট এটি নির্দেশ করবে এবং কোনটি (গুলি) বাদ দিতে হবে তা নির্ধারণ করতে আপনাকে কোন কোন বাইন্ডিংগুলি উপস্থিত রয়েছে তা নির্দেশ করবে।
icfantv

4
Slf4j একটি এপিআই সরবরাহ করে যাতে অ্যাপ্লিকেশন বিকাশকারী যা চান লগ ফ্রেমওয়ার্ক ব্যবহার করে গ্রন্থাগারগুলি অ্যাপ্লিকেশন লগগুলিতে লগ করতে পারে। মুল বক্তব্যটি হ'ল অ্যাপ্লিকেশন বিকাশকারীকে এখনও একটি লগ ফ্রেমওয়ার্ক বেছে নিতে হবে, এটির উপর নির্ভর করে এবং এটি কনফিগার করতে হবে। লগারটি কুকুরবান হিসাবে কনফিগার করা এই নীতি লঙ্ঘন করে না।
সর্বাধিক

4
@ জনজ্ঞানী আপনি যদি এটি কনফিগার করতে চান তবে আপনাকে এটি অন্য কোথাও কনফিগার করতে হবে । যেহেতু slf4j এই সম্মানের সাথে কিছুই সরবরাহ করে না, তাই সর্বদা অন্তর্নিহিত লগারের উপর নির্ভরশীল কিছু থাকবে। সে কোডের টুকরো বা কনফিগারেশন ফাইল হোক। +++ ওপির অনুরোধ অনুসারে যদি এটি প্রোগ্রামগতভাবে করা উচিত, তবে আপনার কোনও বিকল্প নেই। তবুও, সুবিধাগুলি রয়ে গেছে: ১. কোডের একটি ক্ষুদ্র অংশই কংক্রিট লগার ইঞ্জিনের উপর নির্ভর করে (এবং এটি এমনভাবে লেখা যেতে পারে যাতে এটি বিভিন্ন বাস্তবায়ন পরিচালনা করতে পারে)। ২. আপনি অন্যান্য লগার ব্যবহার করে লিখিত গ্রন্থাগারগুলিও কনফিগার করতে পারেন।
মার্টিনাস

4
এটি লগিংয়ের মতো কোনও কিছুর জন্য কেন এত জটিল হতে হবে, কোডে লগিংয়ের স্তর পরিবর্তন করার কোনও সরাসরি উপায় না থাকা উচিত। কীভাবে নির্দিষ্ট গ্রন্থাগারের নীতি অনুসরণ করা তার সরলতার চেয়ে অগ্রাধিকার গ্রহণ করে? পাইথন বিশ্ব থেকে আগত, জাভা / স্কালায় লগিংয়ের মতো সহজ কিছু কেন এত জটিল তা আমি বুঝতে ব্যর্থ হয়েছি।
অভিনন্দন দুবে

11

আমি ধরে নিয়েছি আপনি লগব্যাক ব্যবহার করছেন (কনফিগারেশন ফাইল থেকে)।

লগব্যাক ম্যানুয়াল থেকে , আমি দেখুন

Logger rootLogger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);

সম্ভবত এটি আপনাকে মান পরিবর্তন করতে সহায়তা করতে পারে?


10

লগব্যাক ব্যবহার করে ১.১.৩ আমাকে নিম্নলিখিতগুলি করতে হয়েছিল (স্কাল কোড):

import ch.qos.logback.classic.Logger
import org.slf4j.LoggerFactory    
...
val root: Logger = LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME).asInstanceOf[Logger]

4

আমি মনে করি আপনি প্রোগ্রামিং হিসাবে লগিং স্তর পরিবর্তন করতে MDC ব্যবহার করতে পারেন। নীচের কোডটি বর্তমান থ্রেডে লগিং স্তর পরিবর্তন করার একটি উদাহরণ। এই পদ্ধতির লগব্যাক বাস্তবায়নের উপর নির্ভরতা তৈরি হয় না (এসএলএফ 4 জে এপিআইতে এমডিসি রয়েছে)।

<configuration>
  <turboFilter class="ch.qos.logback.classic.turbo.DynamicThresholdFilter">
    <Key>LOG_LEVEL</Key>
    <DefaultThreshold>DEBUG</DefaultThreshold>
    <MDCValueLevelPair>
      <value>TRACE</value>
      <level>TRACE</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>DEBUG</value>
      <level>DEBUG</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>INFO</value>
      <level>INFO</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>WARN</value>
      <level>WARN</level>
    </MDCValueLevelPair>
    <MDCValueLevelPair>
      <value>ERROR</value>
      <level>ERROR</level>
    </MDCValueLevelPair>
  </turboFilter>
  ......
</configuration>
MDC.put("LOG_LEVEL", "INFO");

3

অন্যদের দ্বারা নির্দেশিত হিসাবে, আপনি কেবল তৈরি mockAppenderএবং তারপরে একটি LoggingEventউদাহরণ তৈরি করেন যা লগিং ইভেন্টটি অবশ্যই নিবন্ধিত / অভ্যন্তরে ঘটে তা শোনায় mockAppender

পরীক্ষায় এটি কেমন দেখাচ্ছে তা এখানে:

import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.core.Appender;

@RunWith(MockitoJUnitRunner.class)
public class TestLogEvent {

// your Logger
private Logger log = (Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);

// here we mock the appender
@Mock
private Appender<ILoggingEvent> mockAppender;

// Captor is generic-ised with ch.qos.logback.classic.spi.LoggingEvent
@Captor
private ArgumentCaptor<LoggingEvent> captorLoggingEvent;

/**
 * set up the test, runs before each test
 */
@Before
public void setUp() {
    log.addAppender(mockAppender);
}

/**
 * Always have this teardown otherwise we can stuff up our expectations. 
 * Besides, it's good coding practise
 */
@After
public void teardown() {
    log.detachAppender(mockAppender);
}


// Assuming this is your method
public void yourMethod() {
    log.info("hello world");
}

@Test
public void testYourLoggingEvent() {

    //invoke your method
    yourMethod();

    // now verify our logging interaction
    // essentially appending the event to mockAppender
    verify(mockAppender, times(1)).doAppend(captorLoggingEvent.capture());

    // Having a generic captor means we don't need to cast
    final LoggingEvent loggingEvent = captorLoggingEvent.getValue();

    // verify that info log level is called
    assertThat(loggingEvent.getLevel(), is(Level.INFO));

    // Check the message being logged is correct
    assertThat(loggingEvent.getFormattedMessage(), containsString("hello world"));
}
}

0

আমি মনে হচ্ছে সফলতা পেয়েছি

org.jboss.logmanager.Logger logger = org.jboss.logmanager.Logger.getLogger("");
logger.setLevel(java.util.logging.Level.ALL);

তারপরে নেট থেকে বিস্তারিত লগিং পেতে, নীচেরগুলি এটি করেছে

org.slf4j.impl.SimpleLogger.setLevel(org.slf4j.impl.SimpleLogger.TRACE);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.