All Downloads are FREE. Search and download functionalities are using the official Maven repository.

de.micromata.genome.logging.FallbackLogging Maven / Gradle / Ivy

The newest version!
//
// Copyright (C) 2010-2016 Micromata GmbH
//
// 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 de.micromata.genome.logging;

import java.lang.ref.SoftReference;
import java.util.Date;

import de.micromata.genome.logging.spi.log4j.Log4JLogging;
import de.micromata.genome.logging.spi.log4j.RoundList;
import de.micromata.genome.util.runtime.HostUtils;
import de.micromata.genome.util.types.Converter;
import de.micromata.genome.util.types.TimeInMillis;

/**
 * Implements Fallbacklogging.
 * 
 * This wrapps doLogImpl(), and if primary throws an exception, passed to secondary.
 * 
 * @author Roger Rene Kommer ([email protected])
 *
 */
public abstract class FallbackLogging extends BaseLogging implements LoggingWithFallback
{

  /**
   * When fast failure occours.
   */
  protected volatile Date lastLogFailure = null;

  /**
   * When last Log entry date in failure.
   */
  protected volatile Date lastLogFailed = null;

  /**
   * How many logs are written into fallback.
   */
  protected volatile long lastFailureCount = 0;

  /**
   * How long log in fallback in error case.
   */
  private long stayInFallbackSeconds = TimeInMillis.SECOND * 60;

  /**
   * Used to make fallback Logging.
   */
  private Logging secondary = new Log4JLogging(Log4JLogging.LOG4J_FALLBACK_PREFIX);

  /**
   * The max hard failed log queue.
   */
  private int maxHardFailedLogQueue = 2000;

  /**
   * The max soft failed log queue.
   */
  private int maxSoftFailedLogQueue = 20000;

  /**
   * The hard queue.
   */
  protected RoundList hardQueue = new RoundList<>(maxHardFailedLogQueue);

  /**
   * The soft queue.
   */
  protected SoftReference> softQueue = new SoftReference<>(
      new RoundList(maxSoftFailedLogQueue));

  /**
   * This implements persistence of Logging, which may fail.
   * 
   * @param lwe log entry to write
   */
  protected abstract void doLogImplWithFallback(LogWriteEntry lwe);

  /**
   * {@inheritDoc}
   *
   */

  @Override
  public void doLogImpl(LogWriteEntry lwe)
  {
    if (lastLogFailure != null) {
      synchronized (this) {
        ++lastFailureCount;
        Date cdate = new Date();
        if ((cdate.getTime() - lastLogFailure.getTime()) < stayInFallbackSeconds) {
          writeToSecondary(lwe);
          return;
        }
        lastLogFailure = null;
        drainFallbackLogs();
        /**
         * @logging
         * @reason Das Logging in die Datenbank ist zu dem angegebenen Zeitpunkt fehlgeschlagen
         * @action Dieser LogEintrag wird im Retry-Fall geschrieben. Sollte Datum des ersten fehlgeschlagenen
         *         DB-Logeintrags enthalten
         */
        fatal(GenomeLogCategory.Database, "Some DBLogging failed: "
            + Converter.dateToDebugString(lastLogFailed)
            + "; c: "
            + lastFailureCount
            + "; n: "
            + HostUtils.getThisHostName()
            + "; time: "
            + Converter.dateToDebugString(lastLogFailed));
      }
    }

    try {
      doLogImplWithFallback(lwe);
      lastLogFailed = null;
      lastFailureCount = 0;
    } catch (Throwable ex) { // NOSONAR "Illegal Catch" framework
      writeToSecondary(lwe);
      getSecondary().doLog(LogLevel.Fatal, GenomeLogCategory.Database, "Cannot write to Logging Table",
          new LogExceptionAttribute(ex));
      lastLogFailure = new Date();
      if (lastLogFailed == null) {
        lastLogFailed = lastLogFailure;
      }
    }
  }

  /**
   * Write to secondary.
   *
   * @param lwe the lwe
   */
  protected void writeToSecondary(LogWriteEntry lwe)
  {
    getSecondary().doLogImpl(lwe);
    putToFallbackQueue(lwe);
  }

  /**
   * Drain fallback logs.
   */
  protected void drainFallbackLogs()
  {
    RoundList sq = softQueue.get();
    if (sq != null) {
      writeFallbackQueue(sq);
    }
    writeFallbackQueue(hardQueue);
  }

  /**
   * Write fallback queue.
   *
   * @param sq the sq
   */
  protected void writeFallbackQueue(RoundList sq)
  {
    for (LogWriteEntry lwe : sq) {
      doLogImplWithFallback(lwe);
    }
    sq.clear();
  }

  /**
   * Put to fallback queue.
   *
   * @param lwe the lwe
   */
  protected void putToFallbackQueue(LogWriteEntry lwe)
  {
    synchronized (this) {
      if (hardQueue.size() == maxHardFailedLogQueue) {
        LogWriteEntry lastentry = hardQueue.get(hardQueue.size() - 1);
        RoundList sq = softQueue.get();
        if (sq == null) {
          softQueue = new SoftReference<>(new RoundList(maxSoftFailedLogQueue));
        }

        sq = softQueue.get();
        sq.add(lastentry);
      }
      hardQueue.add(lwe);
    }
  }

  /**
   * Gets the stay in fallback seconds.
   *
   * @return the stay in fallback seconds
   */
  public long getStayInFallbackSeconds()
  {
    return stayInFallbackSeconds;
  }

  /**
   * Sets the stay in fallback seconds.
   *
   * @param stayInFallbackSeconds the new stay in fallback seconds
   */
  public void setStayInFallbackSeconds(long stayInFallbackSeconds)
  {
    this.stayInFallbackSeconds = stayInFallbackSeconds;
  }

  /**
   * Gets the secondary.
   *
   * @return the secondary
   */
  @Override
  public Logging getSecondary()
  {
    return secondary;
  }

  /**
   * Sets the secondary.
   *
   * @param secondary the new secondary
   */
  @Override
  public void setSecondary(Logging secondary)
  {
    this.secondary = secondary;
  }

  /**
   * Gets the max hard failed log queue.
   *
   * @return the max hard failed log queue
   */
  public int getMaxHardFailedLogQueue()
  {
    return maxHardFailedLogQueue;
  }

  /**
   * Sets the max hard failed log queue.
   *
   * @param maxHardFailedLogQueue the new max hard failed log queue
   */
  public void setMaxHardFailedLogQueue(int maxHardFailedLogQueue)
  {
    this.maxHardFailedLogQueue = maxHardFailedLogQueue;
    hardQueue = new RoundList(maxHardFailedLogQueue); // NOSONAR reassign locked design
  }

  /**
   * Gets the max soft failed log queue.
   *
   * @return the max soft failed log queue
   */
  public int getMaxSoftFailedLogQueue()
  {
    return maxSoftFailedLogQueue;
  }

  /**
   * Sets the max soft failed log queue.
   *
   * @param maxSoftFailedLogQueue the new max soft failed log queue
   */
  public void setMaxSoftFailedLogQueue(int maxSoftFailedLogQueue)
  {
    this.maxSoftFailedLogQueue = maxSoftFailedLogQueue;
    softQueue = new SoftReference<>(new RoundList(maxSoftFailedLogQueue)); // NOSONAR reassign locked design
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy