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

org.smallmind.scribe.pen.XMLFormatter Maven / Gradle / Ivy

There is a newer version: 6.3.0
Show newest version
/*
 * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 David Berkman
 * 
 * This file is part of the SmallMind Code Project.
 * 
 * The SmallMind Code Project is free software, you can redistribute
 * it and/or modify it under either, at your discretion...
 * 
 * 1) The terms of GNU Affero General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * 
 * ...or...
 * 
 * 2) The terms of the Apache License, Version 2.0.
 * 
 * The SmallMind Code Project is distributed in the hope that it will
 * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License or Apache License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * and the Apache License along with the SmallMind Code Project. If not, see
 *  or .
 * 
 * Additional permission under the GNU Affero GPL version 3 section 7
 * ------------------------------------------------------------------
 * If you modify this Program, or any covered work, by linking or
 * combining it with other code, such other code is not for that reason
 * alone subject to any of the requirements of the GNU Affero GPL
 * version 3.
 */
package org.smallmind.scribe.pen;

import java.util.Arrays;
import java.util.Date;
import org.smallmind.nutsnbolts.lang.UnknownSwitchCaseException;
import org.smallmind.scribe.pen.adapter.LoggingBlueprintsFactory;
import org.smallmind.scribe.pen.probe.CompleteOrAbortProbeEntry;
import org.smallmind.scribe.pen.probe.Correlator;
import org.smallmind.scribe.pen.probe.MetricMilieu;
import org.smallmind.scribe.pen.probe.ProbeEntry;
import org.smallmind.scribe.pen.probe.ProbeReport;
import org.smallmind.scribe.pen.probe.Statement;
import org.smallmind.scribe.pen.probe.UpdateProbeEntry;

public class XMLFormatter implements Formatter {

  private Timestamp timestamp = DateFormatTimestamp.getDefaultInstance();
  private XMLElement[] xmlElements = XMLElement.values();
  private String newLine = System.getProperty("line.separator");
  private boolean cdata = false;
  private int indent = 3;

  private static int findRepeatedStackElements (StackTraceElement singleElement, StackTraceElement[] prevStackTrace) {

    for (int count = 0; count < prevStackTrace.length; count++) {
      if (singleElement.equals(prevStackTrace[count])) {
        return prevStackTrace.length - count;
      }
    }

    return -1;
  }

  public XMLFormatter setXmlElements (XMLElement[] xmlElements) {

    this.xmlElements = xmlElements;

    return this;
  }

  public XMLFormatter setTimestamp (Timestamp timestamp) {

    this.timestamp = timestamp;

    return this;
  }

  public XMLFormatter setNewLine (String newLine) {

    this.newLine = newLine;

    return this;
  }

  public XMLFormatter setCdata (boolean cdata) {

    this.cdata = cdata;

    return this;
  }

  public XMLFormatter setIndent (int indent) {

    this.indent = indent;

    return this;
  }

  public String format (Record record, Filter[] filters) {

    StringBuilder formatBuilder = new StringBuilder();

    appendLine(formatBuilder, "", 0);

    for (XMLElement xmlElement : xmlElements) {
      switch (xmlElement) {
        case DATE:
          appendElement(formatBuilder, "date", timestamp.getTimestamp(new Date(record.getMillis())), false, 1);
          break;
        case MILLISECONDS:
          appendElement(formatBuilder, "milliseconds", String.valueOf(record.getMillis()), false, 1);
          break;
        case LOGGER_NAME:
          appendElement(formatBuilder, "logger", record.getLoggerName(), false, 1);
          break;
        case LEVEL:
          appendElement(formatBuilder, "level", record.getLevel().name(), false, 1);
          break;
        case MESSAGE:

          String message;

          if ((message = record.getMessage()) == null) {

            Throwable throwable;

            if ((throwable = record.getThrown()) != null) {
              message = throwable.getMessage();
            }
          }

          appendElement(formatBuilder, "message", message, cdata, 1);
          break;
        case THREAD:
          appendThreadInfo(formatBuilder, record.getThreadName(), record.getThreadID(), 1);
          break;
        case LOGICAL_CONTEXT:
          appendLogicalContext(formatBuilder, record.getLogicalContext(), 1);
          break;
        case PARAMETERS:
          appendParameters(formatBuilder, record.getParameters(), 1);
          break;
        case STACK_TRACE:
          appendStackTrace(formatBuilder, record.getThrown(), 1);
          break;
        case PROBE_REPORT:
          appendProbeReport(formatBuilder, record, record.getProbeReport(), filters, 1);
          break;
        default:
          throw new UnknownSwitchCaseException(xmlElement.name());
      }
    }

    appendFinalLine(formatBuilder, "", 0);

    return formatBuilder.toString();
  }

