static { ClassLoader prevLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(TCLoggingLog4J.class.getClassLoader()); Log4jSafeInit.init(); Logger customerLogger = Logger.getLogger(CUSTOMER_LOGGER_NAMESPACE); Logger consoleLogger = Logger.getLogger(CONSOLE_LOGGER_NAME); console = new TCLoggerImpl(CONSOLE_LOGGER_NAME); consoleAppender = new TCConsoleAppender(new PatternLayout(CONSOLE_PATTERN), ConsoleAppender.SYSTEM_OUT); operatorEventLogger = new TCLoggerImpl(OPERATOR_EVENT_LOGGER_NAME); List<Logger> internalLoggers = new ArrayList<Logger>(); for (String nameSpace : INTERNAL_LOGGER_NAMESPACES) { internalLoggers.add(Logger.getLogger(nameSpace)); } /** * Don't add consoleLogger to allLoggers because it's a child of customerLogger, so it shouldn't * get any appenders. If you DO add consoleLogger here, you'll see duplicate messages in the log * file. */ allLoggers = createAllLoggerList(internalLoggers, customerLogger); try { boolean customLogging = customConfiguration(); boolean isDev = customLogging ? false : developmentConfiguration(); if (!customLogging) { for (Logger internalLogger : internalLoggers) { internalLogger.setLevel(Level.INFO); } customerLogger.setLevel(Level.INFO); consoleLogger.setLevel(Level.INFO); if (!isDev) { // Only the console logger goes to the console (by default) consoleLogger.addAppender(consoleAppender); } else { consoleAppender.setLayout(new PatternLayout(CONSOLE_PATTERN_DEVELOPMENT)); // For non-customer environments, send all logging to the console... Logger.getRootLogger().addAppender(consoleAppender); } } delegateFileAppender = new DelegatingAppender(new NullAppender()); addToAllLoggers(delegateFileAppender); BufferingAppender realBufferingAppender; realBufferingAppender = new BufferingAppender(MAX_BUFFERED_LOG_MESSAGES); realBufferingAppender.setName("buffering appender"); delegateBufferingAppender = new DelegatingAppender(realBufferingAppender); addToAllLoggers(delegateBufferingAppender); buffering = true; if (!isDev) { console.info("New logging session started."); } writeVersion(); writePID(); writeLoggingConfigurations(); } finally { Thread.currentThread().setContextClassLoader(prevLoader); } }
@SuppressWarnings("resource") public void setLogDirectory(File theDirectory, int processType) { Assert.assertNotNull(theDirectory); if (theDirectory.getName().trim().equalsIgnoreCase("stdout:") || theDirectory.getName().trim().equalsIgnoreCase("stderr:")) { if (currentLoggingDirectory != null && currentLoggingDirectory.getName().trim().equalsIgnoreCase(theDirectory.getName())) { // Nothing to do; great! return; } delegateFileAppender.setDelegate(new NullAppender()); consoleAppender.setLayout(new PatternLayout(CONSOLE_LOGGING_ONLY_PATTERN)); // Logger.addAppender() doesn't double-add, so this is safe Logger.getRootLogger().addAppender(consoleAppender); if (buffering) { BufferingAppender realBufferingAppender = (BufferingAppender) delegateBufferingAppender.setDelegate(new NullAppender()); realBufferingAppender.stopAndSendContentsTo(consoleAppender); realBufferingAppender.close(); buffering = false; } boolean stdout = theDirectory.getName().trim().equalsIgnoreCase("stdout:"); getConsoleLogger() .info( "All logging information now output to standard " + (stdout ? "output" : "error") + "."); return; } synchronized (TCLoggingLog4J.class) { if (currentLoggingDirectory != null) { try { if (theDirectory.getCanonicalPath().equals(currentLoggingDirectory.getCanonicalPath())) { return; } } catch (IOException ioe) { // oh, well -- what can we do? we'll continue on. } } } try { FileUtils.forceMkdir(theDirectory); } catch (IOException ioe) { reportLoggingError( "We can't create the directory '" + theDirectory.getAbsolutePath() + "' that you specified for your logs.", ioe); return; } if (!theDirectory.canWrite()) { // formatting reportLoggingError( "The log directory, '" + theDirectory.getAbsolutePath() + "', can't be written to.", null); return; } FileLock thisDirectoryLock = null; if (!lockingDisabled) { File lockFile = new File(theDirectory, LOCK_FILE_NAME); try { lockFile.createNewFile(); Assert.eval(lockFile.exists()); FileChannel channel = new RandomAccessFile(lockFile, "rw").getChannel(); thisDirectoryLock = channel.tryLock(); if (thisDirectoryLock == null) { reportLoggingError( "The log directory, '" + theDirectory.getAbsolutePath() + "', is already in use by another " + "Terracotta process. Logging will proceed to the console only.", null); return; } } catch (OverlappingFileLockException ofle) { // This VM already holds the lock; no problem } catch (IOException ioe) { reportLoggingError( "We can't lock the file '" + lockFile.getAbsolutePath() + "', to make sure that only one " + "Terracotta process is using this directory for logging. This may be a permission " + "issue, or some unexpected error. Logging will proceed to the console only.", ioe); return; } } RollingFileAppender newFileAppender; String logFileName; switch (processType) { case PROCESS_TYPE_L1: logFileName = TERRACOTTA_L1_LOG_FILE_NAME; break; case PROCESS_TYPE_L2: logFileName = TERRACOTTA_L2_LOG_FILE_NAME; break; case PROCESS_TYPE_GENERIC: logFileName = TERRACOTTA_GENERIC_LOG_FILE_NAME; break; default: throw Assert.failure("Unknown process type: " + processType); } String logFilePath = new File(theDirectory, logFileName).getAbsolutePath(); synchronized (TCLoggingLog4J.class) { try { TCProperties props = TCPropertiesImpl.getProperties().getPropertiesFor(TCPropertiesConsts.LOGGING_CATEGORY); newFileAppender = new TCRollingFileAppender(new PatternLayout(FILE_AND_JMX_PATTERN), logFilePath, true); newFileAppender.setName("file appender"); int maxLogFileSize = props.getInt(MAX_LOG_FILE_SIZE_PROPERTY, DEFAULT_MAX_LOG_FILE_SIZE); newFileAppender.setMaxFileSize(maxLogFileSize + "MB"); newFileAppender.setMaxBackupIndex(props.getInt(MAX_BACKUPS_PROPERTY, DEFAULT_MAX_BACKUPS)); // This makes us start with a new file each time. newFileAppender.rollOver(); // Note: order of operations is very important here. We start the new appender before we // close and remove the // old one so that you don't drop any log records. Appender oldFileAppender = delegateFileAppender.setDelegate(newFileAppender); if (oldFileAppender != null) { oldFileAppender.close(); } if (buffering) { BufferingAppender realBufferingAppender = (BufferingAppender) delegateBufferingAppender.setDelegate(new NullAppender()); realBufferingAppender.stopAndSendContentsTo(delegateFileAppender); realBufferingAppender.close(); buffering = false; } currentLoggingDirectory = theDirectory; if (currentLoggingDirectoryFileLock != null) currentLoggingDirectoryFileLock.release(); currentLoggingDirectoryFileLock = thisDirectoryLock; } catch (IOException ioe) { reportLoggingError( "We were unable to switch the logging system to log to '" + logFilePath + "'.", ioe); } } getConsoleLogger().info("Log file: '" + logFilePath + "'."); writeSystemProperties(); }