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 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* ident "%Z%%M% %I% %E% SMI" */ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate package com.sun.solaris.service.logging; 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate import java.text.*; 327c478bd9Sstevel@tonic-gate import java.util.*; 337c478bd9Sstevel@tonic-gate import java.util.logging.Formatter; 347c478bd9Sstevel@tonic-gate import java.util.logging.Handler; 357c478bd9Sstevel@tonic-gate import java.util.logging.LogRecord; 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate import com.sun.solaris.service.exception.SuccinctStackTraceFormatter; 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /** 407c478bd9Sstevel@tonic-gate * This handler outputs LogRecords with <code>syslog(3C)</code> to the 417c478bd9Sstevel@tonic-gate * given facility with a severity translated by Level with a fixed 427c478bd9Sstevel@tonic-gate * table. Formatters are not used. 437c478bd9Sstevel@tonic-gate * 447c478bd9Sstevel@tonic-gate * Multiple SyslogHandlers may not be in concurrent use in one virtual 457c478bd9Sstevel@tonic-gate * machine. 467c478bd9Sstevel@tonic-gate */ 477c478bd9Sstevel@tonic-gate public final class SyslogHandler extends Handler { 487c478bd9Sstevel@tonic-gate /** 497c478bd9Sstevel@tonic-gate * <code>syslog(3C)</code> ident string, prepended to every 507c478bd9Sstevel@tonic-gate * message. 517c478bd9Sstevel@tonic-gate */ 527c478bd9Sstevel@tonic-gate private String ident; 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate /** 557c478bd9Sstevel@tonic-gate * <code>syslog</code> facility to be logged to. 567c478bd9Sstevel@tonic-gate */ 577c478bd9Sstevel@tonic-gate private Facility facility; 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /** 607c478bd9Sstevel@tonic-gate * Records the instance of this singleton. 617c478bd9Sstevel@tonic-gate */ 627c478bd9Sstevel@tonic-gate private static SyslogHandler instance = null; 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate /** 657c478bd9Sstevel@tonic-gate * Flag whether stack traces should be output when a record's 667c478bd9Sstevel@tonic-gate * <code>thrown</code> field is set. They will be formatted in 677c478bd9Sstevel@tonic-gate * a single line by <code>SuccinctStackTraceFormatter</code>, 687c478bd9Sstevel@tonic-gate * which does not include the Throwable's description, since 697c478bd9Sstevel@tonic-gate * it's presumably described by the log message). Default 707c478bd9Sstevel@tonic-gate * <code>true</code>. 717c478bd9Sstevel@tonic-gate */ 727c478bd9Sstevel@tonic-gate private static boolean useStackTraces = true; 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate /** 757c478bd9Sstevel@tonic-gate * Default logging option value. Sets no options. (Corresponds 767c478bd9Sstevel@tonic-gate * to the <code>logopt</code> argument to openlog(3c).) 777c478bd9Sstevel@tonic-gate */ 787c478bd9Sstevel@tonic-gate private static final int DEF_LOGOPT = 0; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /** 817c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the record's 827c478bd9Sstevel@tonic-gate * logger. (default false) 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate private boolean useLoggerName = false; 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /** 877c478bd9Sstevel@tonic-gate * Flag to set whether log records should indicate the last 887c478bd9Sstevel@tonic-gate * component of the record's logger name, if useLoggerName isn't 897c478bd9Sstevel@tonic-gate * set. (default true) 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate private boolean useShortLoggerName = true; 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate static { 947c478bd9Sstevel@tonic-gate System.loadLibrary("jsyslog"); 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate SyslogHandler(String ident, Facility facility)977c478bd9Sstevel@tonic-gate private SyslogHandler(String ident, Facility facility) 987c478bd9Sstevel@tonic-gate { 997c478bd9Sstevel@tonic-gate if (ident == null || facility == null) 1007c478bd9Sstevel@tonic-gate throw new IllegalArgumentException(); 101*55fea89dSDan Cross 1027c478bd9Sstevel@tonic-gate this.ident = ident; 1037c478bd9Sstevel@tonic-gate this.facility = facility; 1047c478bd9Sstevel@tonic-gate 1057c478bd9Sstevel@tonic-gate openlog(ident, DEF_LOGOPT, facility.getNative()); 1067c478bd9Sstevel@tonic-gate instance = this; 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /** 1107c478bd9Sstevel@tonic-gate * Return this virtual machine's instance of SyslogHandler, 1117c478bd9Sstevel@tonic-gate * creating one which logs with the given identity to the given 1127c478bd9Sstevel@tonic-gate * facility if necessary, unless an instance with a different 1137c478bd9Sstevel@tonic-gate * identity or facility is already open, in which case an 1147c478bd9Sstevel@tonic-gate * IllegalArgumentException is thrown. 1157c478bd9Sstevel@tonic-gate * 1167c478bd9Sstevel@tonic-gate * @throws IllegalArgumentException if the requested identity or 1177c478bd9Sstevel@tonic-gate * facility differs from a previously-created instance. 1187c478bd9Sstevel@tonic-gate */ getInstance(String ident, Facility facility)1197c478bd9Sstevel@tonic-gate public static SyslogHandler getInstance(String ident, 1207c478bd9Sstevel@tonic-gate Facility facility) 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate if (instance != null) { 1237c478bd9Sstevel@tonic-gate if (!instance.ident.equals(ident) || 1247c478bd9Sstevel@tonic-gate !instance.facility.equals(facility)) 1257c478bd9Sstevel@tonic-gate throw new IllegalArgumentException(); 1267c478bd9Sstevel@tonic-gate else 1277c478bd9Sstevel@tonic-gate return (instance); 1287c478bd9Sstevel@tonic-gate } else 1297c478bd9Sstevel@tonic-gate return (instance = new SyslogHandler(ident, facility)); 1307c478bd9Sstevel@tonic-gate } 1317c478bd9Sstevel@tonic-gate finalize()1327c478bd9Sstevel@tonic-gate public void finalize() 1337c478bd9Sstevel@tonic-gate { 1347c478bd9Sstevel@tonic-gate try { 1357c478bd9Sstevel@tonic-gate close(); 1367c478bd9Sstevel@tonic-gate } catch (Exception e) { 1377c478bd9Sstevel@tonic-gate // superclass-defined exceptions do not apply 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate toString()1417c478bd9Sstevel@tonic-gate public String toString() 1427c478bd9Sstevel@tonic-gate { 1437c478bd9Sstevel@tonic-gate return ("SyslogHandler(" + ident + ", " + facility.toString() + 1447c478bd9Sstevel@tonic-gate ")"); 1457c478bd9Sstevel@tonic-gate } 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /** 1487c478bd9Sstevel@tonic-gate * Calls <code>syslog(3C)</code>. 1497c478bd9Sstevel@tonic-gate */ syslog(int severity, String message)1507c478bd9Sstevel@tonic-gate private static native void syslog(int severity, String message); 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /** 1537c478bd9Sstevel@tonic-gate * Calls <code>openlog(3C)</code>. 1547c478bd9Sstevel@tonic-gate */ openlog(String ident, int logopt, int facility)1557c478bd9Sstevel@tonic-gate private static native void openlog(String ident, int logopt, 1567c478bd9Sstevel@tonic-gate int facility); 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /** 1597c478bd9Sstevel@tonic-gate * Calls <code>closelog(3C)</code>. 1607c478bd9Sstevel@tonic-gate */ closelog()1617c478bd9Sstevel@tonic-gate private static native void closelog(); 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate /** 1647c478bd9Sstevel@tonic-gate * Publishes the given record with its associated Severity (or 1657c478bd9Sstevel@tonic-gate * infers its severity with Severity.severityForLevel(), if 1667c478bd9Sstevel@tonic-gate * another type of Level is used), if the result is non-null. 1677c478bd9Sstevel@tonic-gate */ publish(LogRecord record)1687c478bd9Sstevel@tonic-gate public void publish(LogRecord record) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate Severity severity; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate if (record.getLevel() instanceof Severity) 1737c478bd9Sstevel@tonic-gate severity = (Severity)record.getLevel(); 1747c478bd9Sstevel@tonic-gate else 1757c478bd9Sstevel@tonic-gate severity = Severity.severityForLevel(record 1767c478bd9Sstevel@tonic-gate .getLevel()); 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (getLevel().intValue() > severity.intValue()) 1797c478bd9Sstevel@tonic-gate return; 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate /* 1827c478bd9Sstevel@tonic-gate * If the severity is null, the message isn't meant to 1837c478bd9Sstevel@tonic-gate * be sent to syslog. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate if (severity == null) 1867c478bd9Sstevel@tonic-gate return; 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate StringBuffer message = new StringBuffer(); 1897c478bd9Sstevel@tonic-gate String loggerName = record.getLoggerName(); 1907c478bd9Sstevel@tonic-gate if (useLoggerName) { 1917c478bd9Sstevel@tonic-gate if (loggerName != null) { 1927c478bd9Sstevel@tonic-gate message.append("("); 1937c478bd9Sstevel@tonic-gate message.append(record.getLoggerName()); 1947c478bd9Sstevel@tonic-gate message.append(") "); 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate } else if (useShortLoggerName) { 1977c478bd9Sstevel@tonic-gate if (loggerName != null) { 1987c478bd9Sstevel@tonic-gate message.append("("); 1997c478bd9Sstevel@tonic-gate int lastDot = loggerName.lastIndexOf('.'); 2007c478bd9Sstevel@tonic-gate if (lastDot >= 0) 2017c478bd9Sstevel@tonic-gate loggerName = loggerName.substring( 2027c478bd9Sstevel@tonic-gate lastDot + 1); 2037c478bd9Sstevel@tonic-gate message.append(loggerName); 2047c478bd9Sstevel@tonic-gate message.append(") "); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate message.append(record.getMessage()); 2097c478bd9Sstevel@tonic-gate 2107c478bd9Sstevel@tonic-gate /* 2117c478bd9Sstevel@tonic-gate * If the Severity is null, it's not meant to be logged 2127c478bd9Sstevel@tonic-gate * via syslog. 2137c478bd9Sstevel@tonic-gate */ 2147c478bd9Sstevel@tonic-gate if (record.getThrown() != null && useStackTraces == true) { 2157c478bd9Sstevel@tonic-gate /* 2167c478bd9Sstevel@tonic-gate * Format the stack trace as one line and tack 2177c478bd9Sstevel@tonic-gate * it onto the message. 2187c478bd9Sstevel@tonic-gate */ 2197c478bd9Sstevel@tonic-gate message.append(" "); 2207c478bd9Sstevel@tonic-gate message.append(SuccinctStackTraceFormatter 2217c478bd9Sstevel@tonic-gate .formatWithDescription(record.getThrown(), 2227c478bd9Sstevel@tonic-gate "with tracing information: ").toString()); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate syslog(severity.getNative(), message.toString()); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate flush()2277c478bd9Sstevel@tonic-gate public void flush() 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate } 2307c478bd9Sstevel@tonic-gate close()2317c478bd9Sstevel@tonic-gate public void close() throws SecurityException 2327c478bd9Sstevel@tonic-gate { 2337c478bd9Sstevel@tonic-gate if (instance != null) { 2347c478bd9Sstevel@tonic-gate closelog(); 2357c478bd9Sstevel@tonic-gate instance = null; 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate /** 2407c478bd9Sstevel@tonic-gate * Formatters may not be used with SyslogHandler. 2417c478bd9Sstevel@tonic-gate * 2427c478bd9Sstevel@tonic-gate * @throws IllegalArgumentException if the use of one is 2437c478bd9Sstevel@tonic-gate * attempted. 2447c478bd9Sstevel@tonic-gate */ setFormatter(Formatter formatter)2457c478bd9Sstevel@tonic-gate public void setFormatter(Formatter formatter) 2467c478bd9Sstevel@tonic-gate { 2477c478bd9Sstevel@tonic-gate throw new IllegalArgumentException(); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /** 2517c478bd9Sstevel@tonic-gate * Returns the <code>syslog(3C)</code> ident string, which is 2527c478bd9Sstevel@tonic-gate * prepended to every message. 2537c478bd9Sstevel@tonic-gate */ getIdent()2547c478bd9Sstevel@tonic-gate public String getIdent() 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate return (ident); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /** 2607c478bd9Sstevel@tonic-gate * Returns the <code>syslog</code> facility to be logged to. 2617c478bd9Sstevel@tonic-gate */ getFacility()2627c478bd9Sstevel@tonic-gate public Facility getFacility() 2637c478bd9Sstevel@tonic-gate { 2647c478bd9Sstevel@tonic-gate return (facility); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate } 268