Logger.java

1
package com.renomad.minum.logging;
2
3
import com.renomad.minum.state.Constants;
4
import com.renomad.minum.queue.AbstractActionQueue;
5
6
import java.util.EnumMap;
7
import java.util.List;
8
import java.util.Map;
9
import java.util.concurrent.ExecutorService;
10
11
import static com.renomad.minum.utils.TimeUtils.getTimestampIsoInstant;
12
13
/**
14
 * Implementation of {@link ILogger}
15
 */
16
public class Logger implements ILogger {
17
    /**
18
     * The {@link LoggingActionQueue} that handles all
19
     * our messages thread-safely by taking
20
     * them off the top of a queue.
21
     */
22
    protected final AbstractActionQueue loggingActionQueue;
23
    private final Constants constants;
24
    private final ExecutorService executorService;
25
    private final String name;
26
    private final Map<LoggingLevel, Boolean> activeLogLevels;
27
28
    /**
29
     * Constructor
30
     * @param constants used for determining enabled log levels
31
     * @param executorService provides thread handling for the logs, used to
32
     *                        build a {@link LoggingActionQueue}
33
     * @param name sets a name on the {@link LoggingActionQueue} to aid debugging, to
34
     *             help distinguish queues.
35
     */
36
    public Logger(Constants constants, ExecutorService executorService, String name) {
37
        this(constants, executorService, name, null);
38
    }
39
40
    private Logger(Constants constants, ExecutorService executorService, String name, AbstractActionQueue loggingActionQueue) {
41
        this.constants = constants;
42
        this.executorService = executorService;
43
        this.name = name;
44
        // this tricky code exists so that a user has the option to create a class extended
45
        // from this one, and can construct it with the logger instance, making it possible
46
        // to inject the running action queue.  This enables us to continue using the same
47
        // action queue amongst descendant classes.
48 1 1. <init> : negated conditional → KILLED
        if (loggingActionQueue == null) {
49
            this.loggingActionQueue = new LoggingActionQueue("loggerPrinter" + name, executorService, constants).initialize();
50
        } else {
51
            this.loggingActionQueue = loggingActionQueue;
52
        }
53
        activeLogLevels = convertToMap(constants.logLevels);
54
    }
55
56
    /**
57
     * A constructor meant for use by descendant classes
58
     * @param logger an existing instance of a running logger, needed in order to have the
59
     *               descendant logger using the same {@link AbstractActionQueue}, which is
60
     *               necessary so logs don't interleave with each other.
61
     */
62
    public Logger(Logger logger) {
63
        this(logger.constants, logger.executorService, logger.name, logger.loggingActionQueue);
64
    }
65
66
    /**
67
     * Convert the list of enabled log levels to a map of enum -> boolean
68
     */
69
    static Map<LoggingLevel, Boolean> convertToMap(List<LoggingLevel> enabledLoggingLevels) {
70
        Map<LoggingLevel, Boolean> activeLogLevels = new EnumMap<>(LoggingLevel.class);
71
        for (LoggingLevel t : LoggingLevel.values()) {
72
            activeLogLevels.put(t, enabledLoggingLevels.contains(t));
73
        }
74 1 1. convertToMap : replaced return value with Collections.emptyMap for com/renomad/minum/logging/Logger::convertToMap → KILLED
        return activeLogLevels;
75
    }
76
77
    @Override
78
    public void logDebug(ThrowingSupplier<String, Exception> msg) {
79
        logHelper(msg, LoggingLevel.DEBUG, activeLogLevels, loggingActionQueue);
80
    }
81
82
    @Override
83
    public void logTrace(ThrowingSupplier<String, Exception> msg) {
84
        logHelper(msg, LoggingLevel.TRACE, activeLogLevels, loggingActionQueue);
85
    }
86
87
    @Override
88
    public void logAudit(ThrowingSupplier<String, Exception> msg) {
89
        logHelper(msg, LoggingLevel.AUDIT, activeLogLevels, loggingActionQueue);
90
    }
91
92
    @Override
93
    public void stop() {
94 1 1. stop : removed call to com/renomad/minum/queue/AbstractActionQueue::stop → TIMED_OUT
        this.loggingActionQueue.stop();
95
        this.executorService.shutdownNow();
96
    }
97
98
    @Override
99
    public void logAsyncError(ThrowingSupplier<String, Exception> msg) {
100
        logHelper(msg, LoggingLevel.ASYNC_ERROR, activeLogLevels, loggingActionQueue);
101
    }
102
103
    @Override
104
    public Map<LoggingLevel, Boolean> getActiveLogLevels() {
105 1 1. getActiveLogLevels : replaced return value with Collections.emptyMap for com/renomad/minum/logging/Logger::getActiveLogLevels → KILLED
        return activeLogLevels;
106
    }
107
108
    /**
109
     * A helper method to reduce duplication
110
     */
111
    static void logHelper(
112
            ThrowingSupplier<String, Exception> msg,
113
            LoggingLevel loggingLevel,
114
            Map<LoggingLevel, Boolean> activeLogLevels,
115
            AbstractActionQueue loggingActionQueue
116
            ) {
117 1 1. logHelper : negated conditional → TIMED_OUT
        if (Boolean.TRUE.equals(activeLogLevels.get(loggingLevel))) {
118
        String receivedMessage;
119
            try {
120
                receivedMessage = msg.get();
121
            } catch (Exception ex) {
122
                receivedMessage = "EXCEPTION DURING GET: " + ex;
123
            }
124
            String finalReceivedMessage = receivedMessage;
125 2 1. logHelper : negated conditional → KILLED
2. logHelper : negated conditional → KILLED
            if (loggingActionQueue == null || loggingActionQueue.isStopped()) {
126
                Object[] args = new Object[]{getTimestampIsoInstant(), loggingLevel.name(), showWhiteSpace(finalReceivedMessage)};
127
                System.out.printf("%s\t%s\t%s%n", args);
128
            } else {
129 1 1. logHelper : removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT
                loggingActionQueue.enqueue("Logger#logHelper(" + receivedMessage + ")", () -> {
130
                    Object[] args = new Object[]{getTimestampIsoInstant(), loggingLevel.name(), showWhiteSpace(finalReceivedMessage)};
131
                    System.out.printf("%s\t%s\t%s%n", args);
132
                });
133
            }
134
        }
135
    }
136
137
    /**
138
     * Given a string that may have whitespace chars, render it in a way we can see
139
     */
140
    static String showWhiteSpace(String msg) {
141 2 1. showWhiteSpace : negated conditional → TIMED_OUT
2. showWhiteSpace : replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED
        if (msg == null) return "(NULL)";
142 2 1. showWhiteSpace : replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED
2. showWhiteSpace : negated conditional → KILLED
        if (msg.isEmpty()) return "(EMPTY)";
143
144
        // if we have tabs, returns, newlines in the text, show them
145
        String text = msg
146
                .replace("\t", "\\t")
147
                .replace("\r", "\\r")
148
                .replace("\n", "\\n");
149
150 2 1. showWhiteSpace : negated conditional → KILLED
2. showWhiteSpace : replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED
        if (text.isBlank()) return "(BLANK)";
151 1 1. showWhiteSpace : replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → TIMED_OUT
        return text;
152
    }
153
154
}