  private void appendThreadInfo (StringBuilder formatBuilder, String threadName, long threadId, int level) {

    if ((threadName != null) || (threadId > 0)) {
      appendLine(formatBuilder, "", level);
      appendElement(formatBuilder, "name", threadName, false, level + 1);
      appendElement(formatBuilder, "id", (threadId > 0) ? String.valueOf(threadId) : null, false, level + 1);
      appendLine(formatBuilder, "", level);
    }
  }

  private void appendLogicalContext (StringBuilder formatBuilder, LogicalContext logicalContext, int level) {

    if ((logicalContext != null) && (logicalContext.isFilled())) {
      appendLine(formatBuilder, "", level);
      appendElement(formatBuilder, "class", logicalContext.getClassName(), false, level + 1);
      appendElement(formatBuilder, "method", logicalContext.getMethodName(), false, level + 1);
      appendElement(formatBuilder, "native", String.valueOf(logicalContext.isNativeMethod()), false, level + 1);
      appendElement(formatBuilder, "line", ((!logicalContext.isNativeMethod()) && (logicalContext.getLineNumber() > 0)) ? String.valueOf(logicalContext.getLineNumber()) : null, false, level + 1);
      appendElement(formatBuilder, "file", logicalContext.getFileName(), false, level + 1);
      appendLine(formatBuilder, "", level);
    }
  }

  private void appendParameters (StringBuilder formatBuilder, Parameter[] parameters, int level) {

    if (parameters.length > 0) {
      appendLine(formatBuilder, "", level);
      for (Parameter parameter : parameters) {

        String key = parameter.getKey();
        Object value = parameter.getValue();

        appendElement(formatBuilder, (key == null) ? "null" : key, (value == null) ? "null" : value.toString(), cdata, level + 1);
      }
      appendLine(formatBuilder, "", level);
    }
  }

  private void appendStackTrace (StringBuilder formatBuilder, Throwable throwable, int level) {

    StackTraceElement[] prevStackTrace = null;
    int repeatedElements;

    if (throwable != null) {
      appendLine(formatBuilder, (cdata) ? "", level);

      do {
        appendIndent(formatBuilder, level + 1);

        if (prevStackTrace == null) {
          formatBuilder.append("Exception in thread ");
        } else {
          formatBuilder.append("Caused by: ");
        }

        formatBuilder.append(throwable.getClass().getCanonicalName());
        formatBuilder.append(": ");
        formatBuilder.append(throwable.getMessage());
        formatBuilder.append(newLine);

        for (StackTraceElement singleElement : throwable.getStackTrace()) {

          appendIndent(formatBuilder, level + 1);

          if (prevStackTrace != null) {
            if ((repeatedElements = findRepeatedStackElements(singleElement, prevStackTrace)) >= 0) {
              formatBuilder.append("   ... ");
              formatBuilder.append(repeatedElements);
              formatBuilder.append(" more");
              formatBuilder.append(newLine);
              break;
            }
          }

          formatBuilder.append("   at ");
          formatBuilder.append(singleElement.toString());
          formatBuilder.append(newLine);
        }

        prevStackTrace = throwable.getStackTrace();
      } while ((throwable = throwable.getCause()) != null);

      appendLine(formatBuilder, (cdata) ? "]]>" : "", level);
    }
  }

  private void appendProbeReport (StringBuilder formatBuilder, Record record, ProbeReport probeReport, Filter[] filters, int level) {

    if (probeReport != null) {
      appendLine(formatBuilder, "", level);
      appendElement(formatBuilder, "first", String.valueOf(probeReport.isFirst()), false, level + 1);
      appendCorrelator(formatBuilder, probeReport.getCorrelator(), level + 1);
      appendProbeEntry(formatBuilder, record, probeReport.getProbeEntry(), filters, level + 1);
      appendLine(formatBuilder, "", level);
    }
  }

