I’ve always enjoyed writing application frameworks…you know, the stuff that works behind the scenes to make an application actually…well, work. One thing every application needs is some sort of instrumentation framework built in (logging/tracing/exception management) to make it run more smoothly, and also to alert operators/infrastructure staff when something does go wrong. There are plenty of solutions already out in the wild that address the above, but something I’ve been working on for the past few months (in what limited free time I have) is what I’d like to call a RSLS (really simple logging service) that can easily be plugged into existing projects.
I’m getting close to my first milestone and wanted to get some feedback from anyone who would like to chime in on what I have thus far (ideas at least, not releasing any code yet). The framework will also include some other basic functionality such as adding configuration support for stand alone assemblies (meaning non-top level executables…stand alone dll’s in .Net don’t support their own .config files), and exception formatting and logging in addition to basic tracing and logging capabilities.
The premise is simple enough…what I’ve come up with is that you decorate your assemblies/classes/members with a custom attribute that instructs the framework to:
- Enable/disable logging for the decorated member (or the entire assembly if need be).
- Log at a specific tracing level (i.e. System.Diagnostics.TraceLevel, which is overridable via a config file).
- Log for a specific type (in case you need to override the type the member is specified in).
After placing the attribute, only a single method call is needed to log the currently executing statement (i.e. method name/parameters, time the method was hit, what level it’s being logged at, physical path/name to the code file, and line number of the member…standard logging information) to one of the usual logging constructs (text file/email/event viewer/etc); in the case of an exception that needs to be logged, same thing…just a single method call and everything is taken care of. All of the configuration settings are configurable at runtime (i.e. what levels to log at, operational settings such as text file name, email settings, etc), and what I feel is the coolest feature is that each individual assembly in the application (so long as it has its own .config file specified) can maintain its own logging settings; in the case where separate support groups/developer groups own different aspects of the application, this is invaluable…in essence each individual assembly can either inherit from the parent assembly’s logging settings, or have their own settings; the settings aren’t all lumped under the parent .exe’s configuration settings (or in the case of a web application, the root web.config file). Or if a specific assembly is considered more critical/starts misbehaving, it can be isolated from the rest of the application for more intensive logging via specific config settings. You get the idea. Moving onwards…
I’ve pretty much settled on the custom attribute’s interface, as follows:
namespace Zerotrilogy.ApplicationBlocks.Framework
{
using System;
using System.Diagnostics;
using System.Reflection;
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Constructor | AttributeTargets.Delegate |
AttributeTargets.Event | AttributeTargets.Field | AttributeTargets.Method | AttributeTargets.Property,
Inherited=true, AllowMultiple=false)]
public class LoggableAttribute : Attribute
{
private bool _isLoggable;
private TraceLevel _level;
private Type _type;
public LoggableAttribute(int level)
:this((TraceLevel)Convert.ToInt32(level))
{
}
public LoggableAttribute(TraceLevel level)
:this(true, level)
{
}
public LoggableAttribute(bool isLoggable, int level)
:this(isLoggable, (TraceLevel)Convert.ToInt32(level))
{
}
public LoggableAttribute(bool isLoggable, TraceLevel level)
:this(isLoggable, Assembly.GetEntryAssembly().EntryPoint.DeclaringType, level)
{
}
public LoggableAttribute(bool isLoggable, Type type, int level)
:this(isLoggable, type, (TraceLevel)Convert.ToInt32(level))
{
}
public LoggableAttribute(bool isLoggable, Type type, TraceLevel level)
{
_isLoggable = isLoggable;
_level = level;
_type = type;
if (_isLoggable)
{
LoggingConfig config = new LoggingConfig(Assembly.GetAssembly(type));
}
}
public bool IsLoggable
{
get { return _isLoggable; }
}
public TraceLevel TraceLevel
{
get { return _level; }
}
public Type Type
{
get { return _type; }
}
public override string ToString()
{
return IsLoggable.ToString();
}
}
}
The LoggingConfig class exposes several static methods to facilitate the logging mechanism (I’m still tweaking some of the internals to the application, more details to come), so once it’s instantiated by the LoggableAttribute, everything should be good to go.
So that’s the basic idea…if anyone has any ideas/suggestions (or would like to see what I have thusfar with the rest of the framework (still a work in progress)), please let me know. It’s been fun so far!
Sidenote: I’m starting a new post category called RSLS, though I’ll more than likely cross-post any future RSLS posts into my .Net category as well.
Share this post: 
|

|

|

|

|
