001/*
002 * JPPF.
003 * Copyright (C) 2005-2018 JPPF Team.
004 * http://www.jppf.org
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019package org.jppf.logging.jdk;
020
021import java.text.SimpleDateFormat;
022import java.util.Date;
023import java.util.logging.*;
024
025import org.jppf.utils.*;
026
027/**
028 * Formats log records in format yyyy-MM-dd hh:mm:ss.SSS [LEVEL][thread name][package.ClassName.method()]: message.
029 * @author Laurent Cohen
030 */
031public class JPPFLogFormatter extends Formatter {
032  /**
033   * Date format used in log entries.
034   */
035  private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS ");
036
037  /**
038   * Format a log record.
039   * @param record the record to format.
040   * @return a string representation of the record according to this formatter.
041   * @see java.util.logging.Formatter#format(java.util.logging.LogRecord)
042   */
043  @Override
044  public String format(final LogRecord record) {
045    final StringBuilder sb = new StringBuilder();
046    sb.append(sdf.format(new Date(record.getMillis())));
047    sb.append('[');
048    final String name = record.getLevel().getName();
049    sb.append(name);
050    // pad to 7 chars
051    for (int i = 0; i < 7 - name.length(); i++) sb.append(' ');
052    sb.append(']');
053
054    sb.append('[');
055    String s = "" + Thread.currentThread().getName();
056    sb.append(StringUtils.padRight(s, ' ', 20, true));
057    sb.append(']');
058
059    sb.append('[');
060    /* String s = record.getSourceClassName();
061     * if (s != null) sb.append(s); */
062    s = record.getSourceClassName();
063    final String shortName = getShortName(s);
064    final StackTraceElement[] elts = new Throwable().getStackTrace();
065    StackTraceElement elt = null;
066    for (final StackTraceElement elt1 : elts) {
067      if (getShortName(elt1.getClassName()).equals(shortName)) {
068        elt = elt1;
069        break;
070      }
071    }
072    if (elt != null) {
073      sb.append(elt.getClassName());
074      if (elt.getMethodName() != null) sb.append('.').append(elt.getMethodName());
075      sb.append('(');
076      if (elt.getLineNumber() >= 0) sb.append(elt.getLineNumber());
077      sb.append(')');
078    } else {
079      if (s != null) sb.append(s);
080      s = record.getSourceMethodName();
081      if (s != null) sb.append('.').append(s).append("()");
082    }
083    sb.append(']');
084    sb.append(": ");
085    s = record.getMessage();
086    if (s != null) sb.append(s);
087    final Object[] params = record.getParameters();
088    if (params != null) for (Object o : params)
089      sb.append('|').append(o);
090    sb.append('\n');
091    if (record.getThrown() != null) sb.append(ExceptionUtils.getStackTrace(record.getThrown())).append("\n");
092    return sb.toString();
093  }
094
095  /**
096   * Get the short name of a class, without the package name.
097   * @param fqn - the fully qualified name of the class.
098   * @return a string representing the short name of a class.
099   */
100  private static String getShortName(final String fqn) {
101    if (fqn == null) return "";
102    final int idx = fqn.lastIndexOf('.');
103    return idx >= 0 ? fqn.substring(idx + 1) : fqn;
104  }
105}