17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7f184c34Ssl108498 * Common Development and Distribution License (the "License"). 6*7f184c34Ssl108498 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*7f184c34Ssl108498 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* ident "%Z%%M% %I% %E% SMI" */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate package com.sun.solaris.service.logging; 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate import java.io.PrintWriter; 317c478bd9Sstevel@tonic-gate import java.io.StringWriter; 327c478bd9Sstevel@tonic-gate import java.text.*; 337c478bd9Sstevel@tonic-gate import java.util.*; 347c478bd9Sstevel@tonic-gate import java.util.logging.Formatter; 357c478bd9Sstevel@tonic-gate import java.util.logging.LogRecord; 36*7f184c34Ssl108498 import java.security.PrivilegedAction; 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate import com.sun.solaris.service.exception.SuccinctStackTraceFormatter; 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate /** 417c478bd9Sstevel@tonic-gate * Formats a LogRecord in a human-readable, <code>syslog</code>-like 427c478bd9Sstevel@tonic-gate * format, and is intended for use with non-syslog handlers, such as 437c478bd9Sstevel@tonic-gate * FileHandler. 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * Multi-line messages are automatically indented by four spaces to make 467c478bd9Sstevel@tonic-gate * subsequent lines easier to differentiate from new records. 477c478bd9Sstevel@tonic-gate */ 487c478bd9Sstevel@tonic-gate public class SysloglikeFormatter extends Formatter { 497c478bd9Sstevel@tonic-gate /** 507c478bd9Sstevel@tonic-gate * The date set for each published Record. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate private Date date = new Date(); 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /** 557c478bd9Sstevel@tonic-gate * Format string for published dates. 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate private final static String dateFormat = 587c478bd9Sstevel@tonic-gate "MMM d kk:mm:ss"; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /** 617c478bd9Sstevel@tonic-gate * For published dates, the formatter. 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate private DateFormat dateFormatter; 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /** 667c478bd9Sstevel@tonic-gate * For published dates, the argument to date formatter. 677c478bd9Sstevel@tonic-gate */ 687c478bd9Sstevel@tonic-gate private Object args[] = { date }; 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /** 717c478bd9Sstevel@tonic-gate * Line separator string. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate private String lineSeparator = (String)java.security.AccessController 74*7f184c34Ssl108498 .doPrivileged(new PrivilegedAction() { 75*7f184c34Ssl108498 public Object run() { 76*7f184c34Ssl108498 return System.getProperty("line.separator"); 77*7f184c34Ssl108498 } 78*7f184c34Ssl108498 }); 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /** 817c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the name of 827c478bd9Sstevel@tonic-gate * the class generating the record, if possible. (default 837c478bd9Sstevel@tonic-gate * false) 847c478bd9Sstevel@tonic-gate */ 857c478bd9Sstevel@tonic-gate private boolean useClassName = false; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate /** 887c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the record's 897c478bd9Sstevel@tonic-gate * logger, if useClassName isn't set and the class name was 907c478bd9Sstevel@tonic-gate * available. (default false) 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate private boolean useLoggerName = false; 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /** 957c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the last 967c478bd9Sstevel@tonic-gate * component of the record's logger name, if useLoggerName isn't 977c478bd9Sstevel@tonic-gate * set. (default true) 987c478bd9Sstevel@tonic-gate */ 997c478bd9Sstevel@tonic-gate private boolean useShortLoggerName = true; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /** 1027c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the method 1037c478bd9Sstevel@tonic-gate * used to invoke the logger, if available. (default false) 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate private boolean useMethodName = false; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /** 1087c478bd9Sstevel@tonic-gate * Flag to set whether each record should be split into two 1097c478bd9Sstevel@tonic-gate * lines such that the severity and message are on a line by 1107c478bd9Sstevel@tonic-gate * themselves. (default false) 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate private boolean useTwoLineStyle = false; 1137c478bd9Sstevel@tonic-gate 1147c478bd9Sstevel@tonic-gate /** 1157c478bd9Sstevel@tonic-gate * Format the given LogRecord. 1167c478bd9Sstevel@tonic-gate * @param record the log record to be formatted. 1177c478bd9Sstevel@tonic-gate * @return a formatted log record. 1187c478bd9Sstevel@tonic-gate */ format(LogRecord record)1197c478bd9Sstevel@tonic-gate public synchronized String format(LogRecord record) 1207c478bd9Sstevel@tonic-gate { 1217c478bd9Sstevel@tonic-gate StringBuffer sb = new StringBuffer(); 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate date.setTime(record.getMillis()); 1247c478bd9Sstevel@tonic-gate StringBuffer text = new StringBuffer(); 1257c478bd9Sstevel@tonic-gate if (dateFormatter == null) 1267c478bd9Sstevel@tonic-gate dateFormatter = new SimpleDateFormat(dateFormat); 1277c478bd9Sstevel@tonic-gate sb.append(dateFormatter.format(date)); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate if (record.getSourceClassName() != null && useClassName) { 1307c478bd9Sstevel@tonic-gate sb.append(" "); 1317c478bd9Sstevel@tonic-gate sb.append(record.getSourceClassName()); 1327c478bd9Sstevel@tonic-gate } else if (useLoggerName) { 1337c478bd9Sstevel@tonic-gate if (record.getLoggerName() != null) { 1347c478bd9Sstevel@tonic-gate sb.append(" "); 1357c478bd9Sstevel@tonic-gate sb.append(record.getLoggerName()); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate } else if (useShortLoggerName) { 1387c478bd9Sstevel@tonic-gate String loggerName = record.getLoggerName(); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate if (loggerName != null) { 1417c478bd9Sstevel@tonic-gate sb.append(" "); 1427c478bd9Sstevel@tonic-gate int lastDot = loggerName.lastIndexOf('.'); 1437c478bd9Sstevel@tonic-gate if (lastDot >= 0) 1447c478bd9Sstevel@tonic-gate loggerName = loggerName.substring( 1457c478bd9Sstevel@tonic-gate lastDot + 1); 1467c478bd9Sstevel@tonic-gate sb.append(loggerName); 1477c478bd9Sstevel@tonic-gate } 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate if (record.getSourceMethodName() != null && useMethodName) { 1517c478bd9Sstevel@tonic-gate sb.append(" "); 1527c478bd9Sstevel@tonic-gate sb.append(record.getSourceMethodName()); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate if (useTwoLineStyle) 1557c478bd9Sstevel@tonic-gate sb.append(lineSeparator); 1567c478bd9Sstevel@tonic-gate else 1577c478bd9Sstevel@tonic-gate sb.append(" "); 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate String message = formatMessage(record); 1607c478bd9Sstevel@tonic-gate message = message.replaceAll("\n", lineSeparator + " "); 1617c478bd9Sstevel@tonic-gate 1627c478bd9Sstevel@tonic-gate sb.append(record.getLevel()).toString(); 1637c478bd9Sstevel@tonic-gate sb.append(": "); 1647c478bd9Sstevel@tonic-gate sb.append(message); 1657c478bd9Sstevel@tonic-gate if (record.getThrown() != null) { 1667c478bd9Sstevel@tonic-gate sb.append(" "); 1677c478bd9Sstevel@tonic-gate sb.append(SuccinctStackTraceFormatter 1687c478bd9Sstevel@tonic-gate .formatWithDescription(record.getThrown(), 1697c478bd9Sstevel@tonic-gate "with tracing information: ").toString()); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate sb.append(lineSeparator); 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate return sb.toString(); 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate } 176