001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.util;
020
021import java.util.Collections;
022import java.util.LinkedHashMap;
023import java.util.Map;
024
025/**
026 * Represents a LogSource and adds several helpers
027 *
028 * @author apr@cs.com.uy
029 * @version $Revision$ $Date$
030 * @see LogSource
031 */
032public class Log implements LogSource {
033    /** Logger receiving the events produced by this {@code Log}. */
034    protected Logger logger;
035    /** Realm associated with events emitted through this {@code Log}. */
036    protected String realm;
037    /** Default tags applied to every {@link LogEvent} created by this {@code Log}. */
038    protected final Map<String,String> defaultTags = Collections.synchronizedMap(new LinkedHashMap<>());
039
040    /** Level constant for trace events. */
041    public static final String TRACE   = "trace";
042    /** Level constant for debug events. */
043    public static final String DEBUG   = "debug";
044    /** Level constant for informational events. */
045    public static final String INFO    = "info";
046    /** Level constant for warning events. */
047    public static final String WARN    = "warn";
048    /** Level constant for error events. */
049    public static final String ERROR   = "error";
050    /** Level constant for fatal events. */
051    public static final String FATAL   = "fatal";
052
053    /** Default constructor. */
054    public Log () {
055        super();
056    }
057    /**
058     * Convenience factory returning a {@code Log} bound to the given logger name and realm.
059     *
060     * @param logName name of the {@link Logger} to use
061     * @param realm realm to associate with emitted events
062     * @return a new {@code Log} instance
063     */
064    public static Log getLog (String logName, String realm) {
065        return new Log (Logger.getLogger (logName), realm);
066    }
067    /**
068     * Constructs a {@code Log} bound to the given logger and realm.
069     *
070     * @param logger underlying {@link Logger}
071     * @param realm realm to associate with emitted events
072     */
073    public Log (Logger logger, String realm) {
074        setLogger (logger, realm);
075    }
076    /**
077     * Replaces the underlying logger and realm.
078     *
079     * @param logger underlying {@link Logger}
080     * @param realm realm to associate with emitted events
081     */
082    public void setLogger (Logger logger, String realm) {
083        this.logger = logger;
084        this.realm  = realm;
085    }
086    /**
087     * Returns the realm associated with events emitted through this {@code Log}.
088     *
089     * @return the configured realm
090     */
091    public String getRealm () {
092        return realm;
093    }
094    /**
095     * Returns the underlying logger.
096     *
097     * @return the {@link Logger} receiving events from this {@code Log}
098     */
099    public Logger getLogger() {
100        return logger;
101    }
102    /**
103     * Replaces the underlying logger, leaving the realm unchanged.
104     *
105     * @param logger new {@link Logger}
106     */
107    public void setLogger (Logger logger) {
108        this.logger = logger;
109    }
110    /**
111     * Replaces the realm associated with emitted events.
112     *
113     * @param realm new realm
114     */
115    public void setRealm (String realm) {
116        this.realm = realm;
117    }
118    /**
119     * Sets a default tag on every event produced by this {@code Log};
120     * a {@code null} value removes the entry.
121     *
122     * @param key tag name (ignored if {@code null})
123     * @param value tag value, or {@code null} to remove the tag
124     */
125    public void setDefaultTag(String key, String value) {
126        if (key == null)
127            return;
128        if (value == null)
129            defaultTags.remove(key);
130        else
131            defaultTags.put(key, value);
132    }
133    /**
134     * Removes a previously-registered default tag.
135     *
136     * @param key tag name (ignored if {@code null})
137     */
138    public void removeDefaultTag(String key) {
139        if (key != null)
140            defaultTags.remove(key);
141    }
142    /**
143     * Replaces the entire set of default tags.
144     *
145     * @param tags new tag set, or {@code null}/empty to clear all tags
146     */
147    public void setDefaultTags(Map<String,String> tags) {
148        defaultTags.clear();
149        if (tags != null && !tags.isEmpty())
150            defaultTags.putAll(tags);
151    }
152    /**
153     * Returns an unmodifiable snapshot of the current default tags.
154     *
155     * @return a snapshot of the registered default tags
156     */
157    public Map<String,String> getDefaultTags() {
158        synchronized (defaultTags) {
159            return Collections.unmodifiableMap(new LinkedHashMap<>(defaultTags));
160        }
161    }
162    /**
163     * Decorates {@code evt} with this {@code Log}'s default tags, if any.
164     *
165     * @param evt the event to decorate
166     * @return the same event (for chaining)
167     */
168    protected LogEvent applyDefaultTags(LogEvent evt) {
169        synchronized (defaultTags) {
170            if (!defaultTags.isEmpty())
171                evt.withTags(defaultTags);
172        }
173        return evt;
174    }
175    /**
176     * Logs a trace event with the given detail.
177     *
178     * @param detail event payload
179     */
180    public void trace (Object detail) {
181        Logger.log (createTrace (detail));
182    }
183    /**
184     * Logs a trace event with the given detail and an additional payload.
185     *
186     * @param detail event payload
187     * @param obj additional message appended to the event
188     */
189    public void trace (Object detail, Object obj) {
190        LogEvent evt = createTrace (detail);
191        evt.addMessage (obj);
192        Logger.log (evt);
193    }
194    /**
195     * Logs a debug event with the given detail.
196     *
197     * @param detail event payload
198     */
199    public void debug (Object detail) {
200        Logger.log (createDebug (detail));
201    }
202    /**
203     * Logs a debug event with the given detail and an additional payload.
204     *
205     * @param detail event payload
206     * @param obj additional message appended to the event
207     */
208    public void debug (Object detail, Object obj) {
209        LogEvent evt = createDebug (detail);
210        evt.addMessage (obj);
211        Logger.log (evt);
212    }
213    /**
214     * Logs an info event with the given detail.
215     *
216     * @param detail event payload
217     */
218    public void info (Object detail) {
219        Logger.log (createInfo (detail));
220    }
221    /**
222     * Logs an info event with the given detail and an additional payload.
223     *
224     * @param detail event payload
225     * @param obj additional message appended to the event
226     */
227    public void info (Object detail, Object obj) {
228        LogEvent evt = createInfo (detail);
229        evt.addMessage (obj);
230        Logger.log (evt);
231    }
232    /**
233     * Logs a warning event with the given detail.
234     *
235     * @param detail event payload
236     */
237    public void warn (Object detail) {
238        Logger.log (createWarn (detail));
239    }
240    /**
241     * Logs a warning event with the given detail and an additional payload.
242     *
243     * @param detail event payload
244     * @param obj additional message appended to the event
245     */
246    public void warn (Object detail, Object obj) {
247        LogEvent evt = createWarn (detail);
248        evt.addMessage (obj);
249        Logger.log (evt);
250    }
251    /**
252     * Logs an error event with the given detail.
253     *
254     * @param detail event payload
255     */
256    public void error (Object detail) {
257        Logger.log (createError (detail));
258    }
259    /**
260     * Logs an error event with the given detail and an additional payload.
261     *
262     * @param detail event payload
263     * @param obj additional message appended to the event
264     */
265    public void error (Object detail, Object obj) {
266        LogEvent evt = createError (detail);
267        evt.addMessage (obj);
268        Logger.log (evt);
269    }
270    /**
271     * Logs a fatal event with the given detail.
272     *
273     * @param detail event payload
274     */
275    public void fatal (Object detail) {
276        Logger.log (createFatal (detail));
277    }
278    /**
279     * Logs a fatal event with the given detail and an additional payload.
280     *
281     * @param detail event payload
282     * @param obj additional message appended to the event
283     */
284    public void fatal (Object detail, Object obj) {
285        LogEvent evt = createFatal (detail);
286        evt.addMessage (obj);
287        Logger.log (evt);
288    }
289    /**
290     * Creates a new {@link LogEvent} at the given level decorated with this {@code Log}'s default tags.
291     *
292     * @param level event level (one of the {@code TRACE}/{@code DEBUG}/{@code INFO}/{@code WARN}/{@code ERROR}/{@code FATAL} constants)
293     * @return a new event ready to be populated and logged
294     */
295    public LogEvent createLogEvent (String level) {
296        return applyDefaultTags(new LogEvent (this, level));
297    }
298    /**
299     * Creates a new {@link LogEvent} at the given level with an initial payload.
300     *
301     * @param level event level
302     * @param detail initial event payload
303     * @return a new event ready to be populated and logged
304     */
305    public LogEvent createLogEvent (String level, Object detail) {
306        return applyDefaultTags(new LogEvent (this, level, detail));
307    }
308    /**
309     * Creates an empty trace-level event.
310     *
311     * @return a new {@link LogEvent} at the {@link #TRACE} level
312     */
313    public LogEvent createTrace () {
314        return createLogEvent (TRACE);
315    }
316    /**
317     * Creates a trace-level event with the given payload.
318     *
319     * @param detail initial event payload
320     * @return a new {@link LogEvent} at the {@link #TRACE} level
321     */
322    public LogEvent createTrace (Object detail) {
323        return createLogEvent (TRACE, detail);
324    }
325    /**
326     * Creates an empty debug-level event.
327     *
328     * @return a new {@link LogEvent} at the {@link #DEBUG} level
329     */
330    public LogEvent createDebug() {
331        return createLogEvent (DEBUG);
332    }
333    /**
334     * Creates a debug-level event with the given payload.
335     *
336     * @param detail initial event payload
337     * @return a new {@link LogEvent} at the {@link #DEBUG} level
338     */
339    public LogEvent createDebug(Object detail) {
340        return createLogEvent (DEBUG, detail);
341    }
342    /**
343     * Creates an empty info-level event.
344     *
345     * @return a new {@link LogEvent} at the {@link #INFO} level
346     */
347    public LogEvent createInfo () {
348        return createLogEvent (INFO);
349    }
350    /**
351     * Creates an info-level event with the given payload.
352     *
353     * @param detail initial event payload
354     * @return a new {@link LogEvent} at the {@link #INFO} level
355     */
356    public LogEvent createInfo (Object detail) {
357        return createLogEvent (INFO, detail);
358    }
359    /**
360     * Creates an empty warning-level event.
361     *
362     * @return a new {@link LogEvent} at the {@link #WARN} level
363     */
364    public LogEvent createWarn () {
365        return createLogEvent (WARN);
366    }
367    /**
368     * Creates a warning-level event with the given payload.
369     *
370     * @param detail initial event payload
371     * @return a new {@link LogEvent} at the {@link #WARN} level
372     */
373    public LogEvent createWarn (Object detail) {
374        return createLogEvent (WARN, detail);
375    }
376    /**
377     * Creates an empty error-level event.
378     *
379     * @return a new {@link LogEvent} at the {@link #ERROR} level
380     */
381    public LogEvent createError () {
382        return createLogEvent (ERROR);
383    }
384    /**
385     * Creates an error-level event with the given payload.
386     *
387     * @param detail initial event payload
388     * @return a new {@link LogEvent} at the {@link #ERROR} level
389     */
390    public LogEvent createError (Object detail) {
391        return createLogEvent (ERROR, detail);
392    }
393    /**
394     * Creates an empty fatal-level event.
395     *
396     * @return a new {@link LogEvent} at the {@link #FATAL} level
397     */
398    public LogEvent createFatal () {
399        return createLogEvent (FATAL);
400    }
401    /**
402     * Creates a fatal-level event with the given payload.
403     *
404     * @param detail initial event payload
405     * @return a new {@link LogEvent} at the {@link #FATAL} level
406     */
407    public LogEvent createFatal (Object detail) {
408        return createLogEvent (FATAL, detail);
409    }
410}