/*
<File>
<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
<License see="prj:///Documentation/License.txt"/>
<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
<CreationDate>2007/11/19 20:00</CreationDate>
<LastSubmissionDate>$Date: $</LastSubmissionDate>
<Version>$Revision: $</Version>
</File>
*/
using System;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Diagnostics;
using System.Web.Configuration;
using Orpius.Logging.LogEntries;
namespace Orpius.Logging
{
/// <summary>
/// The main application log.
/// Use this static class to write to a
/// <see cref="ILogStrategy"/> defined in the current
/// <see cref="ILogStrategyProvider"/>.
/// </summary>
public static class Log
{
static ILogStrategyProvider provider;
static LogStrategyProviderCollection providers = null;
static readonly object providersLock = new object();
static ClientLoggingConfigSection section;
static List<IFilter> filters = new List<IFilter>();
static Log()
{
LoadProviders();
BuildFilters();
}
static void BuildFilters()
{
filters.Clear();
foreach (FilterElement element in section.FilterElements)
{
IFilter filter = element.BuildFilter();
filters.Add(filter);
}
}
static bool ValidateFilters(LogEntryOrigin origin)
{
foreach (IFilter filter in filters)
{
if (!filter.IsValid(origin))
{
return false;
}
}
return true;
}
internal static LogLevel GetLogLevel(string logName)
{
return provider.LogStrategy.GetLogLevel(logName);
}
internal static void LogMessage(IClientLogEntry logEntry)
{
provider.LogStrategy.Write(logEntry);
}
internal static void LogMessage(IServerLogEntry logEntry)
{
provider.LogStrategy.Write(logEntry);
}
/// <summary>
/// Loads the providers.
/// </summary>
static void LoadProviders()
{
/* Avoid claiming lock if providers are already loaded. */
if (provider == null)
{
lock (providersLock)
{
/* Do this again to make sure provider is still null. */
if (provider == null)
{
section = (ClientLoggingConfigSection)WebConfigurationManager.GetSection("ClientLogging");
/* Load registered providers and point provider
* to the default provider. */
providers = new LogStrategyProviderCollection();
ProvidersHelper.InstantiateProviders(section.Providers, providers, typeof(ILogStrategyProvider));
provider = providers[section.DefaultProvider];
if (provider == null)
{
throw new ProviderException("Unable to load default ILogProvider");
}
}
}
}
}
/// <summary>
/// Determines whether logging to the specified origin is enabled.
/// Checks whether the current provider is null
/// and if not, then whether all filters are validate.
/// Each <see cref="IFilter"/> makes use of the origin
/// parameter and decides whether it is, itself, valid.
/// If any filters are not valid, then this method
/// returns <code>false</code>.
/// </summary>
/// <param name="origin">The origin.</param>
/// <returns>
/// <c>true</c> if logging is enable; otherwise, <c>false</c>.
/// </returns>
public static bool IsEnabled(LogEntryOrigin origin)
{
return provider != null && ValidateFilters(origin);
}
#region Log writing overloads.
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Debug"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
public static void Debug(string message)
{
WriteLogEntry(LogLevel.Debug, message);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Debug"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
/// <param name="exception">The exception that this message
/// is regarding.</param>
public static void Debug(string message, Exception exception)
{
WriteLogEntry(LogLevel.Debug, message, exception);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Info"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
public static void Info(string message)
{
WriteLogEntry(LogLevel.Info, message);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Info"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
/// <param name="exception">The exception that this message
/// is regarding.</param>
public static void Info(string message, Exception exception)
{
WriteLogEntry(LogLevel.Info, message, exception);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Warn"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
public static void Warn(string message)
{
WriteLogEntry(LogLevel.Warn, message);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Warn"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
/// <param name="exception">The exception that this message
/// is regarding.</param>
public static void Warn(string message, Exception exception)
{
WriteLogEntry(LogLevel.Warn, message, exception);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Fatal"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
public static void Fatal(string message)
{
WriteLogEntry(LogLevel.Fatal, message);
}
/// <summary>
/// Writes a log entry at the <see cref="LogLevel.Fatal"/>
/// level to the active <see cref="ILogStrategy"/>.
/// </summary>
/// <param name="message">The message to write.</param>
/// <param name="exception">The exception that this message
/// is regarding.</param>
public static void Fatal(string message, Exception exception)
{
WriteLogEntry(LogLevel.Fatal, message, exception);
}
#endregion
static void WriteLogEntry(LogLevel logLevel, string message, Exception exception)
{
if (IsEnabled(LogEntryOrigin.Server))
{
CodeLocation location = GetCallerLocation();
ServerLogEntry entry = new ServerLogEntry(logLevel, message) {
CodeLocation = location,
Exception = exception,
OccuredAt = DateTime.Now,
LogName = location.ClassName
};
provider.LogStrategy.Write(entry);
}
}
static void WriteLogEntry(LogLevel logLevel, string message)
{
if (IsEnabled(LogEntryOrigin.Server))
{
CodeLocation location = GetCallerLocation();
ServerLogEntry entry = new ServerLogEntry(logLevel, message)
{
CodeLocation = GetCallerLocation(),
OccuredAt = DateTime.Now,
LogName = location.ClassName
};
provider.LogStrategy.Write(entry);
}
}
static CodeLocation GetCallerLocation()
{
StackTrace trace;
string className;
string methodName;
string fileName;
int lineNumber;
StackFrame frame = null;
try
{
trace = new StackTrace(true);
frame = trace.GetFrame(3);
}
catch (MethodAccessException ex)
{
System.Diagnostics.Debug.Fail("Unable to get stack trace." + ex);
}
if (frame != null)
{
className = frame.GetMethod().ReflectedType.FullName;
methodName = frame.GetMethod().Name;
fileName = frame.GetFileName();
lineNumber = frame.GetFileLineNumber();
}
else
{
className = string.Empty;
methodName = string.Empty;
fileName = string.Empty;
lineNumber = -1;
}
CodeLocation location = new CodeLocation()
{
ClassName = className,
MethodName = methodName,
FileName = fileName,
LineNumber = lineNumber
};
return location;
}
}
}