001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 *
009 *   or (per the licensee's choosing)
010 *
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.pattern;
015
016import java.net.InetAddress;
017import java.net.UnknownHostException;
018import java.text.SimpleDateFormat;
019import java.util.Calendar;
020import java.util.Date;
021import java.util.Locale;
022
023import ch.qos.logback.classic.spi.ILoggingEvent;
024import ch.qos.logback.classic.util.LevelToSyslogSeverity;
025import ch.qos.logback.core.net.SyslogAppenderBase;
026
027public class SyslogStartConverter extends ClassicConverter {
028
029    long lastTimestamp = -1;
030    String timesmapStr = null;
031    SimpleDateFormat simpleMonthFormat;
032    SimpleDateFormat simpleTimeFormat;
033    private final Calendar calendar = Calendar.getInstance(Locale.US);
034
035    String localHostName;
036    int facility;
037
038    public void start() {
039        int errorCount = 0;
040
041        String facilityStr = getFirstOption();
042        if (facilityStr == null) {
043            addError("was expecting a facility string as an option");
044            return;
045        }
046
047        facility = SyslogAppenderBase.facilityStringToint(facilityStr);
048
049        localHostName = getLocalHostname();
050        try {
051            // hours should be in 0-23, see also http://jira.qos.ch/browse/LBCLASSIC-48
052            simpleMonthFormat = new SimpleDateFormat("MMM", Locale.US);
053            simpleTimeFormat = new SimpleDateFormat("HH:mm:ss", Locale.US);
054        } catch (IllegalArgumentException e) {
055            addError("Could not instantiate SimpleDateFormat", e);
056            errorCount++;
057        }
058
059        if (errorCount == 0) {
060            super.start();
061        }
062    }
063
064    public String convert(ILoggingEvent event) {
065        StringBuilder sb = new StringBuilder();
066
067        int pri = facility + LevelToSyslogSeverity.convert(event);
068
069        sb.append("<");
070        sb.append(pri);
071        sb.append(">");
072        sb.append(computeTimeStampString(event.getTimeStamp()));
073        sb.append(' ');
074        sb.append(localHostName);
075        sb.append(' ');
076
077        return sb.toString();
078    }
079
080    /**
081     * This method gets the network name of the machine we are running on. Returns
082     * "UNKNOWN_LOCALHOST" in the unlikely case where the host name cannot be found.
083     * 
084     * @return String the name of the local host
085     */
086    public String getLocalHostname() {
087        try {
088            InetAddress addr = InetAddress.getLocalHost();
089            return addr.getHostName();
090        } catch (UnknownHostException uhe) {
091            addError("Could not determine local host name", uhe);
092            return "UNKNOWN_LOCALHOST";
093        }
094    }
095
096    String computeTimeStampString(long now) {
097        synchronized (this) {
098            // Since the formatted output is only precise to the second, we can use the same
099            // cached string if the
100            // current
101            // second is the same (stripping off the milliseconds).
102            if ((now / 1000) != lastTimestamp) {
103                lastTimestamp = now / 1000;
104                Date nowDate = new Date(now);
105                calendar.setTime(nowDate);
106                timesmapStr = String.format("%s %2d %s", simpleMonthFormat.format(nowDate),
107                        calendar.get(Calendar.DAY_OF_MONTH), simpleTimeFormat.format(nowDate));
108            }
109            return timesmapStr;
110        }
111    }
112}