Compute lucene-style scores for our hits.
[beagle.git] / Util / Logger.cs
blob7a57fa41ba122e8f1afebebf0bf7b256bb7cc72a
1 //
2 // Logger.cs
3 //
4 // Copyright (C) 2004 Novell, Inc.
5 //
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
27 using System;
28 using System.Collections;
29 using System.Text;
30 using System.IO;
31 using System.Diagnostics;
33 namespace Beagle.Util {
35 public enum LogLevel {
36 None,
37 Fatal,
38 Error,
39 Warn,
40 Info,
41 Debug
44 public class Logger {
46 private static Hashtable loggers = new Hashtable ();
47 private static TextWriter defaultWriter = null;
48 private static bool defaultEcho = true; //false;
49 private static string defaultLogName = null;
51 // FIXME: The defaultLevel should be something higher
52 // than just LogLevel.Debug in the future. Users bitch
53 // about disk space.
54 private static LogLevel defaultLevel = LogLevel.Debug; //LogLevel.Info
56 public static Logger Log {
57 get {
58 return Get ("other");
62 public static Logger Get (string logName)
64 if (loggers.ContainsKey (logName)) {
65 return (Logger)loggers[logName];
66 } else {
67 Logger log = new Logger (logName);
68 log.Level = defaultLevel;
69 log.Writer = defaultWriter;
70 log.Echo = defaultEcho;
71 loggers[logName] = log;
72 return log;
76 public static LogLevel DefaultLevel {
77 get { return defaultLevel; }
78 set { defaultLevel = value; }
82 public static TextWriter DefaultWriter {
83 get { return defaultWriter; }
84 set { defaultWriter = value; }
87 public static bool DefaultEcho {
88 get { return defaultEcho; }
89 set { defaultEcho = value; }
92 private static object write_lock = new object ();
94 private bool levelSet = false;
95 private LogLevel level;
96 private TextWriter writer = null;
97 private bool echo = false;
99 private Logger (string name) {
102 public LogLevel Level {
103 get { lock (this) { return (levelSet) ? level : DefaultLevel; } }
104 set { lock (this) { level = value; levelSet = true; } }
107 public TextWriter Writer {
108 get { return writer; }
109 set { writer = value; }
112 public bool Echo {
113 get { return echo; }
114 set { echo = value; }
117 // Multiple logs can be merge-sorted via "sort -m log1 log2 ..."
118 private string GetStamp ()
120 StringBuilder builder = new StringBuilder ();
121 builder.AppendFormat ("{0:yy-MM-dd HH.mm.ss.ff} ", DateTime.Now);
122 builder.AppendFormat ("{0:00000} ", Process.GetCurrentProcess().Id);
123 if (defaultLogName != null) {
124 builder.AppendFormat (defaultLogName);
125 builder.Append (' ');
127 return builder.ToString ();
130 private void WriteLine (string level, string message) {
131 if (Writer != null) {
132 lock (write_lock) {
133 Writer.WriteLine ("{0}{1}: {2}", GetStamp (), level, message);
134 Writer.Flush ();
137 if (Echo)
138 System.Console.WriteLine ("{0}: {1}", level, message);
141 public void Debug (string message, params object [] args)
143 if (IsDebugEnabled) {
144 WriteLine ("DEBUG", String.Format (message, args));
148 public void Debug (Exception e)
150 Debug ("{0}", e);
153 public void Info (string message, params object [] args)
155 if (IsInfoEnabled) {
156 WriteLine ("INFO", String.Format (message, args));
160 public void Info (Exception e)
162 Info ("{0}", e);
165 public void Warn (string message, params object [] args)
167 if (IsWarnEnabled) {
168 WriteLine ("WARN", String.Format (message, args));
172 public void Warn (Exception e)
174 Warn ("{0}", e);
177 public void Error (string message, params object [] args)
179 if (IsErrorEnabled) {
180 WriteLine ("ERROR", String.Format (message, args));
184 public void Error (Exception e)
186 Error ("{0}", e);
189 public void Fatal (string message, params object [] args)
191 if (IsFatalEnabled) {
192 WriteLine ("FATAL", String.Format (message, args));
196 public void Fatal (Exception e)
198 Fatal ("{0}", e);
201 public bool IsDebugEnabled { get { return level >= LogLevel.Debug; } }
202 public bool IsInfoEnabled { get { return level >= LogLevel.Info; } }
203 public bool IsWarnEnabled { get { return level >= LogLevel.Warn; } }
204 public bool IsErrorEnabled { get { return level >= LogLevel.Error;} }
205 public bool IsFatalEnabled { get { return level >= LogLevel.Fatal; } }
207 ////////////////////////////////////////////////////////////////////////////////
209 static private void PruneOldLogs (string path, string instance)
211 DateTime magic_date = DateTime.Now.AddDays (-7);
212 DirectoryInfo dir = new DirectoryInfo (path);
214 foreach (FileInfo file in dir.GetFiles ()) {
215 if (file.Name.StartsWith ("current") || (! file.Name.EndsWith (instance)))
216 continue;
218 int last_dash = file.Name.LastIndexOf ("-");
219 if (last_dash == -1)
220 continue; // skip strange-looking files
222 string date = file.Name.Substring (0, last_dash);
224 try {
225 DateTime log_date;
226 log_date = DateTime.ParseExact (date, "yyyy-MM-dd-HH-mm-ss", null);
227 if (log_date < magic_date)
228 file.Delete ();
229 } catch (Exception e) { }
233 static public void LogToFile (string path, string name, bool foreground_mode)
235 defaultLogName = name;
236 if (defaultLogName.Length > 6)
237 defaultLogName = defaultLogName.Substring (0, 6);
238 else
239 defaultLogName = defaultLogName.PadRight (6);
241 string timestamped_name = String.Format ("{0:yyyy-MM-dd-HH-mm-ss}-{1}", DateTime.Now, name);
242 string log_path = Path.Combine (path, timestamped_name);
243 string log_link = Path.Combine (path, "current-" + name);
245 // Delete old and obsolete log files
246 PruneOldLogs (path, name);
248 // Open the log file and set it as the default
249 // destination for log messages.
250 // Also redirect stdout and stderr to the same file.
251 FileStream log_stream = new FileStream (log_path,
252 FileMode.Append,
253 FileAccess.Write,
254 FileShare.Write);
255 TextWriter log_writer = new StreamWriter (log_stream);
257 File.Delete (log_link);
258 Mono.Posix.Syscall.symlink (log_path, log_link);
260 Logger.DefaultWriter = log_writer;
261 Logger.DefaultEcho = foreground_mode;
263 if (! foreground_mode) {
265 // Redirect stdout and stderr to the logfile
266 Console.SetOut (Logger.DefaultWriter);
267 Console.SetError (Logger.DefaultWriter);
269 // Redirect stdin to /dev/null
270 FileStream dev_null_stream = new FileStream ("/dev/null",
271 FileMode.Open,
272 FileAccess.Read,
273 FileShare.ReadWrite);
274 TextReader dev_null_reader = new StreamReader (dev_null_stream);
275 Console.SetIn (dev_null_reader);
279 ////////////////////////////////////////////////////////////////////////////////
281 static Logger ()
283 // Parse the contents of the BEAGLE_DEBUG environment variable
284 // and adjust the default log levels accordingly.
285 string debug = System.Environment.GetEnvironmentVariable ("BEAGLE_DEBUG");
286 if (debug != null) {
287 string[] debugArgs = debug.Split (',');
288 foreach (string arg in debugArgs) {
289 if (arg.Trim () == "all") {
290 Logger.DefaultLevel = LogLevel.Debug;
294 foreach (string arg_raw in debugArgs) {
295 string arg = arg_raw.Trim ();
297 if (arg.Length == 0 || arg == "all")
298 continue;
300 if (arg[0] == '-') {
301 string name = arg.Substring (1);
302 Logger log = Logger.Get (name);
303 log.Level = LogLevel.Info;
304 } else {
305 Logger log = Logger.Get (arg);
306 log.Level = LogLevel.Debug;