Package com.cisco.oss.foundation.logging

Source Code of com.cisco.oss.foundation.logging.FoundationHierarchyEventListener

/*
* Copyright 2014 Cisco Systems, Inc.
*
*  Licensed under the Apache License, Version 2.0 (the "License");
*  you may not use this file except in compliance with the License.
*  You may obtain a copy of the License at
*
*  http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/

/**
*
*/
package com.cisco.oss.foundation.logging;

import com.cisco.oss.foundation.logging.appender.FoundationFileRollingAppender;
import com.cisco.oss.foundation.logging.appender.FoundationRollEventListener;
import org.apache.log4j.*;
import org.apache.log4j.appender.TimeAndSizeRollingAppender;
import org.apache.log4j.spi.HierarchyEventListener;

import java.util.Enumeration;
import java.util.HashMap;

/**
* Override conversion pattern to the Foundation default if pattern was not speicified in the log4j.properties file. This applies only if the appender has a Layout of PatternLayout or EnhancedPatternLayout.
*
* @author Yair Ogen
*/
public class FoundationHierarchyEventListener implements HierarchyEventListener {

  private static HashMap<String,AsyncAppender> asyncAppenders =  new HashMap<String,AsyncAppender>();

  /**
   * the default for max files to be rolled.
   */
  private static final int Foundation_MAX_ROLL_COUNT = 100;

  /**
   * The log4j appender default max rolling files number.
   */
  private static final int LOG4J_MAX_ROLL_COUNT = 10;

  /**
   * In this method perform the actual override in runtime.
   *
   * @see org.apache.log4j.spi.HierarchyEventListener#addAppenderEvent(org.apache.log4j.Category, org.apache.log4j.Appender)
   */
  public void addAppenderEvent(final Category cat, final Appender appender) {

    updateDefaultLayout(appender);

    if (appender instanceof FoundationFileRollingAppender) {
      final FoundationFileRollingAppender timeSizeRollingAppender = (FoundationFileRollingAppender) appender;

      // update the appender with default vales such as logging pattern, file size etc.
      //updateDefaultTimeAndSizeRollingAppender(timeSizeRollingAppender);

      // read teh proeprties and determine if archiving should be enabled.
      updateArchivingSupport(timeSizeRollingAppender);

      // by default add the rolling file listener to enable application
      // state.
      timeSizeRollingAppender.setFileRollEventListener(FoundationRollEventListener.class.getName());

      boolean rollOnStartup = true;

      if (FoundationLogger.log4jConfigProps != null && FoundationLogger.log4jConfigProps.containsKey(FondationLoggerConstants.Foundation_ROLL_ON_STARTUP.toString())) {
        rollOnStartup = Boolean.valueOf(FoundationLogger.log4jConfigProps.getProperty(FondationLoggerConstants.Foundation_ROLL_ON_STARTUP.toString()));
      }

      timeSizeRollingAppender.setRollOnStartup(rollOnStartup);

      // refresh the appender
      timeSizeRollingAppender.activateOptions();

     
    //  timeSizeRollingAppender.setOriginalLayout(); //So application state will not make any problems

    }else if(!(appender instanceof FoundationFileRollingAppender) && (appender instanceof TimeAndSizeRollingAppender)){ //TimeAndSizeRollingAppender
      final TimeAndSizeRollingAppender timeSizeRollingAppender = (TimeAndSizeRollingAppender) appender;

      // update the appender with default vales such as logging pattern, file size etc.
      updateDefaultTimeAndSizeRollingAppender(timeSizeRollingAppender);

      // read teh proeprties and determine if archiving should be enabled.
      updateArchivingSupport(timeSizeRollingAppender);

      // by default add the rolling file listener to enable application
      // state.
      timeSizeRollingAppender.setFileRollEventListener(FoundationRollEventListener.class.getName());

      boolean rollOnStartup = true;

      if (FoundationLogger.log4jConfigProps != null && FoundationLogger.log4jConfigProps.containsKey(FondationLoggerConstants.Foundation_ROLL_ON_STARTUP.toString())) {
        rollOnStartup = Boolean.valueOf(FoundationLogger.log4jConfigProps.getProperty(FondationLoggerConstants.Foundation_ROLL_ON_STARTUP.toString()));
      }

      timeSizeRollingAppender.setRollOnStartup(rollOnStartup);

      // refresh the appender
      timeSizeRollingAppender.activateOptions();

     
    //  timeSizeRollingAppender.setOriginalLayout();
    }
    if ( ! (appender instanceof org.apache.log4j.AsyncAppender))
            initiateAsyncSupport(appender);

  }

