Thursday 18 March 2010

MS Enterprise Library – Database Trace Listener

 

The Microsoft Enterprise Library is a collection of reusable software components (application blocks) designed to assist software developers with common enterprise development cross-cutting concerns (such as logging, validation, data access, exception handling, and many others).

Data Access Application Block provides access to the most frequently used features of ADO.NET, exposing them through easily used classes.

Create logs in database with EntLib:

It sets up a logging to database framework. The steps needed for this job :

STEP 1: configure entries in web.config:

<configuration>

<configSections>

<!—For Logging Handler-->

<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

<!—For Database Handler-->
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />

……

…..

</configSections>

<!—Logging Handler Block-->

<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>

       <!—Data Base Litener-->
      <add databaseInstanceName="FCConnectionString" writeLogStoredProcName="fantasyCricket.WriteLog"
        addCategoryStoredProcName="fantasyCricket.AddCategory" formatter=""
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="Database Trace Listener" />

          </listeners>
    <formatters>
      <add template="Timestamp: {timestamp}&#xD;&#xA;Message: {message}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {appDomain}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;Extended Properties: {dictionary({key} - {value}&#xD;&#xA;)}"
        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
        name="Text Formatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Database Trace Listener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events"></allEvents>
      <notProcessed switchValue="All" name="Unprocessed Category">
      </notProcessed>
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Database Trace Listener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>

<connectionStrings>
    <add name="FCConnectionString" connectionString="server=localhost; Database=HowLuckyMe;User=sa; Password=hari999"
      providerName="System.Data.SqlClient" />
  </connectionStrings>

Alternatively we can add the same setting ny suing configuration toll in All program Files –> Microsoft Patterns & Practises –> Enterprise Library 4.1 – October 2008 –> Enterprise Library Configuration.

 

image 

 

 image

STEP 2: Add the following References to the web site.

Microsoft.Practices.EnterpriseLibrary.Common.xml
Microsoft.Practices.EnterpriseLibrary.Common.dll
Microsoft.Practices.EnterpriseLibrary.Data.xml
Microsoft.Practices.EnterpriseLibrary.Data.dll
Microsoft.Practices.EnterpriseLibrary.Logging.Database.xml
Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll
Microsoft.Practices.EnterpriseLibrary.Logging.xml
Microsoft.Practices.EnterpriseLibrary.Logging.dll
Microsoft.Practices.ObjectBuilder.dll

Which will be in folder :

Installation Directory\Microsoft Enterprise Library 4.1 - October 2008\Bin

STEP 2: Create the Data base tables.

Run the following DB script to create log related tables and stored procedures.

or you can find the same script file in EntLib(Go to : Installation Directory\Microsoft Enterprise Library 4.1 - October 2008\src –> Click on “Enterprise Library 4.1 - October 2008 - Source Code” windows installer package).

EntLib provides a script(CreateLoggingDb.cmd) for creating a database for logging.  It's located in the @\EntLib41Src\Blocks\Logging\Src\DatabaseTraceListener\Scripts folder. 
1. Run this script.
2. Add a Database Trace Listener to your configuration file.  This will automatically add the Data Access Application block if you haven't done so.
3. Create a connection string for your Logging database.
4. Set the DatabaseInstance property of your Database Trace Listener to the name of your connection string.
5. Add a category under the Category Source node and reference the Database Trace Listener.

 

