#region Copyright 2008-2014 by Roger Knapp, Licensed under the Apache License, Version 2.0 /* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #endregion using System; using System.Diagnostics; using System.IO; using System.Runtime.CompilerServices; /// /// Quick and dirty logging for components that do not have dependencies. /// [System.Diagnostics.DebuggerNonUserCode] internal static partial class Log { static int _init = 0; static TextWriter _textWriter = null; static TextWriterTraceListener _traceWriter = null; /// /// Allows you to close/open the writer /// public static void Open() { try { string fullName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), String.Format("{0}\\LogFile.txt", Process.GetCurrentProcess().ProcessName)); Directory.CreateDirectory(Path.GetDirectoryName(fullName)); string back = Path.ChangeExtension(fullName, ".bak"); if (File.Exists(back)) File.Delete(back); if (File.Exists(fullName)) File.Move(fullName, back); FileStream fsStream = File.Open(fullName, FileMode.Append, FileAccess.Write, FileShare.Read | FileShare.Delete); StreamWriter sw = new StreamWriter(fsStream); sw.AutoFlush = true; Open(TextWriter.Synchronized(sw)); } catch (Exception e) { Trace.WriteLine(e.ToString(), "CSharpTest.Net.QuickLog.Open()"); } } /// /// Redirects all log output to the provided text-writer /// public static void Open(TextWriter writer) { try { Close(); _init = 1; _textWriter = writer; Trace.Listeners.Add(_traceWriter = new TextWriterTraceListener(_textWriter)); } catch (Exception e) { Trace.WriteLine(e.ToString(), "CSharpTest.Net.QuickLog.Open()"); } } /// /// Returns the currently in-use text writer for log output /// public static TextWriter TextWriter { get { return _textWriter ?? TextWriter.Null; } } /// /// Allows you to close/open the writer /// public static void Close() { if (_traceWriter != null) { try { Trace.Listeners.Remove(_traceWriter); _traceWriter.Dispose(); } catch { } finally { _textWriter = null; _traceWriter = null; } } } [MethodImpl(MethodImplOptions.NoInlining)] public static void Error(Exception e) { InternalWrite(TraceLevel.Error, "{0}", e); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Warning(Exception e) { InternalWrite(TraceLevel.Warning, "{0}", e); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Error(string format, params object[] args) { InternalWrite(TraceLevel.Error, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Warning(string format, params object[] args) { InternalWrite(TraceLevel.Warning, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Info(string format, params object[] args) { InternalWrite(TraceLevel.Info, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Verbose(string format, params object[] args) { InternalWrite(TraceLevel.Verbose, format, args); } [MethodImpl(MethodImplOptions.NoInlining), Conditional("DEBUG")] public static void Debug(string format, params object[] args) { InternalWrite(TraceLevel.Verbose, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Write(string format, params object[] args) { InternalWrite(TraceLevel.Off, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static void Write(TraceLevel level, string format, params object[] args) { InternalWrite(level, format, args); } [MethodImpl(MethodImplOptions.NoInlining)] public static IDisposable Start(string format, params object[] args) { try { if (args.Length > 0) format = String.Format(format, args); InternalWrite(TraceLevel.Verbose, "Start {0}", format); } catch (Exception e) { Trace.WriteLine(e.ToString(), "CSharpTest.Net.QuickLog.Write()"); } return new TaskInfo(format); } [MethodImpl(MethodImplOptions.NoInlining)] public static IDisposable AppStart(string format, params object[] args) { try { if (args.Length > 0) format = String.Format(format, args); InternalWrite(TraceLevel.Verbose, "Start {0}", format); } catch (Exception e) { Trace.WriteLine(e.ToString(), "CSharpTest.Net.QuickLog.Write()"); } return new TaskInfo(format); } [System.Diagnostics.DebuggerNonUserCode] private class TaskInfo : IDisposable { private readonly DateTime _start; private readonly string _task; [MethodImpl(MethodImplOptions.NoInlining)] public TaskInfo(string task) { _task = task; _start = DateTime.Now; } [MethodImpl(MethodImplOptions.NoInlining)] void IDisposable.Dispose() { InternalWrite(TraceLevel.Verbose, "End {0} ({1} ms)", _task, (DateTime.Now - _start).TotalMilliseconds); } } [MethodImpl(MethodImplOptions.NoInlining)] private static void InternalWrite(TraceLevel level, string format, params object[] args) { try { if (_init == 0) { if (0 == System.Threading.Interlocked.Exchange(ref _init, 1)) { Open(); } } int depth = 2; if (args.Length > 0) format = String.Format(format, args); if (level <= _consoleLogLevel) Console_LogWrite(level, format); StackFrame frame; System.Reflection.MethodBase method; do { frame = new StackFrame(depth++); method = frame.GetMethod(); } while (method.ReflectedType.FullName.StartsWith("System.", StringComparison.OrdinalIgnoreCase) || method.ReflectedType.GetCustomAttributes(typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), true).Length > 0); string methodName, callingType; methodName = String.Format("{0}", method); callingType = String.Format("{0}", method.ReflectedType); string full = String.Format("{0:D2}{1,8} - {2} at {3}", System.Threading.Thread.CurrentThread.ManagedThreadId, level == TraceLevel.Off ? "None" : level.ToString(), format, methodName); Trace.WriteLine(full, callingType); if (LogWrite != null) LogWrite(method, level, format); } catch (Exception e) { Trace.WriteLine(e.ToString(), "CSharpTest.Net.QuickLog.Write()"); } } public delegate void LogEventHandler(System.Reflection.MethodBase method, TraceLevel level, string message); public static event LogEventHandler LogWrite; private static TraceLevel _consoleLogLevel = TraceLevel.Off; public static TraceLevel ConsoleLevel { get { return _consoleLogLevel;} set { _consoleLogLevel = value; } } static void Console_LogWrite(System.Diagnostics.TraceLevel level, string message) { if (String.IsNullOrEmpty(message) || level > _consoleLogLevel) return; lock (typeof(Console)) { if (level != TraceLevel.Warning && level != TraceLevel.Error) { Console.Out.WriteLine(message); } else { ConsoleColor clr = Console.ForegroundColor; if (level == System.Diagnostics.TraceLevel.Error) Console.ForegroundColor = ConsoleColor.Red; else Console.ForegroundColor = ConsoleColor.Yellow; Console.Error.WriteLine(message); Console.ForegroundColor = clr; } } } }