  public void initiateAsyncSupport(final Appender appender) {

    final String asyncAppenderReferencesKey = FondationLoggerConstants.Foundation_ASYNC_REF.toString();

    // first check if we have some appender references. if not - do nothing.
    if (FoundationLogger.log4jConfigProps != null && FoundationLogger.log4jConfigProps.containsKey(asyncAppenderReferencesKey)) {

      // if the async appender is null or it was closed by log4j as part of the log4j reload we need to create a new instance.
  //    if (asyncAppenders == null || isAsyncAppenderClosed()) {
       
  //    }

      String asyncAppenderReferences = FoundationLogger.log4jConfigProps.getProperty(asyncAppenderReferencesKey);
      String[] asyncAppenderReferencesList = asyncAppenderReferences.split(",");

      // for each appender ref, we need to check if should be added to async appender.
      for (String asyncAppenderRef : asyncAppenderReferencesList) {

        // validate the appender ref matches: "[appender_name]"
        if (!(asyncAppenderRef.startsWith("[") && asyncAppenderRef.endsWith("]"))) {

          // write to error stream as we do can not yet use the logging API
          System.err.println("could not parse async appender ref. Illegal format. " + asyncAppenderRef);
          // ignore
          continue;

        } else {

          // get the "real" appender ref name
          asyncAppenderRef = asyncAppenderRef.substring(1, asyncAppenderRef.lastIndexOf("]"));

          if (appender.getName().equals(asyncAppenderRef)) {

            // check if the appender already exists in the async appender
            Appender appenderRefInAsync = asyncAppenders.get(appender.getName());

            if (appenderRefInAsync != null) {
              asyncAppenders.remove(appender.getName());
            }
            AsyncAppender async=createAsyncAppender();
            async.addAppender(appender);
            async.activateOptions();
            asyncAppenders.put(appender.getName(),async);
           

            Enumeration currentLoggers = LogManager.getLoggerRepository().getCurrentLoggers();
            while (currentLoggers.hasMoreElements()) {
              Logger logger = (Logger) currentLoggers.nextElement();
              if (logger.getAppender(appender.getName()) != null) {
                logger.removeAppender(appender.getName());
                logger.addAppender(async);
              }
            }
           
            if(LogManager.getRootLogger().getAppender(appender.getName()) != null) {
              LogManager.getRootLogger().removeAppender(appender.getName());
              LogManager.getRootLogger().addAppender(async);
            }

            // Logger.getRootLogger().removeAppender(asyncAppender);
            // Logger.getRootLogger().addAppender(asyncAppender);
            //
            // //remove the appender from the root logger so we don't have 2 appenders write to the same file.
            // Logger.getRootLogger().removeAppender(appender);

          }

        }
      }
    }
  }

  private AsyncAppender createAsyncAppender() {
    AsyncAppender asyncAppender = new AsyncAppender();
    String bufferSize = FoundationLogger.log4jConfigProps.getProperty(FondationLoggerConstants.Foundation_ASYNC_BUFFER_SIZE.toString(), "2500");
    try {
      asyncAppender.setBufferSize(Integer.parseInt(bufferSize));
    } catch (NumberFormatException e) {
      asyncAppender.setBufferSize(2500);
    }

  //  updateDispatcher(asyncAppender);

    return asyncAppender;
  }

//  private void updateDispatcher(AsyncAppender asyncAppender) {
//    try {
//      String fieldName = "dispatcher";
//      Field dispatcherField = getField(fieldName);
//      Thread thread = (Thread) dispatcherField.get(asyncAppender);
//      if (thread != null) {
//        thread.stop();
//      }
//
//      fieldName = "buffer";
//      Field bufferField = getField(fieldName);
//
//      fieldName = "discardMap";
//      Field discardMapField = getField(fieldName);
//
//      fieldName = "appenders";
//      Field appendersField = getField(fieldName);
//
//      FoundationLoggingDispatcher dispatcher = new FoundationLoggingDispatcher(asyncAppender, (List<LoggingEvent>) bufferField.get(asyncAppender), (Map<String, DiscardSummary>) discardMapField.get(asyncAppender), (AppenderAttachableImpl) appendersField.get(asyncAppender));
//      Thread dispatcherThread = new Thread(dispatcher);
//      dispatcherThread.setDaemon(true);
//
//      dispatcherThread.setName("AsyncAppender-Dispatcher-" + dispatcherThread.getName());
//      dispatcherThread.start();
//     
//      dispatcherField.set(asyncAppender, dispatcherThread);
//     
//    } catch (IllegalArgumentException e) {
//      throw new IllegalArgumentException(e);
//    } catch (NoSuchFieldException e) {
//      throw new IllegalArgumentException(e);
//    } catch (IllegalAccessException e) {
//      throw new IllegalArgumentException(e);
//    }
//  }

//  private Field getField(String fieldName) throws NoSuchFieldException {
//    Field dispatcherField = AsyncAppender.class.getDeclaredField(fieldName);
//    dispatcherField.setAccessible(true);
//    return dispatcherField;
//  }
/*does not needed anymore since we create an Async appender every time.
  private boolean isAsyncAppenderClosed() {
    // no other way than use reflection to validate the state of the appender.
    // NOTE: this code will break if java SecurityManager is used.
    try {
      Field closedField = AppenderSkeleton.class.getDeclaredField("closed");
      closedField.setAccessible(true);
      boolean closed = (Boolean) closedField.get(asyncAppender);

      return closed;
    } catch (Exception e) {
      System.err.println("Cannot check AsyncAppender state. Error is: " + e);
      // assume closed in case of error.
      return true;
    }
  }
*/
  /**
   * @param timeSizeRollingAppender
   */
  private void updateArchivingSupport(final FoundationFileRollingAppender timeSizeRollingAppender) {

    boolean shouldArchive = true;

    final String FoundationFileArchiveKey = FondationLoggerConstants.Foundation_FILE_ARCHIVE.toString();

    if (FoundationLogger.log4jConfigProps != null && FoundationLogger.log4jConfigProps.containsKey(FoundationFileArchiveKey)) {
      shouldArchive = Boolean.valueOf(FoundationLogger.log4jConfigProps.getProperty(FoundationFileArchiveKey));
    }

    if (shouldArchive) {
      if (OperatingSystem.getOperatingSystem().equals(OperatingSystem.Windows)) {
        timeSizeRollingAppender.setCompressionAlgorithm(FondationLoggerConstants.ZIP.toString());
      } else {
        timeSizeRollingAppender.setCompressionAlgorithm(FondationLoggerConstants.GZIP.toString());
      }
    }
  }