CREATE TABLE [fantasyCricket].[Category](
    [CategoryID] [int] IDENTITY(1,1) NOT NULL,
    [CategoryName] [nvarchar](64) NOT NULL,
CONSTRAINT [PK_Categories] PRIMARY KEY CLUSTERED
(
    [CategoryID] ASC
) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [fantasyCricket].[CategoryLog](
    [CategoryLogID] [int] IDENTITY(1,1) NOT NULL,
    [CategoryID] [int] NOT NULL,
    [LogID] [int] NOT NULL,
CONSTRAINT [PK_CategoryLog] PRIMARY KEY CLUSTERED
(
    [CategoryLogID] ASC
) ON [PRIMARY]
) ON [PRIMARY]

CREATE TABLE [fantasyCricket].[Log](
    [LogID] [int] IDENTITY(1,1) NOT NULL,
    [EventID] [int] NULL,
    [Priority] [int] NOT NULL,
    [Severity] [nvarchar](32) NOT NULL,
    [Title] [nvarchar](256) NOT NULL,
    [Timestamp] [datetime] NOT NULL,
    [MachineName] [nvarchar](32) NOT NULL,
    [AppDomainName] [nvarchar](512) NOT NULL,
    [ProcessID] [nvarchar](256) NOT NULL,
    [ProcessName] [nvarchar](512) NOT NULL,
    [ThreadName] [nvarchar](512) NULL,
    [Win32ThreadId] [nvarchar](128) NULL,
    [Message] [nvarchar](1500) NULL,
    [FormattedMessage] [ntext] NULL,
CONSTRAINT [PK_Log] PRIMARY KEY CLUSTERED
(
    [LogID] ASC
) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

CREATE PROCEDURE fantasyCricket.InsertCategoryLog
    @CategoryID INT,
    @LogID INT
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @CatLogID INT
    SELECT @CatLogID FROM fantasyCricket.CategoryLog WHERE CategoryID=@CategoryID and LogID = @LogID
    IF @CatLogID IS NULL
    BEGIN
        INSERT INTO fantasyCricket.CategoryLog (CategoryID, LogID) VALUES(@CategoryID, @LogID)
        RETURN @@IDENTITY
    END
    ELSE RETURN @CatLogID
END

CREATE PROCEDURE [fantasyCricket].[AddCategory]
    -- Add the parameters for the function here
    @CategoryName nvarchar(64),
    @LogID int
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE @CatID INT
    SELECT @CatID = CategoryID FROM fantasyCricket.Category WHERE CategoryName = @CategoryName
    IF @CatID IS NULL
    BEGIN
        INSERT INTO fantasyCricket.Category (CategoryName) VALUES(@CategoryName)
        SELECT @CatID = @@IDENTITY
    END

    EXEC fantasyCricket.InsertCategoryLog @CatID, @LogID

    RETURN @CatID
END

CREATE PROCEDURE fantasyCricket.ClearLogs
AS
BEGIN
    SET NOCOUNT ON;

    DELETE FROM fantasyCricket.CategoryLog
    DELETE FROM fantasyCricket.[Log]
    DELETE FROM fantasyCricket.Category
END

CREATE PROCEDURE [fantasyCricket].[WriteLog]
(
    @EventID int,
    @Priority int,
    @Severity nvarchar(32),
    @Title nvarchar(256),
    @Timestamp datetime,
    @MachineName nvarchar(32),
    @AppDomainName nvarchar(512),
    @ProcessID nvarchar(256),
    @ProcessName nvarchar(512),
    @ThreadName nvarchar(512),
    @Win32ThreadId nvarchar(128),
    @Message nvarchar(1500),
    @FormattedMessage ntext,
    @LogId int OUTPUT
)
AS

    INSERT INTO fantasyCricket.[Log] (
        EventID,
        Priority,
        Severity,
        Title,
        [Timestamp],
        MachineName,
        AppDomainName,
        ProcessID,
        ProcessName,
        ThreadName,
        Win32ThreadId,
        Message,
        FormattedMessage
    )
    VALUES (
        @EventID,
        @Priority,
        @Severity,
        @Title,
        @Timestamp,
        @MachineName,
        @AppDomainName,
        @ProcessID,
        @ProcessName,
        @ThreadName,
        @Win32ThreadId,
        @Message,
        @FormattedMessage)

    SET @LogID = @@IDENTITY
    RETURN @LogID

ALTER TABLE [fantasyCricket].[CategoryLog]  WITH CHECK ADD  CONSTRAINT [FK_CategoryLog_Category] FOREIGN KEY(    [CategoryID])
REFERENCES [fantasyCricket].[Category] (    [CategoryID])
ALTER TABLE [fantasyCricket].[CategoryLog]  WITH CHECK ADD  CONSTRAINT [FK_CategoryLog_Log] FOREIGN KEY(    [LogID])
REFERENCES [fantasyCricket].[Log] (    [LogID])

 

STEP 4: Code to write errors to this db log:

Add a default aspx page to the website and write the following code in .cs file.

 

public partial class _Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        try
        {
            int i = 1;
            int j = 0;
            i = i / j;
        }
        catch (System.DivideByZeroException ex)
        {
            LogEntry logEntry = new LogEntry();
            logEntry.Message = "Informational message

                                        generated using Logging Application Block.";
            logEntry.Categories.Add("General");
            logEntry.Title = "SomeTitle";
            Logger.Write(logEntry, "General");   

        }
    }
}

1 comment: