package jp.ehobby.util.syslog; import java.io.IOException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Calendar; import jp.ehobby.info.SystemInfo; import jp.ehobby.io.SyslogWriter; /** * Syslog を扱う. * * @author kei-n */ public class Syslog { /** Syslog Server のポート. */ public static final int SERVER_PORT = SyslogWriter.SYSLOG_SERVER_PORT; /** ローカルアドレス. */ private static final String LOCALHOST = "localhost"; //$NON-NLS-1$ /** TIMESTAMPのフォーマット. */ private static final String TIMESTAMP_FORMAT = "%s %2d %02d:%02d:%02d "; //$NON-NLS-1$ /** HOST名部分の最大サイズ. */ private static final int MAX_HOSTNAME_SIZE = 255; /** TAG部分の最大サイズ. */ private static final int MAX_TAG_SIZE = 32; /** 月の文字列表現. */ private static final String[] MONTH_STRING = { "Jan", "Feb", "Mar", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ "Apr", "May", "Jun", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ "Jul", "Aug", "Sep", //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ "Oct", "Nov", "Dec" //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ }; /** syslog に書き出す Writer. */ private final SyslogWriter writer; /** * ローカルの syslog に出力する syslog を構築します. * * @throws SocketException ソケットエラー * @throws UnknownHostException 不明なホストエラー */ public Syslog() throws SocketException, UnknownHostException { this(LOCALHOST); } /** * 指定されたホストの syslog に出力する syslog を構築します. * * @param host ホストまたはアドレス * @throws UnknownHostException 不明なホスト名 * @throws SocketException ソケットエラー */ public Syslog(final String host) throws SocketException, UnknownHostException { this(host, SERVER_PORT); } /** * 指定されたホストの syslog に出力する syslog を構築します. * * @param host ホストまたはアドレス * @param port ポート番号 * @throws UnknownHostException 不明なホスト名 * @throws SocketException ソケットエラー */ public Syslog(final String host, final int port) throws SocketException, UnknownHostException { this.writer = new SyslogWriter(host, port); } /** * ログ分類 user-level message の syslog を出力します. * * @param severity 重要度 * @param tag タグ(最大30文字、": "が自動で付与される) * @param comment コメント * @throws IOException ログ書き込み失敗 */ public void logger( final SyslogSeverity severity, final String tag, final String comment ) throws IOException { logger(SyslogFacility.USER_LEVEL, severity, null, tag, comment); } /** * syslog を出力します. * * @param facility ログの分類 * @param severity 重要度 * @param host ホスト名 * @param tag タグ(最大30文字、": "が自動で付与される) * @param comment コメント * @throws IOException ログ書き込み失敗 */ public void logger( final SyslogFacility facility, final SyslogSeverity severity, final String host, final String tag, final String comment) throws IOException { StringBuffer sb = new StringBuffer(); sb.append(createPriority(facility, severity)); sb.append(createTimestamp()); sb.append(createHostName(host)); sb.append(createTag(tag)); sb.append(comment); this.writer.write(sb.toString()); } /** * Syslog用のソケットをcloseします. * @throws IOException close失敗 */ public void close() throws IOException { this.writer.close(); } //////////////////////////////////////////////////////////////////////////// // // private static // /** * PRI部分を生成します. * * @param facility ログの分類 * @param severity 重要度 * @return PRI部分 */ private static String createPriority(final SyslogFacility facility, final SyslogSeverity severity) { int pri = facility.getPriorityValue() + severity.getValue(); StringBuffer sb = new StringBuffer(); sb.append('<'); sb.append(pri); sb.append('>'); return sb.toString(); } /** * TIMESTAMP部分を生成します. * * @return TIMESTAMP部分 */ private static String createTimestamp() { Calendar cal = Calendar.getInstance(); int month = cal.get(Calendar.MONTH); int day = cal.get(Calendar.DAY_OF_MONTH); int hour = cal.get(Calendar.HOUR_OF_DAY); int minute = cal.get(Calendar.MINUTE); int second = cal.get(Calendar.SECOND); // MMM dd HH:MM:SS String timestampStr = String.format(TIMESTAMP_FORMAT, MONTH_STRING[month], Integer.valueOf(day), Integer.valueOf(hour), Integer.valueOf(minute), Integer.valueOf(second)); return timestampStr; } /** * ホスト名部分を生成します. * ホストが指定されている場合、指定された host を返します. * * @param host ホスト名 * @return ホスト名部分の文字列 */ private static String createHostName(final String host) { StringBuffer sb = new StringBuffer(); if (host == null) { sb.append(SystemInfo.getLocalHostName()); } else if (host.length() > MAX_HOSTNAME_SIZE) { sb.append(host.substring(0, MAX_HOSTNAME_SIZE)); } else { sb.append(host); } sb.append(' '); return sb.toString(); } /** * TAB部分を生成します. * 指定されたタグ tag に、"[PID]: " が付与されます. * 指定されたタグ tag が長い場合、"[PID]" を付与せず、tag が切り詰められます. * * @param tag TAG文字 * @return PIDを含んだTAG */ private static String createTag(final String tag) { if (tag == null) { return ""; } //$NON-NLS-1$ String pid = getPidString(); int tagSize = tag.getBytes().length; int pidSize = pid.getBytes().length; int totalSize = tagSize + pidSize + 2; // +2 は、": "分 StringBuffer sb = new StringBuffer(); if (totalSize < MAX_TAG_SIZE) { sb.append(tag); sb.append(pid); } else { // 指定されたTAG文字部分を切り詰める(PIDは付与しない) sb.append(tag.substring(0, MAX_TAG_SIZE)); } sb.append(": "); //$NON-NLS-1$ return sb.toString(); } /** * PIDの文字列表現を返します. * PIDが取得できない場合、空文字を返します. * * @return PIDの文字列表現 */ private static String getPidString() { StringBuffer sb = new StringBuffer(); int pid = SystemInfo.getPid(); if (pid >= 0) { sb.append('['); sb.append(pid); sb.append(']'); } return sb.toString(); } }