  /**
   * Set default values for the TimeAndSizeRollingAppender appender
   *
   * @param appender
   */
  private void updateDefaultTimeAndSizeRollingAppender(final FoundationFileRollingAppender appender) {

    if (appender.getDatePattern().trim().length() == 0) {
      appender.setDatePattern(FondationLoggerConstants.DEFAULT_DATE_PATTERN.toString());
    }
   
    String maxFileSizeKey = "log4j.appender."+appender.getName()+".MaxFileSize";
    appender.setMaxFileSize(FoundationLogger.log4jConfigProps.getProperty(maxFileSizeKey, FondationLoggerConstants.Foundation_MAX_FILE_SIZE.toString()));

//    if (appender.getMaxFileSize() == null || appender.getMaxFileSize().equals(FondationLoggerConstants.DEFAULT_FILE_SIZE.toString())) {
//      appender.setMaxFileSize(FondationLoggerConstants.Foundation_MAX_FILE_SIZE.toString());
//    }

    String maxRollCountKey = "log4j.appender."+appender.getName()+".MaxRollFileCount";
    appender.setMaxRollFileCount(Integer.parseInt(FoundationLogger.log4jConfigProps.getProperty(maxRollCountKey,"100")));
  }

  private void updateDefaultLayout(final Appender appender) {
    Layout layout = appender.getLayout();

    if (layout == null) {
      layout = new FoundationLoggingPatternLayout();
      appender.setLayout(layout);
    }

    if (layout instanceof EnhancedPatternLayout) {

      final EnhancedPatternLayout enhancedPatternLayout = (EnhancedPatternLayout) layout;
      String conversionPattern = enhancedPatternLayout.getConversionPattern();

      if (shouldUpdatePattern(conversionPattern)) {
        conversionPattern = FondationLoggerConstants.DEFAULT_CONV_PATTERN.toString();
        enhancedPatternLayout.setConversionPattern(conversionPattern);
      }

    } else if (layout instanceof PatternLayout) {

      final PatternLayout patternLayout = (PatternLayout) layout;
      String conversionPattern = patternLayout.getConversionPattern();

      if (shouldUpdatePattern(conversionPattern)) {
        conversionPattern = FondationLoggerConstants.DEFAULT_CONV_PATTERN.toString();
        patternLayout.setConversionPattern(conversionPattern);
      }

    }
  }

  private boolean shouldUpdatePattern(final String conversionPattern) {
    return conversionPattern == null || conversionPattern.equals(FoundationLoggingPatternLayout.DEFAULT_CONVERSION_PATTERN) || conversionPattern.equals(PatternLayout.DEFAULT_CONVERSION_PATTERN) || conversionPattern.equals("");
  }

  /**
   * Not implemented by this listener.
   *
   * @see org.apache.log4j.spi.HierarchyEventListener#removeAppenderEvent(org.apache.log4j.Category, org.apache.log4j.Appender)
   *
   */
  public void removeAppenderEvent(final Category cat, final Appender appender) {
    // Empty method
  }

}
TOP

Related Classes of com.cisco.oss.foundation.logging.FoundationHierarchyEventListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.