001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010-2011 ApexIdentity Inc.
015 * Portions Copyright 2011-2014 ForgeRock AS.
016 */
017
018package org.forgerock.openig.log;
019
020import org.forgerock.openig.heap.Name;
021
022/**
023 * Wraps a log sink and exposes a set of convenience methods for various logging activities.
024 */
025public class Logger {
026
027    /** The sink to write log entries to. */
028    private final LogSink sink;
029
030    /** The base source to write all log entries with. */
031    private final Name source;
032
033    /**
034     * Constructs a new logger. If the supplied sink is {@code null}, then a
035     * {@link NullLogSink} will be used.
036     *  @param sink the sink to write log entries to.
037     * @param source the base source to write all log entries with.
038     */
039    public Logger(LogSink sink, Name source) {
040        this.sink = (sink != null ? sink : new NullLogSink());
041        this.source = source;
042    }
043
044    /**
045     * Logs the message at the specified log level.
046     *
047     * @param level the log level to set in the log entry.
048     * @param message the message to be logged.
049     */
050    public void logMessage(LogLevel level, String message) {
051        log(createEntry("log", level, message));
052    }
053
054    /**
055     * Logs the specified exception.
056     *
057     * @param level the log level to set in the log entry.
058     * @param throwable the exception to be logged.
059     * @param <T> type of logged throwable
060     * @return the exception being logged.
061     */
062    public <T extends Throwable> T logException(LogLevel level, T throwable) {
063        log(createEntry("throwable", level, throwable.getMessage(), throwable));
064        return throwable;
065    }
066
067    /**
068     * Logs the specified message at the {@code ERROR} log level.
069     *
070     * @param message the message to be logged.
071     */
072    public void error(String message) {
073        logMessage(LogLevel.ERROR, message);
074    }
075
076    /**
077     * Logs the specified exception at the {@code ERROR} log level.
078     *
079     * @param throwable the exception to be logged.
080     * @param <T> type of logged throwable
081     * @return the exception being logged.
082     */
083    public <T extends Throwable> T error(T throwable) {
084        return logException(LogLevel.ERROR, throwable);
085    }
086
087    /**
088     * Logs the specified message at the {@code WARNING} log level.
089     *
090     * @param message the message to be logged.
091     */
092    public void warning(String message) {
093        logMessage(LogLevel.WARNING, message);
094    }
095
096    /**
097     * Logs the specified exception at the {@code WARNING} log level.
098     *
099     * @param throwable the exception to be logged.
100     * @param <T> type of logged throwable
101     * @return the exception being logged.
102     */
103    public <T extends Throwable> T warning(T throwable) {
104        return logException(LogLevel.WARNING, throwable);
105    }
106
107    /**
108     * Logs the specified message at the {@code INFO} log level.
109     *
110     * @param message the message to be logged.
111     */
112    public void info(String message) {
113        logMessage(LogLevel.INFO, message);
114    }
115
116    /**
117     * Logs the specified exception at the {@code INFO} log level.
118     *
119     * @param throwable the exception to be logged.
120     * @param <T> type of logged throwable
121     * @return the exception being logged.
122     */
123    public <T extends Throwable> T info(T throwable) {
124        return logException(LogLevel.INFO, throwable);
125    }
126
127    /**
128     * Logs the specified message at the {@code CONFIG} log level.
129     *
130     * @param message the message to be logged.
131     */
132    public void config(String message) {
133        logMessage(LogLevel.CONFIG, message);
134    }
135
136    /**
137     * Logs the specified exception at the {@code CONFIG} log level.
138     *
139     * @param throwable the exception to be logged.
140     * @param <T> type of logged throwable
141     * @return the exception being logged.
142     */
143    public <T extends Throwable> T config(T throwable) {
144        return logException(LogLevel.CONFIG, throwable);
145    }
146
147    /**
148     * Logs the specified message at the {@code DEBUG} log level.
149     *
150     * @param message the message to be logged.
151     */
152    public void debug(String message) {
153        logMessage(LogLevel.DEBUG, message);
154    }
155
156    /**
157     * Logs the specified exception at the {@code DEBUG} log level.
158     *
159     * @param throwable the exception to be logged.
160     * @param <T> type of logged throwable
161     * @return the exception being logged.
162     */
163    public <T extends Throwable> T debug(T throwable) {
164        return logException(LogLevel.DEBUG, throwable);
165    }
166
167    /**
168     * Logs the specified message at the {@code TRACE} log level.
169     *
170     * @param message the message to be logged.
171     */
172    public void trace(String message) {
173        logMessage(LogLevel.TRACE, message);
174    }
175
176    /**
177     * Logs the specified exception at the {@code TRACE} log level.
178     *
179     * @param throwable the exception to be logged.
180     * @param <T> type of logged throwable
181     * @return the exception being logged.
182     */
183    public <T extends Throwable> T trace(T throwable) {
184        return logException(LogLevel.TRACE, throwable);
185    }
186
187    /**
188     * Returns a new timer to measure elapsed time. Entries are written to the log with a
189     * {@code STAT} log level.
190     * @return A timer to measure elapsed time.
191     */
192    public LogTimer getTimer() {
193        return new LogTimer(this, LogLevel.STAT);
194    }
195
196    /**
197     * Returns a new timer to measure elapsed time for a specified event. The event is
198     * appended to the source in hierarchical fashion. Entries are written to the log with a
199     * {@code STAT} log level.
200     *
201     * @param event the event that is being timed.
202     * @return A timer to measure elapsed time for a specified event.
203     */
204    public LogTimer getTimer(String event) {
205        return new LogTimer(this, LogLevel.STAT, event);
206    }
207
208    /**
209     * Creates a {@link LogEntry} with the given parameters and no attached data.
210     * The created entry will inherit the source name of this logger.
211     *
212     * @param type
213     *         entry type (free form tag String like {@literal log}, {@literal started} or {@literal elapsed}).
214     * @param level
215     *         entry's level
216     * @param message
217     *         entry's message
218     * @return a new entry with no attached data
219     */
220    LogEntry createEntry(final String type, final LogLevel level, final String message) {
221        return createEntry(type, level, message, null);
222    }
223
224    /**
225     * Creates a {@link LogEntry} with the given parameters and attached data (possibly {@code null} data).
226     * The created entry will inherit the source name of this logger.
227     *
228     * @param type
229     *         entry type (free form tag String like {@literal log}, {@literal started} or {@literal elapsed}).
230     * @param level
231     *         entry's level
232     * @param message
233     *         entry's message
234     * @param data
235     *         entry's attached data
236     * @return a new entry with attached data (possibly {@code null} data)
237     */
238    LogEntry createEntry(final String type, final LogLevel level, final String message, final Object data) {
239        return new LogEntry(source, type, level, message, data);
240    }
241
242    /**
243     * Logs an entry. This implementation will prepend the logger source to all log entries.
244     *
245     * @param entry the entry to be logged.
246     */
247    public void log(LogEntry entry) {
248        sink.log(entry);
249    }
250
251    /**
252     * Returns {@code true} if the entry may be logged, given the specified source name and log
253     * level.
254     *
255     * @param source the source name that is intended to be logged.
256     * @param level the log level of the entry to be logged.
257     * @return {@code true} if the entry may be logged.
258     */
259    public boolean isLoggable(Name source, LogLevel level) {
260        return sink.isLoggable(source, level);
261    }
262
263    /**
264     * Returns {@code true} if the entry may be logged, given the source of this logger and
265     * the specified log level.
266     *
267     * @param level the log level of the entry to be logged.
268     * @return {@code true} if the entry may be logged.
269     */
270    public boolean isLoggable(LogLevel level) {
271        return sink.isLoggable(this.source, level);
272    }
273}