Package reactor.logback

Source Code of reactor.logback.DurableLogUtility

/*
* Copyright (c) 2011-2014 Pivotal Software, 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 reactor.logback;

import ch.qos.logback.classic.BasicConfigurator;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.joran.JoranConfigurator;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.joran.spi.JoranException;
import ch.qos.logback.core.util.StatusPrinter;
import net.openhft.chronicle.Chronicle;
import net.openhft.chronicle.ChronicleConfig;
import net.openhft.chronicle.ExcerptTailer;
import net.openhft.chronicle.IndexedChronicle;
import net.openhft.chronicle.tools.ChronicleTools;
import org.apache.commons.cli.*;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.regex.Pattern;

/**
* @author Jon Brisbin
*/
public class DurableLogUtility {

  private static Options OPTS = new Options();

  static {
    Option path = new Option("p", "path", true, "Base path to a durable log file to interpret");
    path.setRequired(true);

    Option config = new Option("c", "config", true, "Logback configuration XML file to parse");
    Option output = new Option("o", "output", true, "Appender to use to output results");

    Option regex = new Option("search", true, "Search for the given regex and print to standard out");
    Option level = new Option("level", true, "Log level to filter");
    Option head = new Option("head", true, "Number of lines to display from the head of the file");
    Option tail = new Option("tail", true, "Number of lines to display from the tail of the file");
    OptionGroup findOpts = new OptionGroup()
        .addOption(regex)
        .addOption(head)
        .addOption(tail);

    OPTS.addOption(path)
        .addOption(config)
        .addOption(output)
        .addOption(level)
        .addOptionGroup(findOpts);
  }

  @SuppressWarnings("unchecked")
  public static void main(String... args) throws ParseException,
                                                 JoranException,
                                                 IOException {
    Parser parser = new BasicParser();
    CommandLine cl = null;
    try {
      cl = parser.parse(OPTS, args);
    } catch (ParseException e) {
      HelpFormatter help = new HelpFormatter();
      help.printHelp("dlog", OPTS, true);
      System.exit(-1);
    }

    LoggerContext loggerContext = (LoggerContext) LoggerFactory.getILoggerFactory();
    loggerContext.reset();

    if (cl.hasOption("config")) {
      // Read Logback configuration
      JoranConfigurator configurator = new JoranConfigurator();
      configurator.setContext(loggerContext);

      configurator.doConfigure(cl.getOptionValue("file", "logback.xml"));

      StatusPrinter.printInCaseOfErrorsOrWarnings(loggerContext);
    } else {
      BasicConfigurator.configure(loggerContext);
    }

    Appender appender = null;
    if (cl.hasOption("output")) {
      String outputAppender = cl.getOptionValue("output", "console");
      appender = loggerContext.getLogger(Logger.ROOT_LOGGER_NAME).getAppender(outputAppender);
    }

    ChronicleTools.warmup();
    Chronicle chronicle = new IndexedChronicle(cl.getOptionValue("path"), ChronicleConfig.DEFAULT);
    ExcerptTailer ex = chronicle.createTailer();

    Level level = Level.valueOf(cl.getOptionValue("level", "TRACE"));

    if (cl.hasOption("head")) {
      int lines = Integer.parseInt(cl.getOptionValue("head", "10"));
      for (int i = 0; i < lines; i++) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (evt.getLevel().isGreaterOrEqual(level)) {
          writeEvent(evt, appender);
        }
      }
    } else if (cl.hasOption("tail")) {
      int lines = Integer.parseInt(cl.getOptionValue("tail", "10"));
      Queue<LoggingEvent> tail = new LinkedBlockingQueue<LoggingEvent>(lines);
      while (ex.nextIndex()) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (!tail.offer(evt)) {
          tail.poll();
          tail.add(evt);
        }
      }
      LoggingEvent evt;
      while (null != (evt = tail.poll())) {
        if (evt.getLevel().isGreaterOrEqual(level)) {
          writeEvent(evt, appender);
        }
      }
    } else if (cl.hasOption("search")) {
      String regex = cl.getOptionValue("search");
      Pattern regexPatt = Pattern.compile(regex);
      while (ex.nextIndex()) {
        LoggingEvent evt = readLoggingEvent(ex, loggerContext);
        if (null != evt && evt.getLevel().isGreaterOrEqual(level)) {
          if (regexPatt.matcher(evt.getFormattedMessage()).matches()) {
            writeEvent(evt, appender);
          }
        }
      }
    }

    loggerContext.stop();
    chronicle.close();
  }

  @SuppressWarnings("unchecked")
  private static void writeEvent(LoggingEvent evt, Appender appender) {
    if (null == evt) {
      return;
    }
    if (null != appender) {
      appender.doAppend(evt);
    } else {
      System.out.println(evt.getFormattedMessage());
    }
  }

  @SuppressWarnings("unchecked")
  private static LoggingEvent readLoggingEvent(ExcerptTailer ex,
                                               LoggerContext ctx) {
    LoggingEventRecord rec = LoggingEventRecord.read(ex);

    Logger logger = ctx.getLogger(rec.getLoggerName());
    LoggingEvent evt = new LoggingEvent(
        logger.getClass().getName(),
        logger,
        Level.toLevel(rec.getLevel()),
        rec.getMessage(),
        rec.getCause(),
        rec.getArgs()
    );
    evt.setTimeStamp(rec.getTimestamp());
    evt.setThreadName(rec.getThreadName());
    evt.setMDCPropertyMap(rec.getMdcProps());
    if (null != rec.getCause()) {
      evt.setThrowableProxy(new ThrowableProxy(rec.getCause()));
    }
    evt.setCallerData(rec.getCallerData());

    return evt;
  }

}
TOP

Related Classes of reactor.logback.DurableLogUtility

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.