AdHocLogDumper { public void dumpLogs(String level, int timePeriod) throws YarnRuntimeException, IOException { synchronized (lock) { if (logFlag) { LOG.info("Attempt to dump logs when appender is already running"); throw new YarnRuntimeException("Appender is already dumping logs"); } Level targetLevel = Level.toLevel(level); Log log = LogFactory.getLog(name); appenderLevels.clear(); if (log instanceof Log4JLogger) { Logger packageLogger = ((Log4JLogger) log).getLogger(); currentLogLevel = packageLogger.getLevel(); Level currentEffectiveLevel = packageLogger.getEffectiveLevel(); Layout layout = new PatternLayout("%d{ISO8601} %p %c: %m%n"); FileAppender fApp; File file = new File(System.getProperty("yarn.log.dir"), targetFilename); try { fApp = new FileAppender(layout, file.getAbsolutePath(), false); } catch (IOException ie) { LOG .warn( "Error creating file, can't dump logs to " + file.getAbsolutePath(), ie); throw ie; } fApp.setName(AdHocLogDumper.AD_HOC_DUMPER_APPENDER); fApp.setThreshold(targetLevel); for (Enumeration appenders = Logger.getRootLogger().getAllAppenders(); appenders .hasMoreElements();) { Object obj = appenders.nextElement(); if (obj instanceof AppenderSkeleton) { AppenderSkeleton appender = (AppenderSkeleton) obj; appenderLevels.put(appender.getName(), appender.getThreshold()); appender.setThreshold(currentEffectiveLevel); } } packageLogger.addAppender(fApp); LOG.info("Dumping adhoc logs for " + name + " to " + file.getAbsolutePath() + " for " + timePeriod + " milliseconds"); packageLogger.setLevel(targetLevel); logFlag = true; TimerTask restoreLogLevel = new RestoreLogLevel(); Timer restoreLogLevelTimer = new Timer(); restoreLogLevelTimer.schedule(restoreLogLevel, timePeriod); } } } AdHocLogDumper(String name, String targetFilename); void dumpLogs(String level, int timePeriod); static final String AD_HOC_DUMPER_APPENDER; }
@Test public void testDumpingSchedulerLogs() throws Exception { Map<Appender, Priority> levels = new HashMap<>(); String logHierarchy = TestAdHocLogDumper.class.getName(); String logFilename = "test.log"; Log log = LogFactory.getLog(logHierarchy); if (log instanceof Log4JLogger) { for (Enumeration appenders = Logger.getRootLogger().getAllAppenders(); appenders .hasMoreElements();) { Object obj = appenders.nextElement(); if (obj instanceof AppenderSkeleton) { AppenderSkeleton appender = (AppenderSkeleton) obj; levels.put(appender, appender.getThreshold()); } } } AdHocLogDumper dumper = new AdHocLogDumper(logHierarchy, logFilename); dumper.dumpLogs("DEBUG", 1000); LOG.debug("test message 1"); LOG.info("test message 2"); File logFile = new File(logFilename); Assert.assertTrue(logFile.exists()); Thread.sleep(2000); long lastWrite = logFile.lastModified(); Assert.assertTrue(lastWrite < Time.now()); Assert.assertTrue(logFile.length() != 0); if (log instanceof Log4JLogger) { for (Enumeration appenders = Logger.getRootLogger().getAllAppenders(); appenders .hasMoreElements();) { Object obj = appenders.nextElement(); if (obj instanceof AppenderSkeleton) { AppenderSkeleton appender = (AppenderSkeleton) obj; Assert.assertEquals(levels.get(appender), appender.getThreshold()); } } } boolean del = logFile.delete(); if(!del) { LOG.info("Couldn't clean up after test"); } }