Welcome to CuttingEdge.Logging
CuttingEdge.Logging is a library that helps programmers to output log statements to a variety of output targets in .NET applications. The design is based on the .NET 2.0 Provider Model. This means the library uses the same configuration and extensibility model.
Overview
CuttingEdge.Logging is a configurable logging system and can even be plugged into ASP.NET applications without a republish or recompile. The library is written in C# .NET 3.5 in Visual Studio 2008, but the library can also be used by .NET 2.0 applications. It can be used for several types of .NET applications, such as server and desktop applications. However, Compact Edition and Silverlight are not supported.
Comparing
CuttingEdge.Logging differentiates with other logging frameworks such as
log4net and the
Enterprise Library Logging Application Block (LAB) in it's simplicity. CuttingEdge.Logging does not allow you to configure layouts (log4net) or formatters (LAB) to control the way events are written. Neither does it support filters (log4net and LAB) to determine which event should be logged and where to. log4net even allows you to change configuration, without an application restart (
dynamic configuration) and it's compatible with Mono, .NET CE and even SSCLI.
While those two frameworks are highly configurable and composable; they are complex to configure and use. CuttingEdge.Logging is designed with the
KISS principle (keep it small, simple) in mind. You won't have to read large manuals and when you are familiar with the .NET provider model, you'll feel right at home.
Usage
C# example
The following example shows some code snippets of what code a C# developer could write using CuttingEdge.Logging.
// Log an information event to the default provider.
Logger.Log("Operation completed successfully.");
// Log a warning to the default provider.
Logger.Log(LoggingEventType.Warning, "Server is currently under high load");
// Log an error event with source location to the default provider.
Logger.Log(LoggingEventType.Error,
"Something went wrong.", MethodBase.GetCurrentMethod());
try
{
this.DoSomeAction();
}
catch (Exception ex)
{
// Log an exception to the default provider.
Logger.Log(ex);
throw;
}
// Log an information event to the default provider.
// This is equivalent to calling 'Logger.Log'.
Logger.Provider.Log("Success!", MethodBase.GetCurrentMethod());
// Log to an alternative provider by name (note that name is case-insensitive).
LoggingProviderBase xmlLogger = Logger.Providers["XmlLogger"];
xmlLogger.Log("Success!");
// Display all configured providers
foreach (LoggingProviderBase loggingProvider in Logger.Providers)
{
Console.WriteLine(loggingProvider.Name);
}
// Logging providers can be chained. Using fallback providers.
// This way you can ensure a event is being logged, even if the
// default provider fails.
LoggingProviderBase fallbackProvider = Logger.Provider.FallbackProvider;
if (fallbackProvider != null)
{
fallbackProvider.Log(LoggingEventType.Warning, "This is a warning.");
}
VB.NET example
The following example shows some code snippets of what code a VB.NET developer could write using CuttingEdge.Logging.
' Log an information event to the default provider.
Logger.Log("Operation completed successfully.")
' Log a warning to the default provider.
Logger.Log(LoggingEventType.Warning, "Server is currently under high load")
' Log an error event with source location to the default provider.
Logger.Log(LoggingEventType.[Error], _
"Something went wrong.", MethodBase.GetCurrentMethod())
Try
DoSomeAction()
Catch ex As Exception
' Log an exception to the default provider.
Logger.Log(ex)
Throw
End Try
' Log an information event to the default provider.
' This is equivalent to calling 'Logger.Log'.
Logger.Provider.Log("Success!", MethodBase.GetCurrentMethod())
' Log to an alternative provider by name (note that name is case-insensitive).
Dim xmlLogger As LoggingProviderBase = Logger.Providers("XmlLogger")
xmlLogger.Log("Success!")
' Display all configured providers
For Each loggingProvider As LoggingProviderBase In Logger.Providers
Console.WriteLine(loggingProvider.Name)
Next
' Logging providers can be chained. Using fallback providers.
' This way you can ensure a event is being logged, even if the
' default provider fails.
Dim fallbackProvider As LoggingProviderBase = Logger.Provider.FallbackProvider
If fallbackProvider IsNot Nothing Then
fallbackProvider.Log(LoggingEventType.Warning, "This is a warning.")
End If
Basic configuration
The following example shows an app.config of a typical application that uses CuttingEdge.Logging. The configuration in this example allows logging to the Windows event log by configuring a
WindowsEventLogLoggingProvider.
<?xml version="1.0"?>
<configuration>
<configSections>
<!-- The following section should be added to the configSections. -->
<section name="logging"
type="CuttingEdge.Logging.LoggingSection, CuttingEdge.Logging" />
</configSections>
<!-- the logging section allows you to configure logging providers -->
<logging defaultProvider="WindowsEventLogLoggingProvider">
<providers>
<!-- The WindowsEventLogLoggingProvider writes to the event log -->
<add
name="WindowsEventLogLoggingProvider"
type="CuttingEdge.Logging.WindowsEventLogLoggingProvider, CuttingEdge.Logging"
source="MyWebApplication"
logName="MyWebApplication"
/>
</providers>
</logging>
</configuration>
You can find more configuration examples on the
configuration examples page.
More advanced configuration
The example below shows how to configure the Logging Provider model in a web environment to log to a SQL Server database and use the Windows event log as
fallback logging store. The
AspNetSqlLoggingProvider is configured with the
threshold set to
Information, which means that
Debug events will not be logged. The
WindowsEventLogLoggingProvider has its threshold set to
Warning, which means that
Debug and
Information events will not be logged. By configuring the
AspNetExceptionLoggingModule http module, the web application ensures that unhandled exceptions will get logged automatically. The configured
LoggingWebEventProvider will route web events, raised by the ASP.NET health monitoring system, to the Logging infrastructure.
The
AspNetSqlLoggingProvider is configured with
initializeSchema="True". This means it will try to create the necessary tables and stored procedures needed for it to operate. This is the alternative for manually running the SQL scripts that are supplied with the release. For initialization to succeed, the supplied connection must have the proper rights on the database. The switch must be removed after initialization; the provider will throw an exception when the database schema already exists.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="logging"
type="CuttingEdge.Logging.LoggingSection, CuttingEdge.Logging" />
</configSections>
<connectionStrings>
<add name="SqlLogging"
connectionString="Data Source=.;Integrated Security=SSPI;Initial Catalog=Logging;" />
</connectionStrings>
<logging defaultProvider="AspNetSqlLoggingProvider">
<providers>
<add
name="AspNetSqlLoggingProvider"
type="CuttingEdge.Logging.Web.AspNetSqlLoggingProvider, CuttingEdge.Logging"
fallbackProvider="WindowsEventLogLoggingProvider"
description="ASP.NET SQL logging provider example"
connectionStringName="SqlLogging"
threshold="Information"
initializeSchema="True"
applicationName="[MyWebApplication]"
userNameRetrievalType="Membership"
logQueryString="True"
logFormData="False"
/>
<add
name="WindowsEventLogLoggingProvider"
type="CuttingEdge.Logging.WindowsEventLogLoggingProvider, CuttingEdge.Logging"
threshold="Warning"
source="MyWebApplication"
logName="MyWebApplication"
/>
</providers>
</logging>
<system.web>
<httpModules>
<!--
We're defining the AspNetExceptionLoggingModule here.
This http module will always log to the default logger.
-->
<add
name="UnhandledExceptionLogger"
type="CuttingEdge.Logging.Web.AspNetExceptionLoggingModule, CuttingEdge.Logging"
/>
</httpModules>
<healthMonitoring heartbeatInterval="0" enabled="true">
<providers>
<!-- We're configuring the web event provider here. -->
<add
name="LoggingWebEventProvider"
type="CuttingEdge.Logging.Web.LoggingWebEventProvider, CuttingEdge.Logging"
loggingProvider="AspNetSqlLoggingProvider"
/>
</providers>
<rules>
<add
name="Custom Event Provider"
eventName="All Events"
provider="LoggingWebEventProvider"
profile="Default"
/>
</rules>
</healthMonitoring>
</system.web>
</configuration>
You can find more configuration examples on the
configuration examples page.
Extending CuttingEdge.Logging
The following example shows how to extend CuttingEdge.Logging by defining a logger that logs to the file system.
Note however that this is an illustrative example. The library contains an XmlFileLoggingProvider for writing log information in an XML format to the file system, and it contains an FileLoggingProviderBase that can act as base class for providers that write to the file system.
using System;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.IO;
using CuttingEdge.Logging;
namespace MyLoggingProviders
{
public class MyFileLoggingProvider : LoggingProviderBase
{
private string path;
public override void Initialize(string name,
NameValueCollection config)
{
if (config == null)
{
throw new ArgumentNullException("config");
}
// Call base initialize first.
base.Initialize(name, config);
// Performing provider specific initialization.
this.InitializePath(name, config);
// Always call this method last.
this.CheckForUnrecognizedAttributes(name, config);
}
protected override object LogInternal(LogEntry entry)
{
DateTime now = DateTime.Now;
string line = String.Format("{0} {1}\t{2}\t{3}\t{4}\n",
now.ToShortDateString(), now.ToShortTimeString(),
entry.Severity, entry.Message, entry.Exception);
File.AppendAllText(this.path, line);
return null;
}
private void InitializePath(string name,
NameValueCollection config)
{
this.path = config["path"];
if (String.IsNullOrEmpty(this.path))
{
throw new ProviderException(string.Format(
"Empty or missing 'path' attribute in " +
"provider '{0}' in config file.", name));
}
config.Remove("path");
}
}
}
The following example shows the configuration for the logging provider that we've defined above:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="logging"
type="CuttingEdge.Logging.LoggingSection, CuttingEdge.Logging" />
</configSections>
<logging defaultProvider="MyFileLoggingProvider">
<providers>
<add
name="MyFileLoggingProvider"
type="MyLoggingProviders.MyFileLoggingProvider, MyLoggingProviders"
path="c:\mylog.txt"
/>
</providers>
</logging>
</configuration>
Please note that this example expects the MyFileLoggingProvider to be placed in an assembly called
MyLoggingProviders. Change this assembly name to the name of the assembly / project where you place the MyFileLoggingProvider. Also note that this example is a bit naive and will not work properly in a multi-threaded environment, such as ASP.NET. Again, please note that this example is illustrative. Please use the XmlFileLoggingProvider or it’s base class FileLoggingProviderBase to create a logger that writes to the file system.
More information
For more information about CuttingEdge.Logging, please visit the following links:
For more information about the ASP.NET provider model, please visit the following links:
This project is supported by:
