aboutsummaryrefslogtreecommitdiffstats
path: root/vespalog/src/main/java/com/yahoo/log/VespaFormat.java
blob: 646459161f5a8a99c69125d15343c10ce90ce9cc (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
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.log;

import com.yahoo.log.impl.LogUtils;
import java.time.Instant;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Vespa log formatting utility methods.
 * Contains some code based on LogUtils.java in Cloudname https://github.com/Cloudname/cloudname
 * written by Bjørn Borud, licensed under the Apache 2.0 license.
 *
 * @author arnej27959
 * @author bjorncs
 *
 * Should only be used internally in the log library
 */
class VespaFormat {

    private static final Pattern special   = Pattern.compile("[\r\\\n\\\t\\\\]+");
    private static final Pattern newLine   = Pattern.compile("\n");
    private static final Pattern carriage  = Pattern.compile("\r");
    private static final Pattern tab       = Pattern.compile("\t");
    private static final Pattern backSlash = Pattern.compile("\\\\");

    private static final String hostname;
    private static final String processID;

    static {
        hostname = LogUtils.getHostName();
        processID = LogUtils.getPID();
    }

    /**
     * This static method is used to detect if a message needs
     * to be escaped, and if so, performs the escaping.  Since the
     * common case is most likely that escaping is <em>not</em>
     * needed, the code is optimized for this case.  The forbidden
     * characters are:
     *
     * <UL>
     *  <LI> newline
     *  <LI> tab
     *  <LI> backslash
     * </UL>
     *
     * <P>
     * Also handles the case where the message is <code>null</code>
     * and replaces the null message with a tag saying that the
     * value was "(empty)".
     *
     * @param s String that might need escaping
     * @return returns the escaped string
     */
    public static String escape (String s) {
        if (s == null) {
            return "(empty)";
        }

        Matcher m = special.matcher(s);
        if (! m.find()) {
            return s;
        }

        // invariant: we had special characters

        m = backSlash.matcher(s);
        if (m.find()) {
            s = m.replaceAll("\\\\\\\\");
        }

        m = newLine.matcher(s);
        if (m.find()) {
            s = m.replaceAll("\\\\n");
        }

        m = carriage.matcher(s);
        if (m.find()) {
            s = m.replaceAll("\\\\r");
        }

        m = tab.matcher(s);
        if (m.find()) {
            s = m.replaceAll("\\\\t");
        }

        return s;
    }


    public static String formatTime(Instant instant) {
        return String.format("%d.%06d", instant.getEpochSecond(), instant.getNano() / 1000);
    }

    static String formatThreadProcess(long processId, long threadId) {
        if (threadId == 0) {
            return Long.toString(processId);
        }
        return processId + "/" + threadId;
    }

}