Mutations

48

1.1
Location : <init>
Killed by : com.renomad.minum.web.SocketWrapperTests.testSendingSingleByte(com.renomad.minum.web.SocketWrapperTests)
negated conditional → KILLED

74

1.1
Location : convertToMap
Killed by : com.renomad.minum.web.SocketWrapperTests.testSendingSingleByte(com.renomad.minum.web.SocketWrapperTests)
replaced return value with Collections.emptyMap for com/renomad/minum/logging/Logger::convertToMap → KILLED

94

1.1
Location : stop
Killed by : none
removed call to com/renomad/minum/queue/AbstractActionQueue::stop → TIMED_OUT

105

1.1
Location : getActiveLogLevels
Killed by : com.renomad.minum.logging.LoggerTests.testEnableAndDisableTrace(com.renomad.minum.logging.LoggerTests)
replaced return value with Collections.emptyMap for com/renomad/minum/logging/Logger::getActiveLogLevels → KILLED

117

1.1
Location : logHelper
Killed by : none
negated conditional → TIMED_OUT

125

1.1
Location : logHelper
Killed by : com.renomad.minum.web.FullSystemTests.testFullSystem_EdgeCase_InstantlyClosed(com.renomad.minum.web.FullSystemTests)
negated conditional → KILLED

2.2
Location : logHelper
Killed by : com.renomad.minum.web.FullSystemTests.testFullSystem_EdgeCase_InstantlyClosed(com.renomad.minum.web.FullSystemTests)
negated conditional → KILLED

129

1.1
Location : logHelper
Killed by : none
removed call to com/renomad/minum/queue/AbstractActionQueue::enqueue → TIMED_OUT

141

1.1
Location : showWhiteSpace
Killed by : none
negated conditional → TIMED_OUT

2.2
Location : showWhiteSpace
Killed by : com.renomad.minum.logging.LoggerTests.testShowWhiteSpace(com.renomad.minum.logging.LoggerTests)
replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED

142

1.1
Location : showWhiteSpace
Killed by : com.renomad.minum.logging.LoggerTests.testShowWhiteSpace(com.renomad.minum.logging.LoggerTests)
replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED

2.2
Location : showWhiteSpace
Killed by : com.renomad.minum.logging.LoggerTests.testShowWhiteSpace(com.renomad.minum.logging.LoggerTests)
negated conditional → KILLED

150

1.1
Location : showWhiteSpace
Killed by : com.renomad.minum.logging.LoggerTests.testShowWhiteSpace(com.renomad.minum.logging.LoggerTests)
negated conditional → KILLED

2.2
Location : showWhiteSpace
Killed by : com.renomad.minum.logging.LoggerTests.testShowWhiteSpace(com.renomad.minum.logging.LoggerTests)
replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → KILLED

151

1.1
Location : showWhiteSpace
Killed by : none
replaced return value with "" for com/renomad/minum/logging/Logger::showWhiteSpace → TIMED_OUT

Active mutators

Tests examined


Report generated by PIT 1.17.0