/**
   * Create an {@link IStatus} from the given event
   *
   * @param event the logging event
   * @param multi if a {@link CustomMultiStatus} shall be created
   * @param hasParent if the status has a parent
   * @return the {@link IStatus} or <code>null</code>
   */
  private IStatus createStatus(LoggingEvent event, boolean multi, boolean hasParent) {
    // pluginId
    String pluginId = ALoggerUtil.getBundleName(event.getMarker());
    if (pluginId == null) {
      // default to logger name
      String name = event.getLoggerName();
      if (name != null) {
        pluginId = "[" + name + "]";
      }

      if (pluginId == null) {
        pluginId = "#unknown";
      }
    }

    // throwable
    Throwable throwable;
    if (event.getThrowableProxy() != null && event.getThrowableProxy() instanceof ThrowableProxy) {
      throwable = ((ThrowableProxy) event.getThrowableProxy()).getThrowable();
    } else {
      throwable = null;
    }

    String message = event.getFormattedMessage();
    if (hasParent) {
      // include time in message
      // (as it gets lost in MultiStatus)
      Date date = new Date(event.getTimeStamp());
      message = "[" + TIME_FORMAT.format(date) + "] " + message;
    }

    // create status object
    IStatus status;
    if (multi) {
      status = new CustomMultiStatus(pluginId, IStatus.OK, message, throwable);
    } else {
      // severity
      Level level = event.getLevel();

      if (!level.isGreaterOrEqual(Level.INFO)) {
        return null;
      }

      int severity;
      if (level == Level.INFO) {
        severity = IStatus.INFO;
      } else if (level == Level.WARN) {
        severity = IStatus.WARNING;
      } else {
        // default to error
        severity = IStatus.ERROR;
      }

      status = new Status(severity, pluginId, message, throwable);
    }

    return status;
  }
 @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")
  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();
  }