Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.background.common.log;
7 import java.io.PrintWriter;
8 import java.util.Iterator;
9 import java.util.LinkedHashSet;
10 import java.util.Set;
12 import org.mozilla.gecko.background.common.GlobalConstants;
13 import org.mozilla.gecko.background.common.log.writers.AndroidLevelCachingLogWriter;
14 import org.mozilla.gecko.background.common.log.writers.AndroidLogWriter;
15 import org.mozilla.gecko.background.common.log.writers.LogWriter;
16 import org.mozilla.gecko.background.common.log.writers.PrintLogWriter;
17 import org.mozilla.gecko.background.common.log.writers.SimpleTagLogWriter;
18 import org.mozilla.gecko.background.common.log.writers.ThreadLocalTagLogWriter;
20 import android.util.Log;
22 /**
23 * Logging helper class. Serializes all log operations (by synchronizing).
24 */
25 public class Logger {
26 public static final String LOGGER_TAG = "Logger";
27 public static final String DEFAULT_LOG_TAG = "GeckoLogger";
29 // For extra debugging.
30 public static boolean LOG_PERSONAL_INFORMATION = false;
32 /**
33 * Allow each thread to use its own global log tag. This allows
34 * independent services to log as different sources.
35 *
36 * When your thread sets up logging, it should do something like the following:
37 *
38 * Logger.setThreadLogTag("MyTag");
39 *
40 * The value is inheritable, so worker threads and such do not need to
41 * set the same log tag as their parent.
42 */
43 private static final InheritableThreadLocal<String> logTag = new InheritableThreadLocal<String>() {
44 @Override
45 protected String initialValue() {
46 return DEFAULT_LOG_TAG;
47 }
48 };
50 public static void setThreadLogTag(final String logTag) {
51 Logger.logTag.set(logTag);
52 }
53 public static String getThreadLogTag() {
54 return Logger.logTag.get();
55 }
57 /**
58 * Current set of writers to which we will log.
59 * <p>
60 * We want logging to be available while running tests, so we initialize
61 * this set statically.
62 */
63 protected final static Set<LogWriter> logWriters;
64 static {
65 final Set<LogWriter> defaultWriters = Logger.defaultLogWriters();
66 logWriters = new LinkedHashSet<LogWriter>(defaultWriters);
67 }
69 /**
70 * Default set of log writers to log to.
71 */
72 public final static Set<LogWriter> defaultLogWriters() {
73 final String processedPackage = GlobalConstants.BROWSER_INTENT_PACKAGE.replace("org.mozilla.", "");
75 final Set<LogWriter> defaultLogWriters = new LinkedHashSet<LogWriter>();
77 final LogWriter log = new AndroidLogWriter();
78 final LogWriter cache = new AndroidLevelCachingLogWriter(log);
80 final LogWriter single = new SimpleTagLogWriter(processedPackage, new ThreadLocalTagLogWriter(Logger.logTag, cache));
82 defaultLogWriters.add(single);
83 return defaultLogWriters;
84 }
86 public static synchronized void startLoggingTo(LogWriter logWriter) {
87 logWriters.add(logWriter);
88 }
90 public static synchronized void startLoggingToWriters(Set<LogWriter> writers) {
91 logWriters.addAll(writers);
92 }
94 public static synchronized void stopLoggingTo(LogWriter logWriter) {
95 try {
96 logWriter.close();
97 } catch (Exception e) {
98 Log.e(LOGGER_TAG, "Got exception closing and removing LogWriter " + logWriter + ".", e);
99 }
100 logWriters.remove(logWriter);
101 }
103 public static synchronized void stopLoggingToAll() {
104 for (LogWriter logWriter : logWriters) {
105 try {
106 logWriter.close();
107 } catch (Exception e) {
108 Log.e(LOGGER_TAG, "Got exception closing and removing LogWriter " + logWriter + ".", e);
109 }
110 }
111 logWriters.clear();
112 }
114 /**
115 * Write to only the default log writers.
116 */
117 public static synchronized void resetLogging() {
118 stopLoggingToAll();
119 logWriters.addAll(Logger.defaultLogWriters());
120 }
122 /**
123 * Start writing log output to stdout.
124 * <p>
125 * Use <code>resetLogging</code> to stop logging to stdout.
126 */
127 public static synchronized void startLoggingToConsole() {
128 setThreadLogTag("Test");
129 startLoggingTo(new PrintLogWriter(new PrintWriter(System.out, true)));
130 }
132 // Synchronized version for other classes to use.
133 public static synchronized boolean shouldLogVerbose(String logTag) {
134 for (LogWriter logWriter : logWriters) {
135 if (logWriter.shouldLogVerbose(logTag)) {
136 return true;
137 }
138 }
139 return false;
140 }
142 public static void error(String tag, String message) {
143 Logger.error(tag, message, null);
144 }
146 public static void warn(String tag, String message) {
147 Logger.warn(tag, message, null);
148 }
150 public static void info(String tag, String message) {
151 Logger.info(tag, message, null);
152 }
154 public static void debug(String tag, String message) {
155 Logger.debug(tag, message, null);
156 }
158 public static void trace(String tag, String message) {
159 Logger.trace(tag, message, null);
160 }
162 public static void pii(String tag, String message) {
163 if (LOG_PERSONAL_INFORMATION) {
164 Logger.debug(tag, "$$PII$$: " + message);
165 }
166 }
168 public static synchronized void error(String tag, String message, Throwable error) {
169 Iterator<LogWriter> it = logWriters.iterator();
170 while (it.hasNext()) {
171 LogWriter writer = it.next();
172 try {
173 writer.error(tag, message, error);
174 } catch (Exception e) {
175 Log.e(LOGGER_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
176 it.remove();
177 }
178 }
179 }
181 public static synchronized void warn(String tag, String message, Throwable error) {
182 Iterator<LogWriter> it = logWriters.iterator();
183 while (it.hasNext()) {
184 LogWriter writer = it.next();
185 try {
186 writer.warn(tag, message, error);
187 } catch (Exception e) {
188 Log.e(LOGGER_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
189 it.remove();
190 }
191 }
192 }
194 public static synchronized void info(String tag, String message, Throwable error) {
195 Iterator<LogWriter> it = logWriters.iterator();
196 while (it.hasNext()) {
197 LogWriter writer = it.next();
198 try {
199 writer.info(tag, message, error);
200 } catch (Exception e) {
201 Log.e(LOGGER_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
202 it.remove();
203 }
204 }
205 }
207 public static synchronized void debug(String tag, String message, Throwable error) {
208 Iterator<LogWriter> it = logWriters.iterator();
209 while (it.hasNext()) {
210 LogWriter writer = it.next();
211 try {
212 writer.debug(tag, message, error);
213 } catch (Exception e) {
214 Log.e(LOGGER_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
215 it.remove();
216 }
217 }
218 }
220 public static synchronized void trace(String tag, String message, Throwable error) {
221 Iterator<LogWriter> it = logWriters.iterator();
222 while (it.hasNext()) {
223 LogWriter writer = it.next();
224 try {
225 writer.trace(tag, message, error);
226 } catch (Exception e) {
227 Log.e(LOGGER_TAG, "Got exception logging; removing LogWriter " + writer + ".", e);
228 it.remove();
229 }
230 }
231 }
232 }