1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /* ident	"%Z%%M%	%I%	%E% SMI" */
27 
28 package com.sun.solaris.service.logging;
29 
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.text.*;
33 import java.util.*;
34 import java.util.logging.Formatter;
35 import java.util.logging.LogRecord;
36 import java.security.PrivilegedAction;
37 
38 import com.sun.solaris.service.exception.SuccinctStackTraceFormatter;
39 
40 /**
41  * Formats a LogRecord in a human-readable, <code>syslog</code>-like
42  * format, and is intended for use with non-syslog handlers, such as
43  * FileHandler.
44  *
45  * Multi-line messages are automatically indented by four spaces to make
46  * subsequent lines easier to differentiate from new records.
47  */
48 public class SysloglikeFormatter extends Formatter {
49 	/**
50 	 * The date set for each published Record.
51 	 */
52 	private Date date = new Date();
53 
54 	/**
55 	 * Format string for published dates.
56 	 */
57 	private final static String dateFormat =
58 	    "MMM d kk:mm:ss";
59 
60 	/**
61 	 * For published dates, the formatter.
62 	 */
63 	private DateFormat dateFormatter;
64 
65 	/**
66 	 * For published dates, the argument to date formatter.
67 	 */
68 	private Object args[] = { date };
69 
70 	/**
71 	 * Line separator string.
72 	 */
73 	private String lineSeparator = (String)java.security.AccessController
74 	    .doPrivileged(new PrivilegedAction() {
75 		public Object run() {
76 			return System.getProperty("line.separator");
77 		}
78 	});
79 
80 	/**
81 	 * Flag to set whether log records should indicate the name of
82 	 * the class generating the record, if possible.  (default
83 	 * false)
84 	 */
85 	private boolean useClassName = false;
86 
87 	/**
88 	 * Flag to set whether log records should indicate the record's
89 	 * logger, if useClassName isn't set and the class name was
90 	 * available.  (default false)
91 	 */
92 	private boolean useLoggerName = false;
93 
94 	/**
95 	 * Flag to set whether log records should indicate the last
96 	 * component of the record's logger name, if useLoggerName isn't
97 	 * set.  (default true)
98 	 */
99 	private boolean useShortLoggerName = true;
100 
101 	/**
102 	 * Flag to set whether log records should indicate the method
103 	 * used to invoke the logger, if available.  (default false)
104 	 */
105 	private boolean useMethodName = false;
106 
107 	/**
108 	 * Flag to set whether each record should be split into two
109 	 * lines such that the severity and message are on a line by
110 	 * themselves.  (default false)
111 	 */
112 	private boolean useTwoLineStyle = false;
113 
114 	/**
115 	 * Format the given LogRecord.
116 	 * @param record the log record to be formatted.
117 	 * @return a formatted log record.
118 	 */
format(LogRecord record)119 	public synchronized String format(LogRecord record)
120 	{
121 		StringBuffer sb = new StringBuffer();
122 
123 		date.setTime(record.getMillis());
124 		StringBuffer text = new StringBuffer();
125 		if (dateFormatter == null)
126 			dateFormatter = new SimpleDateFormat(dateFormat);
127 		sb.append(dateFormatter.format(date));
128 
129 		if (record.getSourceClassName() != null && useClassName) {
130 			sb.append(" ");
131 			sb.append(record.getSourceClassName());
132 		} else if (useLoggerName) {
133 			if (record.getLoggerName() != null) {
134 				sb.append(" ");
135 				sb.append(record.getLoggerName());
136 			}
137 		} else if (useShortLoggerName) {
138 			String loggerName = record.getLoggerName();
139 
140 			if (loggerName != null) {
141 				sb.append(" ");
142 				int lastDot = loggerName.lastIndexOf('.');
143 				if (lastDot >= 0)
144 					loggerName = loggerName.substring(
145 					    lastDot + 1);
146 				sb.append(loggerName);
147 			}
148 		}
149 
150 		if (record.getSourceMethodName() != null && useMethodName) {
151 			sb.append(" ");
152 			sb.append(record.getSourceMethodName());
153 		}
154 		if (useTwoLineStyle)
155 			sb.append(lineSeparator);
156 		else
157 			sb.append(" ");
158 
159 		String message = formatMessage(record);
160 		message = message.replaceAll("\n", lineSeparator + "    ");
161 
162 		sb.append(record.getLevel()).toString();
163 		sb.append(": ");
164 		sb.append(message);
165 		if (record.getThrown() != null) {
166 			sb.append(" ");
167 			sb.append(SuccinctStackTraceFormatter
168 			    .formatWithDescription(record.getThrown(),
169 			    "with tracing information: ").toString());
170 		}
171 		sb.append(lineSeparator);
172 
173 		return sb.toString();
174 	}
175 }
176