/source/D3Sharp/Utils/TinyLogger.cs
C# | 273 lines | 193 code | 49 blank | 31 comment | 15 complexity | 7aac4339231336dc2758f8cf2af472cf MD5 | raw file
1/*
2 * Copyright (C) 2011 D3Sharp Project
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19using System;
20using System.Collections.Generic;
21using System.Diagnostics;
22using System.Globalization;
23using System.IO;
24using System.Linq;
25
26namespace D3Sharp.Utils
27{
28 public enum Level
29 {
30 Trace,
31 Debug,
32 Info,
33 Warn,
34 Error,
35 Fatal,
36 Incoming,
37 Outgoing,
38 }
39
40 public static class LogManager
41 {
42 public static bool Enabled { get; set; }
43
44 internal readonly static List<Target> Targets = new List<Target>();
45 internal static readonly Dictionary<string, Logger> Loggers = new Dictionary<string, Logger>();
46
47 public static void AttachLogTarget(Target target)
48 {
49 Targets.Add(target);
50 }
51
52 public static Logger CreateLogger()
53 {
54 var frame = new StackFrame(1, false);
55 var name = frame.GetMethod().DeclaringType.Name;
56 if (name == null) throw new Exception("Error getting full name for declaring type.");
57 if (!Loggers.ContainsKey(name)) Loggers.Add(name, new Logger(name));
58 return Loggers[name];
59 }
60
61 public static Logger CreateLogger(string name)
62 {
63 if (!Loggers.ContainsKey(name)) Loggers.Add(name, new Logger(name));
64 return Loggers[name];
65 }
66 }
67
68 internal static class LogRouter
69 {
70 public static void RouteMessage(Level level, string logger, string message)
71 {
72 if (!LogManager.Enabled) return;
73 if (LogManager.Targets.Count == 0) return;
74
75 foreach (var target in LogManager.Targets.Where(target => level >= target.MinimumLevel))
76 {
77 target.LogMessage(level, logger, message);
78 }
79 }
80
81 public static void RouteException(Level level, string logger, string message, Exception exception)
82 {
83 if (!LogManager.Enabled) return;
84 if (LogManager.Targets.Count == 0) return;
85
86 foreach (var target in LogManager.Targets.Where(target => level >= target.MinimumLevel))
87 {
88 target.LogException(level, logger, message, exception);
89 }
90 }
91 }
92
93 public class Logger
94 {
95 public string Name { get; protected set; }
96
97 public Logger(string name)
98 {
99 Name = name;
100 }
101
102 private void Log(Level level, string message, object[] args)
103 {
104 LogRouter.RouteMessage(level, this.Name, args == null ? message : string.Format(CultureInfo.InvariantCulture, message, args));
105 }
106
107 private void LogException(Level level, string message, object[] args, Exception exception)
108 {
109 LogRouter.RouteException(level, this.Name, args == null ? message : string.Format(CultureInfo.InvariantCulture, message, args), exception);
110 }
111
112 public void Trace(string message) { Log(Level.Trace, message, null); }
113 public void Trace(string message, params object[] args) { Log(Level.Trace, message, args); }
114
115 public void Debug(string message) { Log(Level.Debug, message, null); }
116 public void Debug(string message, params object[] args) { Log(Level.Debug, message, args); }
117
118 public void Info(string message) { Log(Level.Info, message, null); }
119 public void Info(string message, params object[] args) { Log(Level.Info, message, args); }
120
121 public void Warn(string message) { Log(Level.Warn, message, null); }
122 public void Warn(string message, params object[] args) { Log(Level.Warn, message, args); }
123
124 public void Error(string message) { Log(Level.Error, message, null); }
125 public void Error(string message, params object[] args) { Log(Level.Error, message, args); }
126
127 public void Fatal(string message) { Log(Level.Fatal, message, null); }
128 public void Fatal(string message, params object[] args) { Log(Level.Fatal, message, args); }
129
130 public void TraceException(Exception exception, string message) { LogException(Level.Trace, message, null, exception); }
131 public void TraceException(Exception exception, string message, params object[] args) { LogException(Level.Trace, message, args, exception); }
132
133 public void DebugException(Exception exception, string message) { LogException(Level.Debug, message, null, exception); }
134 public void DebugException(Exception exception, string message, params object[] args) { LogException(Level.Debug, message, args, exception); }
135
136 public void InfoException(Exception exception, string message) { LogException(Level.Info, message, null, exception); }
137 public void InfoException(Exception exception, string message, params object[] args) { LogException(Level.Info, message, args, exception); }
138
139 public void WarnException(Exception exception, string message) { LogException(Level.Warn, message, null, exception); }
140 public void WarnException(Exception exception, string message, params object[] args) { LogException(Level.Warn, message, args, exception); }
141
142 public void ErrorException(Exception exception, string message) { LogException(Level.Error, message, null, exception); }
143 public void ErrorException(Exception exception, string message, params object[] args) { LogException(Level.Error, message, args, exception); }
144
145 public void FatalException(Exception exception, string message) { LogException(Level.Fatal, message, null, exception); }
146 public void FatalException(Exception exception, string message, params object[] args) { LogException(Level.Fatal, message, args, exception); }
147
148 public void LogIncoming(Google.ProtocolBuffers.IMessage msg) { Log(Level.Incoming, msg.AsText(), null); }
149 public void LogOutgoing(Google.ProtocolBuffers.IMessage msg) { Log(Level.Outgoing, msg.AsText(), null); }
150 public void LogIncoming(D3Sharp.Net.Game.Packets.GameMessage msg) { Log(Level.Incoming, msg.AsText(), null); }
151 public void LogOutgoing(D3Sharp.Net.Game.Packets.GameMessage msg) { Log(Level.Outgoing, msg.AsText(), null); }
152 }
153
154 public class Target
155 {
156 public Level MinimumLevel { get; protected set; }
157 public virtual void LogMessage(Level level, string logger, string message) { throw new NotSupportedException(); }
158 public virtual void LogException(Level level, string logger, string message, Exception exception) { throw new NotSupportedException(); }
159 }
160
161 public class FileTarget : Target, IDisposable
162 {
163 private readonly string _filePath;
164
165 private FileStream _fileStream;
166 private StreamWriter _logStream;
167
168 public FileTarget(Level minLevel, string filePath)
169 {
170 MinimumLevel = minLevel;
171 _filePath = filePath;
172 this._fileStream = new FileStream(_filePath, FileMode.Append, FileAccess.Write);
173 this._logStream = new StreamWriter(this._fileStream);
174 this._logStream.AutoFlush = true;
175 }
176
177 public override void LogMessage(Level level, string logger, string message)
178 {
179 this._logStream.WriteLine(string.Format("[{0}] [{1}]: {2}", level.ToString().PadLeft(5), logger, message));
180 }
181
182 public override void LogException(Level level, string logger, string message, Exception exception)
183 {
184 this._logStream.WriteLine(string.Format("[{0}] [{1}]: {2} - [Exception] {3}", level.ToString().PadLeft(5), logger, message, exception));
185 }
186
187 #region de-ctor
188
189 // IDisposable pattern: http://msdn.microsoft.com/en-us/library/fs2xkftw%28VS.80%29.aspx
190
191 private bool _disposed = false;
192 public void Dispose()
193 {
194 Dispose(true);
195 GC.SuppressFinalize(this); // Take object out the finalization queue to prevent finalization code for it from executing a second time.
196 }
197
198 private void Dispose(bool disposing)
199 {
200 if (this._disposed) return; // if already disposed, just return
201
202 if (disposing) // only dispose managed resources if we're called from directly or in-directly from user code.
203 {
204 this._logStream.Close();
205 this._logStream.Dispose();
206 this._fileStream.Close();
207 this._fileStream.Dispose();
208 }
209
210 this._logStream = null;
211 this._fileStream = null;
212
213 _disposed = true;
214 }
215
216 ~FileTarget() { Dispose(false); } // finalizer called by the runtime. we should only dispose unmanaged objects and should NOT reference managed ones.
217
218 #endregion
219 }
220
221 public class ConsoleTarget : Target
222 {
223 // Win32 API constants.
224 private const int StdOutputHandle = -11;
225 private const int CodePage = 437;
226
227 public ConsoleTarget(Level minLevel, bool initConsole = false)
228 {
229 MinimumLevel = minLevel;
230 // if (initConsole) InitConsole(); TODO: Make sure only get compiled in win32
231 }
232
233 // TODO: Make sure only get compiled in win32
234 /*private static void InitConsole() // binds a new console window to a windowed application.
235 {
236 NativeMethods.AllocConsole(); // allocate a new console window.
237 var stdHandle = NativeMethods.GetStdHandle(StdOutputHandle); // the stdout handle.
238 var safeFileHandle = new Microsoft.Win32.SafeHandles.SafeFileHandle(stdHandle, true);
239 var fileStream = new FileStream(safeFileHandle, FileAccess.Write);
240 var encoding = Encoding.GetEncoding(CodePage);
241 var standardOutput = new StreamWriter(fileStream, encoding) { AutoFlush = true };
242 Console.SetOut(standardOutput); // set console's output stream to stdout.
243 }*/
244
245 public override void LogMessage(Level level, string logger, string message)
246 {
247 SetForeGroundColor(level);
248 Console.WriteLine(string.Format("[{0}] [{1}]: {2}", level.ToString().PadLeft(5), logger, message));
249 }
250
251 public override void LogException(Level level, string logger, string message, Exception exception)
252 {
253 SetForeGroundColor(level);
254 Console.WriteLine(string.Format("[{0}] [{1}]: {2} - [Exception] {3}", level.ToString().PadLeft(5), logger, message, exception));
255 }
256
257 private static void SetForeGroundColor(Level level)
258 {
259 switch (level)
260 {
261 case Level.Trace: Console.ForegroundColor = ConsoleColor.DarkGray; break;
262 case Level.Debug: Console.ForegroundColor = ConsoleColor.Gray; break;
263 case Level.Info: Console.ForegroundColor = ConsoleColor.White; break;
264 case Level.Warn: Console.ForegroundColor = ConsoleColor.Yellow; break;
265 case Level.Error: Console.ForegroundColor = ConsoleColor.Magenta; break;
266 case Level.Fatal: Console.ForegroundColor = ConsoleColor.Red; break;
267 case Level.Incoming:
268 case Level.Outgoing: Console.ForegroundColor = ConsoleColor.White; break;
269 default: break;
270 }
271 }
272 }
273}