using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Filters;
namespace EntLibLoggingExtended
{
//
// By wrapping the EntLib Logger class we are able to strongly type the operation string values
// and priroty int values and limit them to the Category and Priority enum values.
//
// We also add some default Write methods for the common loggoing message types we will be using.
//
/// <summary>
/// Facade for writing a log entry to one or more <see cref="Microsoft.Practices.EnterpriseLibrary.LoggingTraceListener"/>s.
/// This class is sealed. This class wraps the <see cref="Microsoft.Practices.EnterpriseLibrary.Logger"/> class.
/// </summary>
public static class Logger
{
#region Enterprise Library Logger interface
//-----------------------------------------------------------------------------------------------------
private const Priority DefaultPriority = Priority.None;
private const TraceEventType DefaultSeverity = TraceEventType.Information;
private const int DefaultEventId = 1;
private const string DefaultTitle = "";
private static readonly CategoriesCollection emptyCategoriesList = new CategoriesCollection();
/// <summary>
/// Add a key/value pair to the <see cref="System.Runtime.Remoting.Messaging.CallContext"/> dictionary.
/// Context items will be recorded with every log entry.
/// </summary>
/// <param name="key">Hashtable key</param>
/// <param name="value">Value. Objects will be serialized.</param>
/// <example>The following example demonstrates use of the AddContextItem method.
/// <code>Logger.SetContextItem("SessionID", myComponent.SessionId);</code></example>
public static void SetContextItem(object key, object value)
{
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.SetContextItem(key, value);
}
/// <summary>
/// Empty the context items dictionary.
/// </summary>
public static void FlushContextItems()
{
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.FlushContextItems();
}
/// <overloads>
/// Write a new log entry to the default category.
/// </overloads>
/// <summary>
/// Write a new log entry to the default category.
/// </summary>
/// <example>The following example demonstrates use of the Write method with
/// one required parameter, message.
/// <code>Logger.Write("My message body");</code></example>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
public static void Write(object message)
{
Write(message, emptyCategoriesList, DefaultPriority,
DefaultEventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry to a specific category.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
public static void Write(object message, Category category)
{
Write(message, category, DefaultPriority, DefaultEventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific category and priority.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
public static void Write(object message, Category category, Priority priority)
{
Write(message, category, priority, DefaultEventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific category, priority and event id.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
public static void Write(object message, Category category, Priority priority, int eventId)
{
Write(message, category, priority, eventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific category, priority, event id and severity.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log entry severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
public static void Write(object message, Category category, Priority priority, int eventId, TraceEventType severity)
{
Write(message, category, priority, eventId, severity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific category, priority, event id, severity
/// and title.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log message severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
/// <param name="title">Additional description of the log entry message</param>
public static void Write(object message, Category category, Priority priority, int eventId,
TraceEventType severity, string title)
{
Write(message, category, priority, eventId, severity, title, null);
}
/// <summary>
/// Write a new log entry and a dictionary of extended properties.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, IDictionary<string, object> properties)
{
Write(message, emptyCategoriesList, DefaultPriority,
DefaultEventId, DefaultSeverity, DefaultTitle, properties);
}
/// <summary>
/// Write a new log entry to a specific category with a dictionary
/// of extended properties.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, Category category, IDictionary<string, object> properties)
{
Write(message, category, DefaultPriority, DefaultEventId, DefaultSeverity,
DefaultTitle, properties);
}
/// <summary>
/// Write a new log entry to with a specific category, priority and a dictionary
/// of extended properties.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, Category category, Priority priority, IDictionary<string, object> properties)
{
Write(message, category, priority, DefaultEventId, DefaultSeverity, DefaultTitle, properties);
}
/// <summary>
/// Write a new log entry with a specific category, priority, event Id, severity
/// title and dictionary of extended properties.
/// </summary>
/// <example>The following example demonstrates use of the Write method with
/// a full set of parameters.
/// <code></code></example>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log message severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
/// <param name="title">Additional description of the log entry message.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, Category category, Priority priority, int eventId,
TraceEventType severity, string title, IDictionary<string, object> properties)
{
CategoriesCollection categories = new CategoriesCollection();
categories.Add(category);
Write(message, categories, priority, eventId, severity, title, properties);
}
/// <summary>
/// Write a new log entry to a specific collection of categories.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
public static void Write(object message, CategoriesCollection categories)
{
Write(message, categories, DefaultPriority, DefaultEventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific collection of categories and priority.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
public static void Write(object message, CategoriesCollection categories, Priority priority)
{
Write(message, categories, priority, DefaultEventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific collection of categories, priority and event id.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
public static void Write(object message, CategoriesCollection categories, Priority priority, int eventId)
{
Write(message, categories, priority, eventId, DefaultSeverity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific collection of categories, priority, event id and severity.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log entry severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
public static void Write(object message, CategoriesCollection categories, Priority priority, int eventId, TraceEventType severity)
{
Write(message, categories, priority, eventId, severity, DefaultTitle, null);
}
/// <summary>
/// Write a new log entry with a specific collection of categories, priority, event id, severity
/// and title.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log message severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
/// <param name="title">Additional description of the log entry message</param>
public static void Write(object message, CategoriesCollection categories, Priority priority, int eventId,
TraceEventType severity, string title)
{
Write(message, categories, priority, eventId, severity, title, null);
}
/// <summary>
/// Write a new log entry to a specific collection of categories with a dictionary of extended properties.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, CategoriesCollection categories, IDictionary<string, object> properties)
{
Write(message, categories, DefaultPriority, DefaultEventId, DefaultSeverity,
DefaultTitle, properties);
}
/// <summary>
/// Write a new log entry to with a specific collection of categories, priority and a dictionary
/// of extended properties.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, CategoriesCollection categories, Priority priority, IDictionary<string, object> properties)
{
Write(message, categories, priority, DefaultEventId, DefaultSeverity, DefaultTitle, properties);
}
/// <summary>
/// Write a new log entry with a specific category, priority, event Id, severity
/// title and dictionary of extended properties.
/// </summary>
/// <example>The following example demonstrates use of the Write method with
/// a full set of parameters.
/// <code></code></example>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="categories">Category names used to route the log entry to a one or more trace listeners.</param>
/// <param name="priority">Only messages must be above the minimum priority are processed.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="severity">Log message severity as a <see cref="TraceEventType"/> enumeration. (Unspecified, Information, Warning or Error).</param>
/// <param name="title">Additional description of the log entry message.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void Write(object message, CategoriesCollection categories, Priority priority, int eventId,
TraceEventType severity, string title, IDictionary<string, object> properties)
{
LogEntry log = new LogEntry();
log.Message = message.ToString();
log.Categories = categories;
log.Priority = priority;
log.EventId = eventId;
log.Severity = severity;
log.Title = title;
log.ExtendedProperties = properties;
Write(log);
}
/// <summary>
/// Write a new log entry as defined in the <see cref="LogEntry"/> parameter.
/// </summary>
/// <example>The following examples demonstrates use of the Write method using
/// a <see cref="LogEntry"/> type.
/// <code>
/// LogEntry log = new LogEntry();
/// log.Category = "MyCategory1";
/// log.Message = "My message body";
/// log.Severity = TraceEventType.Error;
/// log.Priority = 100;
/// Logger.Write(log);</code></example>
/// <param name="log">Log entry object to write.</param>
public static void Write(LogEntry log)
{
Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.Write(log);
}
/// <summary>
/// Returns the filter of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of filter requiered.</typeparam>
/// <returns>The instance of <typeparamref name="T"/> in the filters collection, or <see langword="null"/>
/// if there is no such instance.</returns>
public static T GetFilter<T>()
where T : class, ILogFilter
{
return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.GetFilter<T>();
}
/// <summary>
/// Returns the filter of type <typeparamref name="T"/> named <paramref name="name"/>.
/// </summary>
/// <typeparam name="T">The type of filter required.</typeparam>
/// <param name="name">The name of the filter required.</param>
/// <returns>The instance of <typeparamref name="T"/> named <paramref name="name"/> in
/// the filters collection, or <see langword="null"/> if there is no such instance.</returns>
public static T GetFilter<T>(string name)
where T : class, ILogFilter
{
return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.GetFilter<T>(name);
}
/// <summary>
/// Returns the filter named <paramref name="name"/>.
/// </summary>
/// <param name="name">The name of the filter required.</param>
/// <returns>The filter named <paramref name="name"/> in
/// the filters collection, or <see langword="null"/> if there is no such filter.</returns>
public static ILogFilter GetFilter(string name)
{
return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.GetFilter(name);
}
/// <summary>
/// Query whether logging is enabled.
/// </summary>
/// <returns><code>true</code> if logging is enabled.</returns>
public static bool IsLoggingEnabled()
{
return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.IsLoggingEnabled();
}
/// <summary>
/// Query whether a <see cref="LogEntry"/> shold be logged.
/// </summary>
/// <param name="log">The log entry to check</param>
/// <returns>Returns <code>true</code> if the entry should be logged.</returns>
public static bool ShouldLog(LogEntry log)
{
return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer.ShouldLog(log);
}
/// <summary>
/// Gets the instance of <see cref="LogWriter"/> used by the facade.
/// </summary>
/// <remarks>
/// The lifetime of this instance is managed by the facade.
/// </remarks>
public static LogWriter Writer
{ get { return Microsoft.Practices.EnterpriseLibrary.Logging.Logger.Writer; } }
//-----------------------------------------------------------------------------------------------------
#endregion
#region Custom Write methods
//-----------------------------------------------------------------------------------------------------
/// <summary>
/// Write a new log entry with Category of Assert and Priority of Low
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
public static void WriteAssert(object message)
{
Write(message, Category.Assert, Priority.Low);
}
/// <summary>
/// Write a new log entry with Category of Debug and Priority of Debug
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
public static void WriteDebug(object message)
{
Write(message, Category.Debug, Priority.Debug);
}
/// <summary>
/// Write a new log entry with Category of Debug and Priority of Debug
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void WriteDebug(object message, IDictionary<string, object> properties)
{
Write(message, Category.Debug, Priority.Debug, properties);
}
/// <summary>
/// Write a new log entry with Category of Debug and Priority of Debug. Use this overload if a LogEntry
/// needed to be created for seeing whether the message would be logged. The Category of the LogEntry
/// will be set to Debug (should already be set to this though) and the Priority will be set to Debug
/// </summary>
/// <param name="log">Log entry object to write.</param>
public static void WriteDebug(LogEntry log)
{
if (!log.Categories.Contains(Category.Debug))
log.Categories.Add(Category.Debug);
log.Priority = Priority.Debug;
Write(log);
}
/// <summary>
/// Write a new log entry with Category of Trace and Priority of Trace. Only gets
/// written in DEBUG build.
/// </summary>
/// <param name="step">A label for the step in the code being taced.</param>
public static void WriteTrace(string step)
{
#if DEBUG
string message = "Trace: Step = '" + step + "' in method '" + GetExecutingMethodName() +
". Current activity = '" + Trace.CorrelationManager.ActivityId + "'.";
Write(message, Category.Trace, Priority.Trace);
#endif
}
/// <summary>
/// Write a new Information log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
public static void WriteInformation(object message, Category category, int eventId)
{
Write(message, category, Priority.Low, eventId, TraceEventType.Information, "Information");
}
/// <summary>
/// Write a new Information log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void WriteInformation(object message, Category category, int eventId, IDictionary<string, object> properties)
{
Write(message, category, Priority.Low, eventId, TraceEventType.Information, "Information", properties);
}
/// <summary>
/// Write a new Warning log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
public static void WriteWarning(object message, Category category, int eventId)
{
Write(message, category, Priority.Medium, eventId, TraceEventType.Warning, "Warning");
}
/// <summary>
/// Write a new Warning log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void WriteWarning(object message, Category category, int eventId, IDictionary<string, object> properties)
{
Write(message, category, Priority.Medium, eventId, TraceEventType.Warning, "Warning", properties);
}
/// <summary>
/// Write a new Error log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
public static void WriteError(object message, Category category, int eventId)
{
Write(message, category, Priority.High, eventId, TraceEventType.Error, "Error");
}
/// <summary>
/// Write a new Error log entry. This method is intended for writting to the Application
/// Event Log so use a Category that will be written to the Application Event Log for the
/// appropriate Source.
/// </summary>
/// <param name="message">Message body to log. Value from ToString() method from message object.</param>
/// <param name="category">Category name used to route the log entry to a one or more trace listeners.</param>
/// <param name="eventId">Event number or identifier.</param>
/// <param name="properties">Dictionary of key/value pairs to log.</param>
public static void WriteError(object message, Category category, int eventId, IDictionary<string, object> properties)
{
Write(message, category, Priority.High, eventId, TraceEventType.Error, "Error", properties);
}
//-----------------------------------------------------------------------------------------------------
#endregion
#region Private methods
//-----------------------------------------------------------------------------------------------------
/// <summary>
/// Finds the first method back in the stack trace that is not a method in this class
/// </summary>
/// <returns>The first method back in the stack trace that is not a method in this class</returns>
private static string GetExecutingMethodName()
{
string result = "Unknown";
StackTrace trace = new StackTrace(1, false);
for (int index = 0; index < trace.FrameCount; ++index)
{
StackFrame frame = trace.GetFrame(index);
MethodBase method = frame.GetMethod();
if (method.DeclaringType != typeof(Logger))
{
result = method.DeclaringType + "." + method.Name;
break;
}
}
return result;
}
//-----------------------------------------------------------------------------------------------------
#endregion
}
}