/** Parse the additivity option for a non-root category. */ void parseAdditivityForLogger(Properties props, Logger cat, String loggerName) { String value = OptionConverter.findAndSubst(ADDITIVITY_PREFIX + loggerName, props); LogLog.debug("Handling " + ADDITIVITY_PREFIX + loggerName + "=[" + value + "]"); // touch additivity only if necessary if ((value != null) && (!value.equals(""))) { boolean additivity = OptionConverter.toBoolean(value, true); LogLog.debug("Setting additivity for \"" + loggerName + "\" to " + additivity); cat.setAdditivity(additivity); } }
/** * 滚动文件 * * <pre> * 1.对文件名带的时间戳进行比较,确定是否更新 * 2.如果�?��更新,当前文件重命名为:原文件名+日期,重新开始写新的日志文件 * 3.根据配置的maxBackupIndex,删除过期的文件 * </pre> * * @throws IOException Signals that an I/O exception has occurred. * @version */ void rollOver() throws IOException { String datedFilename = fileName + sdf.format(now); // 如果上次写的日期跟当前日期相同,不需要换文件 if (scheduledFilename.equals(datedFilename)) { return; } // 关闭当前文件,并重命�? this.closeFile(); File target = new File(scheduledFilename); if (target.exists()) { target.delete(); } File file = new File(fileName); boolean result = file.renameTo(target); if (result) { LogLog.debug(fileName + " -> " + scheduledFilename); } else { LogLog.error("Failed to rename [" + fileName + "] to [" + scheduledFilename + "]."); } // 删除过期文件 if (maxBackupIndex > 0) { File folder = new File(file.getParent()); List<String> maxBackupIndexDates = getMaxBackupIndexDates(); for (File ff : folder.listFiles()) { // 遍历目录,将日期不在备份范围内的日志删掉 if (ff.getName().startsWith(file.getName()) && !ff.getName().equals(file.getName())) { // 获取文件名带的日期时间戳 String markedDate = ff.getName().substring(file.getName().length()); if (!maxBackupIndexDates.contains(markedDate)) { result = ff.delete(); } if (result) { LogLog.debug(ff.getName() + " -> deleted "); } else { LogLog.error("Failed to deleted old DayRollingFileAppender file :" + ff.getName()); } } } } try { // 关闭文件,多个关闭操作并行时安装�? this.setFile(fileName, false, this.bufferedIO, this.bufferSize); } catch (IOException e) { errorHandler.error("setFile(" + fileName + ", false) call failed."); } // 更新�?��更新日期�? scheduledFilename = datedFilename; }
/** This method must work for the root category as well. */ void parseCategory( Properties props, Logger logger, String optionKey, String loggerName, String value) { LogLog.debug("Parsing for [" + loggerName + "] with value=[" + value + "]."); // We must skip over ',' but not white space StringTokenizer st = new StringTokenizer(value, ","); // If value is not in the form ", appender.." or "", then we should set // the level of the loggeregory. if (!(value.startsWith(",") || value.equals(""))) { // just to be on the safe side... if (!st.hasMoreTokens()) return; String levelStr = st.nextToken(); LogLog.debug("Level token is [" + levelStr + "]."); // If the level value is inherited, set category level value to // null. We also check that the user has not specified inherited for the // root category. if (INHERITED.equalsIgnoreCase(levelStr) || NULL.equalsIgnoreCase(levelStr)) { if (loggerName.equals(INTERNAL_ROOT_NAME)) { LogLog.warn("The root logger cannot be set to null."); } else { logger.setLevel(null); } } else { logger.setLevel(OptionConverter.toLevel(levelStr, (Level) Level.DEBUG)); } LogLog.debug("Category " + loggerName + " set to " + logger.getLevel()); } // Begin by removing all existing appenders. logger.removeAllAppenders(); Appender appender; String appenderName; while (st.hasMoreTokens()) { appenderName = st.nextToken().trim(); if (appenderName == null || appenderName.equals(",")) continue; LogLog.debug("Parsing appender named \"" + appenderName + "\"."); appender = parseAppender(props, appenderName); if (appender != null) { logger.addAppender(appender); } } }
/** Read configuration options from url <code>configURL</code>. */ public void doConfigure(java.net.URL configURL, LoggerRepository hierarchy) { Properties props = new Properties(); LogLog.debug("Reading configuration from URL " + configURL); InputStream istream = null; URLConnection uConn = null; try { uConn = configURL.openConnection(); uConn.setUseCaches(false); istream = uConn.getInputStream(); props.load(istream); } catch (Exception e) { if (e instanceof InterruptedIOException || e instanceof InterruptedException) { Thread.currentThread().interrupt(); } LogLog.error("Could not read configuration file from URL [" + configURL + "].", e); LogLog.error("Ignoring configuration file [" + configURL + "]."); return; } finally { if (istream != null) { try { istream.close(); } catch (InterruptedIOException ignore) { Thread.currentThread().interrupt(); } catch (IOException ignore) { } catch (RuntimeException ignore) { } } } doConfigure(props, hierarchy); }
/** * Finalize this appender by calling the derived class' <code>close</code> method. * * @since 0.8.4 */ public void finalize() { // An appender might be closed then garbage collected. There is no // point in closing twice. if (this.closed) return; LogLog.debug("Finalizing appender named [" + name + "]."); close(); }
/** * Implements the usual roll over behaviour. * * <p>If <code>MaxBackupIndex</code> is positive, then files {<code>File.1</code>, ..., <code> * File.MaxBackupIndex -1</code>} are renamed to {<code>File.2</code>, ..., <code> * File.MaxBackupIndex</code>}. Moreover, <code>File</code> is renamed <code>File.1</code> and * closed. A new <code>File</code> is created to receive further log output. * * <p>If <code>MaxBackupIndex</code> is equal to zero, then the <code>File</code> is truncated * with no backup files created. */ public // synchronization not necessary since doAppend is alreasy synched void rollOver() { File target; File file; LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount()); LogLog.debug("maxBackupIndex=" + maxBackupIndex); // If maxBackups <= 0, then there is no file renaming to be done. if (maxBackupIndex > 0) { // Delete the oldest file, to keep Windows happy. file = new File(fileName + '.' + maxBackupIndex); if (file.exists()) file.delete(); // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2} for (int i = maxBackupIndex - 1; i >= 1; i--) { file = new File(fileName + "." + i); if (file.exists()) { target = new File(fileName + '.' + (i + 1)); LogLog.debug("Renaming file " + file + " to " + target); file.renameTo(target); } } // Rename fileName to fileName.1 target = new File(fileName + "." + 1); this.closeFile(); // keep windows happy. file = new File(fileName); LogLog.debug("Renaming file " + file + " to " + target); file.renameTo(target); } try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false, bufferedIO, bufferSize); } catch (IOException e) { LogLog.error("setFile(" + fileName + ", false) call failed.", e); } }
/** * Check the provided <code>Properties</code> object for a {@link * org.apache.log4j.spi.LoggerFactory LoggerFactory} entry specified by {@link * #LOGGER_FACTORY_KEY}. If such an entry exists, an attempt is made to create an instance using * the default constructor. This instance is used for subsequent Category creations within this * configurator. * * @see #parseCatsAndRenderers */ protected void configureLoggerFactory(Properties props) { String factoryClassName = OptionConverter.findAndSubst(LOGGER_FACTORY_KEY, props); if (factoryClassName != null) { LogLog.debug("Setting category factory to [" + factoryClassName + "]."); loggerFactory = (LoggerFactory) OptionConverter.instantiateByClassName( factoryClassName, LoggerFactory.class, loggerFactory); PropertySetter.setProperties(loggerFactory, props, FACTORY_PREFIX + "."); } }
public void run() { while (!isInterrupted()) { try { ServerSocket serverSocket = new ServerSocket(port); while (true) { Socket socket = serverSocket.accept(); LogLog.debug("Connected to client at " + socket.getInetAddress()); new Thread(new HUPNode(socket, er)).start(); } } catch (Exception e) { e.printStackTrace(); } } }
/** * Read configuration options from <code>properties</code>. * * <p>See {@link #doConfigure(String, LoggerRepository)} for the expected format. */ public void doConfigure(Properties properties, LoggerRepository hierarchy) { repository = hierarchy; String value = properties.getProperty(LogLog.DEBUG_KEY); if (value == null) { value = properties.getProperty("log4j.configDebug"); if (value != null) LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead."); } if (value != null) { LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true)); } // // if log4j.reset=true then // reset hierarchy String reset = properties.getProperty(RESET_KEY); if (reset != null && OptionConverter.toBoolean(reset, false)) { hierarchy.resetConfiguration(); } String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX, properties); if (thresholdStr != null) { hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr, (Level) Level.ALL)); LogLog.debug("Hierarchy threshold set to [" + hierarchy.getThreshold() + "]."); } configureRootCategory(properties, hierarchy); configureLoggerFactory(properties); parseCatsAndRenderers(properties, hierarchy); LogLog.debug("Finished configuring."); // We don't want to hold references to appenders preventing their // garbage collection. registry.clear(); }
/** AppenderSkeleton回调函数, 事件到达时将时间放入Queue. */ @Override public void append(LoggingEvent event) { if (queue == null) { queue = QueuesHolder.getQueue(queueName); } boolean sucess = queue.offer(event); if (sucess) { LogLog.debug( "put event to queue success:" + new LoggingEventWrapper(event).convertToString()); } else { LogLog.error("Put event to queue fail:" + new LoggingEventWrapper(event).convertToString()); } }
void configureRootCategory(Properties props, LoggerRepository hierarchy) { String effectiveFrefix = ROOT_LOGGER_PREFIX; String value = OptionConverter.findAndSubst(ROOT_LOGGER_PREFIX, props); if (value == null) { value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props); effectiveFrefix = ROOT_CATEGORY_PREFIX; } if (value == null) LogLog.debug("Could not find root logger information. Is this OK?"); else { Logger root = hierarchy.getRootLogger(); synchronized (root) { parseCategory(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value); } } }
public void run() { try { String line = dis.readUTF(); LogLog.debug("Got external roll over signal."); if (ExternallyRolledFileAppender.ROLL_OVER.equals(line)) { synchronized (er) { er.rollOver(); } dos.writeUTF(ExternallyRolledFileAppender.OK); } else { dos.writeUTF("Expecting [RollOver] string."); } dos.close(); } catch (Exception e) { LogLog.error("Unexpected exception. Exiting HUPNode.", e); } }
public void activateOptions() { LogLog.debug("DBAppender.activateOptions called"); if (connectionSource == null) { throw new IllegalStateException("DBAppender cannot function without a connection source"); } sqlDialect = Util.getDialectFromCode(connectionSource.getSQLDialectCode()); if (GET_GENERATED_KEYS_METHOD != null) { cnxSupportsGetGeneratedKeys = connectionSource.supportsGetGeneratedKeys(); } else { cnxSupportsGetGeneratedKeys = false; } cnxSupportsBatchUpdates = connectionSource.supportsBatchUpdates(); if (!cnxSupportsGetGeneratedKeys && (sqlDialect == null)) { throw new IllegalStateException( "DBAppender cannot function if the JDBC driver does not support getGeneratedKeys method *and* without a specific SQL dialect"); } // all nice and dandy on the eastern front super.activateOptions(); }
void printPeriodicity(int type) { switch (type) { case TOP_OF_MINUTE: LogLog.debug("Appender [" + name + "] to be rolled every minute."); break; case TOP_OF_HOUR: LogLog.debug("Appender [" + name + "] to be rolled on top of every hour."); break; case HALF_DAY: LogLog.debug("Appender [" + name + "] to be rolled at midday and midnight."); break; case TOP_OF_DAY: LogLog.debug("Appender [" + name + "] to be rolled at midnight."); break; case TOP_OF_WEEK: LogLog.debug("Appender [" + name + "] to be rolled at start of week."); break; case TOP_OF_MONTH: LogLog.debug("Appender [" + name + "] to be rolled at start of every month."); break; default: LogLog.warn("Unknown periodicity for appender [" + name + "]."); } }
void parseAppenderFilters(Properties props, String appenderName, Appender appender) { // extract filters and filter options from props into a hashtable mapping // the property name defining the filter class to a list of pre-parsed // name-value pairs associated to that filter final String filterPrefix = APPENDER_PREFIX + appenderName + ".filter."; int fIdx = filterPrefix.length(); Hashtable filters = new Hashtable(); Enumeration e = props.keys(); String name = ""; while (e.hasMoreElements()) { String key = (String) e.nextElement(); if (key.startsWith(filterPrefix)) { int dotIdx = key.indexOf('.', fIdx); String filterKey = key; if (dotIdx != -1) { filterKey = key.substring(0, dotIdx); name = key.substring(dotIdx + 1); } Vector filterOpts = (Vector) filters.get(filterKey); if (filterOpts == null) { filterOpts = new Vector(); filters.put(filterKey, filterOpts); } if (dotIdx != -1) { String value = OptionConverter.findAndSubst(key, props); filterOpts.add(new NameValue(name, value)); } } } // sort filters by IDs, insantiate filters, set filter options, // add filters to the appender Enumeration g = new SortedKeyEnumeration(filters); while (g.hasMoreElements()) { String key = (String) g.nextElement(); String clazz = props.getProperty(key); if (clazz != null) { LogLog.debug( "Filter key: [" + key + "] class: [" + props.getProperty(key) + "] props: " + filters.get(key)); Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz, Filter.class, null); if (filter != null) { PropertySetter propSetter = new PropertySetter(filter); Vector v = (Vector) filters.get(key); Enumeration filterProps = v.elements(); while (filterProps.hasMoreElements()) { NameValue kv = (NameValue) filterProps.nextElement(); propSetter.setProperty(kv.key, kv.value); } propSetter.activate(); LogLog.debug( "Adding filter of type [" + filter.getClass() + "] to appender named [" + appender.getName() + "]."); appender.addFilter(filter); } } else { LogLog.warn("Missing class definition for filter: [" + key + "]"); } } }
Appender parseAppender(Properties props, String appenderName) { Appender appender = registryGet(appenderName); if ((appender != null)) { LogLog.debug("Appender \"" + appenderName + "\" was already parsed."); return appender; } // Appender was not previously initialized. String prefix = APPENDER_PREFIX + appenderName; String layoutPrefix = prefix + ".layout"; appender = (Appender) OptionConverter.instantiateByKey(props, prefix, org.apache.log4j.Appender.class, null); if (appender == null) { LogLog.error("Could not instantiate appender named \"" + appenderName + "\"."); return null; } appender.setName(appenderName); if (appender instanceof OptionHandler) { if (appender.requiresLayout()) { Layout layout = (Layout) OptionConverter.instantiateByKey(props, layoutPrefix, Layout.class, null); if (layout != null) { appender.setLayout(layout); LogLog.debug("Parsing layout options for \"" + appenderName + "\"."); // configureOptionHandler(layout, layoutPrefix + ".", props); PropertySetter.setProperties(layout, props, layoutPrefix + "."); LogLog.debug("End of parsing for \"" + appenderName + "\"."); } } final String errorHandlerPrefix = prefix + ".errorhandler"; String errorHandlerClass = OptionConverter.findAndSubst(errorHandlerPrefix, props); if (errorHandlerClass != null) { ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByKey( props, errorHandlerPrefix, ErrorHandler.class, null); if (eh != null) { appender.setErrorHandler(eh); LogLog.debug("Parsing errorhandler options for \"" + appenderName + "\"."); parseErrorHandler(eh, errorHandlerPrefix, props, repository); final Properties edited = new Properties(); final String[] keys = new String[] { errorHandlerPrefix + "." + ROOT_REF, errorHandlerPrefix + "." + LOGGER_REF, errorHandlerPrefix + "." + APPENDER_REF_TAG }; for (Iterator iter = props.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); int i = 0; for (; i < keys.length; i++) { if (keys[i].equals(entry.getKey())) break; } if (i == keys.length) { edited.put(entry.getKey(), entry.getValue()); } } PropertySetter.setProperties(eh, edited, errorHandlerPrefix + "."); LogLog.debug("End of errorhandler parsing for \"" + appenderName + "\"."); } } // configureOptionHandler((OptionHandler) appender, prefix + ".", props); PropertySetter.setProperties(appender, props, prefix + "."); LogLog.debug("Parsed \"" + appenderName + "\" options."); } parseAppenderFilters(props, appenderName, appender); registryPut(appender); return appender; }
/** @param connectionSource The connectionSource to set. */ public void setConnectionSource(ConnectionSource connectionSource) { LogLog.debug("setConnectionSource called for DBAppender"); this.connectionSource = connectionSource; }
protected void append(LoggingEvent event) { Connection connection = null; try { connection = connectionSource.getConnection(); connection.setAutoCommit(false); PreparedStatement insertStatement; if (cnxSupportsGetGeneratedKeys) { insertStatement = connection.prepareStatement(insertSQL, Statement.RETURN_GENERATED_KEYS); } else { insertStatement = connection.prepareStatement(insertSQL); } /* insertStatement.setLong(1, event.getSequenceNumber());*/ insertStatement.setLong(1, 0); insertStatement.setLong(2, event.getTimeStamp()); insertStatement.setString(3, event.getRenderedMessage()); insertStatement.setString(4, event.getLoggerName()); insertStatement.setString(5, event.getLevel().toString()); insertStatement.setString(6, event.getNDC()); insertStatement.setString(7, event.getThreadName()); insertStatement.setShort(8, DBHelper.computeReferenceMask(event)); LocationInfo li; if (event.locationInformationExists() || locationInfo) { li = event.getLocationInformation(); } else { li = LocationInfo.NA_LOCATION_INFO; } insertStatement.setString(9, li.getFileName()); insertStatement.setString(10, li.getClassName()); insertStatement.setString(11, li.getMethodName()); insertStatement.setString(12, li.getLineNumber()); int updateCount = insertStatement.executeUpdate(); if (updateCount != 1) { LogLog.warn("Failed to insert loggingEvent"); } ResultSet rs = null; Statement idStatement = null; boolean gotGeneratedKeys = false; if (cnxSupportsGetGeneratedKeys) { try { rs = (ResultSet) GET_GENERATED_KEYS_METHOD.invoke(insertStatement, null); gotGeneratedKeys = true; } catch (InvocationTargetException ex) { Throwable target = ex.getTargetException(); if (target instanceof SQLException) { throw (SQLException) target; } throw ex; } catch (IllegalAccessException ex) { LogLog.warn("IllegalAccessException invoking PreparedStatement.getGeneratedKeys", ex); } } if (!gotGeneratedKeys) { insertStatement.close(); insertStatement = null; idStatement = connection.createStatement(); idStatement.setMaxRows(1); rs = idStatement.executeQuery(sqlDialect.getSelectInsertId()); } // A ResultSet cursor is initially positioned before the first row; the // first call to the method next makes the first row the current row rs.next(); int eventId = rs.getInt(1); rs.close(); // we no longer need the insertStatement if (insertStatement != null) { insertStatement.close(); insertStatement = null; } if (idStatement != null) { idStatement.close(); idStatement = null; } Set propertiesKeys = event.getPropertyKeySet(); if (propertiesKeys.size() > 0) { PreparedStatement insertPropertiesStatement = connection.prepareStatement(insertPropertiesSQL); for (Iterator i = propertiesKeys.iterator(); i.hasNext(); ) { String key = (String) i.next(); String value = event.getProperty(key); // LogLog.info("id " + eventId + ", key " + key + ", value " + value); insertPropertiesStatement.setInt(1, eventId); insertPropertiesStatement.setString(2, key); insertPropertiesStatement.setString(3, value); if (cnxSupportsBatchUpdates) { insertPropertiesStatement.addBatch(); } else { insertPropertiesStatement.execute(); } } if (cnxSupportsBatchUpdates) { insertPropertiesStatement.executeBatch(); } insertPropertiesStatement.close(); insertPropertiesStatement = null; } String[] strRep = event.getThrowableStrRep(); if (strRep != null) { LogLog.debug("Logging an exception"); PreparedStatement insertExceptionStatement = connection.prepareStatement(insertExceptionSQL); for (short i = 0; i < strRep.length; i++) { insertExceptionStatement.setInt(1, eventId); insertExceptionStatement.setShort(2, i); insertExceptionStatement.setString(3, strRep[i]); if (cnxSupportsBatchUpdates) { insertExceptionStatement.addBatch(); } else { insertExceptionStatement.execute(); } } if (cnxSupportsBatchUpdates) { insertExceptionStatement.executeBatch(); } insertExceptionStatement.close(); insertExceptionStatement = null; } connection.commit(); } catch (Throwable sqle) { LogLog.error("problem appending event", sqle); } finally { DBHelper.closeConnection(connection); } }
/** * Implements the usual roll over behaviour. * * <p>If <code>MaxBackupIndex</code> is positive, then files { <code>File.1</code>, ..., <code> * File.MaxBackupIndex -1</code> are renamed to {<code>File.2</code>, ..., <code> * File.MaxBackupIndex</code> . Moreover, <code>File</code> is renamed <code>File.1</code> and * closed. A new <code>File</code> is created to receive further log output. * * <p>If <code>MaxBackupIndex</code> is equal to zero, then the <code>File</code> is truncated * with no backup files created. */ public // synchronization not necessary since doAppend is alreasy synched void rollOver(int rolltype) throws IOException { // if (RollingFileType == rolltype) { File target; File file; LogLog.debug("rolling over count=" + ((CountingQuietWriter) qw).getCount()); LogLog.debug("maxBackupIndex=" + maxBackupIndex); // If maxBackups <= 0, then there is no file renaming to be done. if (maxBackupIndex > 0) { file = new File(buildLogFilePathAnddeleteTimeoutFile(maxBackupIndex)); if (file.exists()) file.delete(); // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, // ..., 3, 2} for (int i = maxBackupIndex - 1; i >= 1; i--) { file = new File(buildLogFilePathAnddeleteTimeoutFile(i)); if (file.exists()) { target = new File(buildLogFilePathAnddeleteTimeoutFile(i + 1)); LogLog.debug("Renaming file " + file + " to " + target); file.renameTo(target); } } // Rename fileName to fileName.1 target = new File(buildLogFilePathAnddeleteTimeoutFile(1)); this.closeFile(); // keep windows happy. file = new File(fileName); LogLog.debug("Renaming file " + file + " to " + target); file.renameTo(target); } try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, false, bufferedIO, bufferSize); } catch (IOException e) { LogLog.error("setFile(" + fileName + ", false) call failed.", e); } } else if (DailyRollingFileType == rolltype) { /* Compute filename, but only if datePattern is specified */ if (datePattern == null) { errorHandler.error("Missing DatePattern option in rollOver()."); return; } String datedFile = sdf.format(now); // It is too early to roll over because we are still within the // bounds of the current interval. Rollover will occur once the // next interval is reached. if (scheduledDate.equals(datedFile)) { return; } // close current file, and rename it to datedFilename this.closeFile(); String targetfilename = buildLogFilePathAnddeleteTimeoutFile(-1); fileName = targetfilename; try { // This will also close the file. This is OK since multiple // close operations are safe. this.setFile(fileName, true, this.bufferedIO, this.bufferSize); } catch (IOException e) { errorHandler.error("setFile(" + fileName + ", false) call failed."); } scheduledDate = datedFile; } }