“How do you do logging in your application?” This is the question many people asks
me. Hence thought to put it into a post and redirect them to it…
SharePoint
2010 Guidance has one approach to log the exception into ULS logs…however
approach needs a farm scoped feature to register ULS Categories and Areas. Many
times, creating farm level feature is not possible due to the restrictions applied
by Farm Administrators.
There is another approach mentioned by my favorite MVP
Waldek Mastykarz in his blog post Logging to ULS inSharePoint 2010.
This approach does not need any feature for registering
the ULS Category and Areas.
Well, I use Waldek’s approach with little bit of tweaks so that I can to log
Exceptions, Information and Warnings. I also use Enums for defining Categories
which represents particular module so that I would come to know in which module
exceptions has occurred. I use Application name as Area and Module names as Categories....
public class
EnumUtil
{
public
static string StringValueOf(Enum
value)
{
FieldInfo
fi = value.GetType().GetField(value.ToString());
DescriptionAttribute[]
attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute),
false);
if
(attributes.Length > 0)
{
return attributes[0].Description;
}
else
{
return value.ToString();
}
}
public
static object EnumValueOf(string
value, Type enumType)
{
string[]
names = Enum.GetNames(enumType);
foreach
(string name in
names)
{
if (StringValueOf((Enum)Enum.Parse(enumType,
name)).Equals(value))
{
return Enum.Parse(enumType,
name);
}
}
throw
new ArgumentException("The string is not a description or value of the specified
enum.");
}
public
static IEnumerable<T> GetValues<T>()
{
return
Enum.GetValues(typeof(T)).Cast<T>();
}
}
public enum
LoggingCategory
{
[DescriptionAttribute("Application Pages")]
ApplicationPages,
[DescriptionAttribute("Event Receiver - Announcements list")]
AnnouncementEventReceivers,
[DescriptionAttribute("Feature Receiver - Master Page Applier")]
MasterPageApplierFeatureReceiver,
[DescriptionAttribute("WebPart - HomePage")]
HomePageWebPart,
[DescriptionAttribute("WebPart - Announcements")]
AnnouncementsWebPart,
[DescriptionAttribute("WebPart - Calendar")]
CalendarWebPart,
[DescriptionAttribute("Module - Product Order")]
ProductOrderModule
}
public class
LoggingService :
SPDiagnosticsServiceBase
{
static
readonly object padlock =
new object();
public
static string diagnosticAreaName =
"SharePoint Custom Development";
private
static LoggingService _Current;
public
static LoggingService Current
{
get
{
lock (padlock)
{
if (_Current ==
null)
{
_Current = new
LoggingService();
}
return _Current;
}
}
}
private LoggingService()
: base("SharePoint Custom Development Logging Service",
SPFarm.Local)
{
}
protected
override IEnumerable<SPDiagnosticsArea>
ProvideAreas()
{
List<SPDiagnosticsCategory> categories =
new List<SPDiagnosticsCategory>();
//Unexpected
Errors
foreach
(var category in
EnumUtil.GetValues<LoggingCategory>())
{
categories.Add(new SPDiagnosticsCategory(EnumUtil.StringValueOf(category) +
" Error", TraceSeverity.Unexpected,
EventSeverity.Error));
}
//Information
(verbose)
foreach
(var category in
EnumUtil.GetValues<LoggingCategory>())
{
categories.Add(new SPDiagnosticsCategory(EnumUtil.StringValueOf(category) +
" Information", TraceSeverity.Verbose,
EventSeverity.Verbose));
}
//Warnings
foreach
(var category in
EnumUtil.GetValues<LoggingCategory>())
{
categories.Add(new SPDiagnosticsCategory(EnumUtil.StringValueOf(category) +
" Warning", TraceSeverity.Medium,
EventSeverity.Warning));
}
List<SPDiagnosticsArea> areas =
new List<SPDiagnosticsArea>
{
new SPDiagnosticsArea(diagnosticAreaName,
categories)
};
return
areas;
}
///
<summary>
///
Log Errors and exceptions
///
</summary>
///
<param name="categoryEnumValue">LoggingEnum value representing the ULS category.</param>
///
<param name="exception">Exception
to be logged</param>
public
static void LogError(LoggingCategory
categoryEnumValue, Exception exception)
{
if
(exception is ApplicationException
&& exception.InnerException != null)
{
exception
= exception.InnerException;
}
string
errorLogString = string.Format("Message:
" + exception.Message + Environment.NewLine
+ "StackStrace: " + exception.StackTrace);
string
categoryName = EnumUtil.StringValueOf(categoryEnumValue);
SPDiagnosticsCategory
category = LoggingService.Current.Areas[diagnosticAreaName].Categories[categoryName
+ " Error"];
LoggingService.Current.WriteTrace(00,
category, TraceSeverity.Unexpected, errorLogString);
}
///
<summary>
///
Log Informative messages
///
</summary>
///
<param name="categoryEnumValue">LoggingEnum value representing the ULS category.</param>
///
<param name="infoMessage">Message
to be logged</param>
public
static void LogInfo(LoggingCategory
categoryEnumValue, string infoMessage)
{
string
categoryName = EnumUtil.StringValueOf(categoryEnumValue);
SPDiagnosticsCategory
category = LoggingService.Current.Areas[diagnosticAreaName].Categories[categoryName
+ " Information"];
LoggingService.Current.WriteTrace(00,
category, TraceSeverity.Verbose, infoMessage);
}
///
<summary>
///
Log warnings messages
///
</summary>
///
<param name="categoryEnumValue">LoggingEnum value representing the ULS category.</param>
///
<param name="warningMessage">Message to be logged</param>
public
static void LogWarning(LoggingCategory
categoryEnumValue, string warningMessage)
{
string
categoryName = EnumUtil.StringValueOf(categoryEnumValue);
SPDiagnosticsCategory
category = LoggingService.Current.Areas[diagnosticAreaName].Categories[categoryName
+ " Warning"];
LoggingService.Current.WriteTrace(00,
category, TraceSeverity.Medium, warningMessage);
}
}
|
SPDiagnosticsServiceBase class used is not supported by Sandbox solutions...but Full Trust proxies can be used in that case...you can find approach and implementation here http://sandbox.codeplex.com/
I hope you will find it helpful.
Wish everybody a happy friendships day…time to go home to end todays fasting…
Hi Parwej,
ReplyDeleteHow are you? Nice posts and in depth blogging.
Thanks for sharing .
Swati