  private void appendCorrelator (StringBuilder formatBuilder, Correlator correlator, int level) {

    appendLine(formatBuilder, "", level);
    appendElement(formatBuilder, "thread-identifier", Arrays.toString(correlator.getThreadIdentifier()), false, level + 1);
    appendElement(formatBuilder, "parent-identifier", Arrays.toString(correlator.getParentIdentifier()), false, level + 1);
    appendElement(formatBuilder, "identifier", Arrays.toString(correlator.getIdentifier()), false, level + 1);
    appendElement(formatBuilder, "frame", String.valueOf(correlator.getFrame()), false, level + 1);
    appendElement(formatBuilder, "instance", String.valueOf(correlator.getInstance()), false, level + 1);
    appendLine(formatBuilder, "", level);
  }

  private void appendProbeEntry (StringBuilder formatBuilder, Record record, ProbeEntry probeEntry, Filter[] filters, int level) {

    Record filterRecord;

    if (probeEntry != null) {
      appendLine(formatBuilder, "", level);
      appendElement(formatBuilder, "status", probeEntry.getProbeStatus().name(), false, level + 1);

      if (probeEntry instanceof UpdateProbeEntry) {
        appendElement(formatBuilder, "updated", String.valueOf(((UpdateProbeEntry)probeEntry).getUpdateTime()), false, level + 1);
        appendElement(formatBuilder, "count", String.valueOf(((UpdateProbeEntry)probeEntry).getUpdateCount()), false, level + 1);
      } else if (probeEntry instanceof CompleteOrAbortProbeEntry) {
        appendElement(formatBuilder, "started", String.valueOf(((CompleteOrAbortProbeEntry)probeEntry).getStartTime()), false, level + 1);
        appendElement(formatBuilder, "stopped", String.valueOf(((CompleteOrAbortProbeEntry)probeEntry).getStopTime()), false, level + 1);
        appendElement(formatBuilder, "elapsed", String.valueOf(((CompleteOrAbortProbeEntry)probeEntry).getStopTime() - ((CompleteOrAbortProbeEntry)probeEntry).getStartTime()), false, level + 1);
      } else {
        throw new IllegalArgumentException("Unknown instance type of ProbeEntry(" + probeEntry.getClass().getCanonicalName() + ")");
      }

      for (Statement statement : probeEntry.getStatements()) {
        if (!FilterUtility.willBeFiltered(record, statement.getDiscriminator(), statement.getLevel(), filters)) {
          appendElement(formatBuilder, "statement", statement.getMessage(), cdata, level + 1);
        }
      }

      for (MetricMilieu metricMilieu : probeEntry.getMetricMilieus()) {

        boolean skipMetric = false;

        if ((filters != null) && (filters.length > 0)) {
          filterRecord = LoggingBlueprintsFactory.getLoggingBlueprints().filterRecord(record, metricMilieu.getDiscriminator(), metricMilieu.getLevel());
          for (Filter filter : filters) {
            if (!filter.willLog(filterRecord)) {
              skipMetric = true;
              break;
            }
          }
        }

        if (!skipMetric) {
          appendLine(formatBuilder, "<" + metricMilieu.getMetric().getTitle() + ">", level + 1);
          for (String key : metricMilieu.getMetric().getKeys()) {
            appendElement(formatBuilder, key, metricMilieu.getMetric().getData(key).toString(), cdata, level + 2);
          }
          appendLine(formatBuilder, "", level + 1);
        }
      }

      appendLine(formatBuilder, "", level);
    }
  }

  private void appendElement (StringBuilder formatBuilder, String tagName, String value, boolean includeCDATA, int level) {

    if (value != null) {
      appendIndent(formatBuilder, level);
      formatBuilder.append("<");
      formatBuilder.append(tagName);
      formatBuilder.append(">");

      if (includeCDATA) {
        formatBuilder.append("");
      }

      formatBuilder.append("");
      formatBuilder.append(newLine);
    }
  }

  private void appendLine (StringBuilder formatBuilder, String content, int level) {

    appendIndent(formatBuilder, level);
    formatBuilder.append(content);
    formatBuilder.append(newLine);
  }

  private void appendFinalLine (StringBuilder formatBuilder, String content, int level) {

    appendIndent(formatBuilder, level);
    formatBuilder.append(content);
    formatBuilder.append(System.getProperty("line.separator"));
  }

  private void appendIndent (StringBuilder formatBuilder, int level) {

    for (int count = 0; count < (level * indent); count++) {
      formatBuilder.append(" ");
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy