aboutsummaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/container/logging/LogFormatter.java
blob: 9970251d84b7e1c64075b9efc4a752677eab6a52 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.container.logging;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;


/**
 * Produces compact output format for prelude logs
 *
 * @author Bob Travis
 */
public class LogFormatter extends Formatter {

    /** date format objects */
    static SimpleDateFormat ddMMMyyyy;
    static DateFormat dfMMM;
    static SimpleDateFormat yyyyMMdd;

    static {
        ddMMMyyyy = new SimpleDateFormat("[dd/MMM/yyyy:HH:mm:ss Z]", Locale.US);
        ddMMMyyyy.setTimeZone(TimeZone.getTimeZone("UTC"));

        dfMMM = new SimpleDateFormat("MMM", Locale.US);
        dfMMM.setTimeZone(TimeZone.getTimeZone("UTC"));

        yyyyMMdd = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]", Locale.US);
        yyyyMMdd.setTimeZone(TimeZone.getTimeZone("UTC"));
    }

    /** Whether to strip down the message to only the message or not */
    private boolean messageOnly = false;

    /** Controls which of the available timestamp formats is used in all log records
     */
    private static final int timestampFormat = 2; // 0=millis, 1=mm/dd/yyyy, 2=yyyy-mm-dd

    /**
     * Standard constructor
     */

    public LogFormatter() {}

    /**
     * Make it possible to log stripped messages
     */
    public void messageOnly (boolean messageOnly) {
        this.messageOnly = messageOnly;
    }

    public String format(LogRecord record) {

        // if we don't want any other stuff we just return the message
        if (messageOnly) {
            return formatMessage(record);
        }

        String rawMsg = record.getMessage();
        boolean isLogMsg =
            rawMsg.charAt(0) == 'L'
            && rawMsg.charAt(1) == 'O'
            && rawMsg.charAt(2) == 'G'
            && rawMsg.charAt(3) == ':';
        String nameInsert =
            (!isLogMsg)
            ? record.getLevel().getName() + ": "
            : "";
        return (timeStamp(record)
                + nameInsert
                + formatMessage(record)
                + "\n"
                );
    }

    /**
     * Public support methods
     */

    /**
     * Static insertDate method will insert date fragments into a string
     * based on '%x' pattern elements.  Equivalents in SimpleDateFormatter patterns,
     * with examples:
     * <ul>
     * <li>%Y  YYYY  2003
     * <li>%m  MM  08
     * <li>%x  MMM  Aug
     * <li>%d  dd  25
     * <li>%H  HH  14
     * <li>%M  mm  30
     * <li>%S  ss  35
     * <li>%s  SSS  123
     * <li>%Z  Z -0400
     * </ul>
     *Others:
     * <ul>
     * <li>%T Long.toString(time)
     * <li>%%  %
     * </ul>
     */
    public static String insertDate(String pattern, long time) {
        DateFormat df = new SimpleDateFormat("yyyy.MM.dd:HH:mm:ss.SSS Z", Locale.US);
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date date = new Date(time);
        String datetime = df.format(date);
        StringBuilder result = new StringBuilder();
        int i=0;
        while (i < pattern.length()) {
            int j = pattern.indexOf('%',i);
            if (j == -1 || j >= pattern.length()-1) { // done
                result.append(pattern.substring(i)); // copy rest of pattern and quit
                break;
            }
            result.append(pattern.substring(i, j));
            switch (pattern.charAt(j+1)) {
            case 'Y':
                result.append(datetime.substring(0,4)); // year
                break;
            case 'm':
                result.append(datetime.substring(5,7)); // month
                break;
            case 'd':
                result.append(datetime.substring(8,10)); // day of month
                break;
            case 'H':
                result.append(datetime.substring(11,13)); // hour
                break;
            case 'M':
                result.append(datetime.substring(14,16)); // minute
                break;
            case 'S':
                result.append(datetime.substring(17,19)); // second
                break;
            case 's':
                result.append(datetime.substring(20,23)); // thousanths
                break;
            case 'Z':
                result.append(datetime.substring(24)); // time zone string
                break;
            case 'T':
                result.append(Long.toString(time)); //time in Millis
                break;
            case 'x':
                result.append(capitalize(dfMMM.format(date)));
                break;
            case '%':
                result.append("%%");
                break;
            default:
                result.append("%"); // copy pattern escape and move on
                j--;                // only want to bump by one position....
                break;
            }
            i = j+2;
        }

        return result.toString();
    }

    /**
     * Private methods: timeStamp(LogRecord)
     */
    private String timeStamp(LogRecord record) {
        Date date = new Date(record.getMillis());
        String stamp;
        switch (timestampFormat) {
        case 0:
            stamp = Long.toString(record.getMillis());
            break;
        case 1:
             stamp = ddMMMyyyy.format(date);
             break;
        case 2:
        default:
            stamp = yyyyMMdd.format(date);
            break;
        }
        return stamp;
    }

    /** Return the given string with the first letter in upper case */
    private static String capitalize(String string) {
        if (Character.isUpperCase(string.charAt(0))) return string;
        return Character.toUpperCase(string.charAt(0)) + string.substring(1);
    }

}