Alhamdulillah, selesai sudah pekerjaan untuk mencatat semua aktifitas dalam modul DotNetNuke. Pekerjaan selesai lebih cepat dari jadwal, Alhamdulillah bisa pulang kampung dengan tenang.
DotNetNuke telah memiliki mekanisme untuk mencatat semua aktifitas dan exception dengan menggunakan Log Provider. Dengan menggunakan Log Provider ini, kita dengan mudah dapat menambahkan log pada modul kita sendiri. Di DotNetNuke terdapat dua jenis log yaitu event-log dan site-log. Event-log ini lah yang akan kita gunakan untuk mencatat aktifitas modul.
Logging DotNetNuke menggunakan tiga tabel yaitu tabel EventLogConfig (untuk menyimpan konfigurasi log), tabel EventLogTypes (untuk menyimpan daftar jenis log) dan tabel EventLog (untuk menyimpan data log). Di sini kita hanya akan mengutak atik dua tabel saja yaitu EventLog dan EventLogTypes.
Pertama yang dilakukan adalah menambahkan beberapa baris data di tabel EventLogTypes karena ini yang akan membedakan tipe log. Untuk membedakan log tersebut adalah log yang ditulis oleh internal DotNetNuke dan modul kita, pada field LogTypeOwner kita isi dengan class modul kita. Sebagai contoh:
INSERT INTO [directpublish_nl].[dbo].[EventLogTypes]
VALUES(N'MY_CUSTOMER_CREATED', N'Customer Add', N'', N'MyModule.Logging', N'ItemCreated')
INSERT INTO [directpublish_nl].[dbo].[EventLogTypes]
VALUES(N'MY_CUSTOMER_UPDATED', N'Customer Edit', N'', N'MyModule.Logging', N'ItemUpdated')
INSERT INTO [directpublish_nl].[dbo].[EventLogTypes]
VALUES(N'MY_CUSTOMER_DELETED', N'Customer Delete', N'', N'MyModule.Logging', N'ItemDeleted')
Setelah jenis log sudah didaftarkan, selanjutnya bikin storedprocedure dan provider untuk mengakses log yang telah disaring berdasarkan LogTypeOwner. Kita hanya butuh storedprocedure dan provider untuk mengambil log saja karena kita hanya perlu menyaring data yang nantinya akan kita tampilkan saja. Storedprocedure dan provider untuk menulis log, kita masih bisa gunakan milik DotNetNuke. Storedprocedure dan provider kita modifikasi dari storedprocedure dan provider DotNetNuke.
Storedprocedure yang telah dimodifikasi sebagai berikut:
/****** Object: StoredProcedure [dbo].[My_GetEventLog] Script Date: 05/30/2007 14:49:35 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF (EXISTS(SELECT NAME, TYPE FROM sysobjects WHERE (NAME = 'My_GetEventLog') AND (TYPE = 'P')))
DROP PROCEDURE [dbo].[My_GetEventLog];
GO
CREATE PROCEDURE [dbo].[My_GetEventLog]
@PortalID int,
@LogTypeKey nvarchar(35),
@PageSize int,
@PageIndex int
AS
DECLARE @PageLowerBound int
DECLARE @PageUpperBound int
-- Set the page bounds
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize + 1
CREATE TABLE #PageIndex
(
IndexID int IDENTITY (1, 1) NOT NULL,
LogGUID varchar(36) COLLATE database_default
)
INSERT INTO #PageIndex (LogGUID)
SELECT EventLog.LogGUID
FROM EventLog
INNER JOIN EventLogConfig
ON EventLog.LogConfigID = EventLogConfig.ID
INNER JOIN EventLogTypes
ON EventLog.LogTypeKey = EventLogTypes.LogTypeKey
WHERE (LogPortalID = @PortalID or @PortalID IS NULL)
AND (EventLog.LogTypeKey = @LogTypeKey or @LogTypeKey IS NULL)
AND (EventLogTypes.LogTypeOwner = 'MyModule.Logging')
ORDER BY LogCreateDate DESC
SELECT EventLog.*
FROM EventLog
INNER JOIN EventLogConfig
ON EventLog.LogConfigID = EventLogConfig.ID
INNER JOIN #PageIndex PageIndex
ON EventLog.LogGUID = PageIndex.LogGUID
WHERE PageIndex.IndexID > @PageLowerBound
AND PageIndex.IndexID < @PageUpperBound
ORDER BY
PageIndex.IndexID
SELECT COUNT(*) as TotalRecords
FROM #PageIndex
GO
/****** Object: StoredProcedure [dbo].[My_GetEventLogType] Script Date: 05/30/2007 15:12:08 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF (EXISTS(SELECT NAME, TYPE FROM sysobjects WHERE (NAME = 'My_GetEventLogType') AND (TYPE = 'P')))
DROP PROCEDURE [dbo].[My_GetEventLogType];
GO
CREATE PROCEDURE [dbo].[My_GetEventLogType]
AS
SELECT *
FROM dbo.EventLogTypes
WHERE (EventLogTypes.LogTypeOwner = 'MyModule.Logging')
GO
Selanjutnya buat provider sendiri untuk mengakses storedprocedure di atas.
Pada DataProvider tambahkan beberapa abstraksi fungsi sebagai berikut:
'Logging
Public MustOverride Function GetLogTypeInfo() As IDataReader
Public MustOverride Function GetLog() As IDataReader
Public MustOverride Function GetLog(ByVal LogType As String) As IDataReader
Public MustOverride Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Public MustOverride Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Public MustOverride Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Public MustOverride Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Implementasi dari abstraksi fungsi di atas adalah sebagai berikut:
Public Overloads Overrides Function GetLog() As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, DBNull.Value), IDataReader)
End Function
Public Overloads Overrides Function GetLog(ByVal LogType As String) As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, LogType), IDataReader)
End Function
Public Overloads Overrides Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, DBNull.Value, PageSize, PageIndex), IDataReader)
End Function
Public Overloads Overrides Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", PortalID, DBNull.Value, PageSize, PageIndex), IDataReader)
End Function
Public Overloads Overrides Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", PortalID, LogType, PageSize, PageIndex), IDataReader)
End Function
Public Overloads Overrides Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer) As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLog", DBNull.Value, LogType, PageSize, PageIndex), IDataReader)
End Function
Public Overrides Function GetLogTypeInfo() As IDataReader
Return CType(SqlHelper.ExecuteReader(ConnectionString, DatabaseOwner & ObjectQualifier & "My_GetEventLogType"), IDataReader)
End Function
Selanjutnya bikin controller untuk menakses provider tersebut. Controller inilah yang akan berkomunikasi dengan module kita.
Imports System.Data
Imports System.Data.SqlClient
Imports System.threading
Imports System.Xml.Serialization
Imports DotNetNuke
Imports DotNetNuke.Services.Log
Imports DotNetNuke.Common.Utilities
Imports DotNetNuke.Entities.Users
Public Class LoggingController
Private Function FillLogInfo(ByVal dr As IDataReader) As DotNetNuke.Services.Log.EventLog.LogInfo
Dim obj As New DotNetNuke.Services.Log.EventLog.LogInfo()
Try
Dim LogGUID As String
LogGUID = Convert.ToString(dr("LogGUID"))
obj.LogCreateDate = Convert.ToDateTime(dr("LogCreateDate"))
obj.LogGUID = Convert.ToString(dr("LogGUID"))
If Not IsDBNull(dr("LogPortalID")) Then
obj.LogPortalID = Convert.ToInt32(dr("LogPortalID"))
End If
If Not IsDBNull(dr("LogPortalName")) Then
obj.LogPortalName = Convert.ToString(dr("LogPortalName"))
End If
If Not IsDBNull(dr("LogServerName")) Then
obj.LogServerName = Convert.ToString(dr("LogServerName"))
End If
If Not IsDBNull(dr("LogUserID")) Then
obj.LogUserID = Convert.ToInt32(dr("LogUserID"))
End If
obj.LogTypeKey = Convert.ToString(dr("LogTypeKey"))
obj.LogUserName = Convert.ToString(dr("LogUserName"))
obj.LogConfigID = Convert.ToString(dr("LogConfigID"))
obj.LogProperties.Deserialize(Convert.ToString(dr("LogProperties")))
Finally
End Try
Return obj
End Function
Public Overridable Function GetLog() As DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog()
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLog(ByVal LogType As String) As DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog(LogType)
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLog(ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog(PageSize, PageIndex)
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
dr.NextResult()
While dr.Read
TotalRecords = Convert.ToInt32(dr("TotalRecords"))
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLog(ByVal PortalID As Integer, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray
If PortalID = -1 Then
Return GetLog()
End If
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog(PortalID, PageSize, PageIndex)
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
dr.NextResult()
While dr.Read
TotalRecords = Convert.ToInt32(dr("TotalRecords"))
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLog(ByVal PortalID As Integer, ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray
If PortalID = -1 Then
Return GetLog(LogType)
End If
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog(PortalID, LogType, PageSize, PageIndex)
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
dr.NextResult()
While dr.Read
TotalRecords = Convert.ToInt32(dr("TotalRecords"))
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLog(ByVal LogType As String, ByVal PageSize As Integer, ByVal PageIndex As Integer, ByRef TotalRecords As Integer) As DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim objArr As DotNetNuke.Services.Log.EventLog.LogInfoArray = New DotNetNuke.Services.Log.EventLog.LogInfoArray
Dim dr As IDataReader = DataProvider.Instance.GetLog(LogType, PageSize, PageIndex)
Try
Dim objLogInfo As DotNetNuke.Services.Log.EventLog.LogInfo
While dr.Read
objLogInfo = FillLogInfo(dr)
objArr.Add(objLogInfo)
End While
dr.NextResult()
While dr.Read
TotalRecords = Convert.ToInt32(dr("TotalRecords"))
End While
Finally
If Not dr Is Nothing Then
dr.Close()
End If
End Try
Return objArr
End Function
Public Overridable Function GetLogTypeInfo() As ArrayList
Return CBO.FillCollection(DataProvider.Instance.GetLogTypeInfo(), GetType(DotNetNuke.Services.Log.EventLog.LogTypeInfo))
End Function
End Class
Nah, storedprocedure, provider dan controller sudah siap. Berikutnya kita siapkan UserControl untuk menampilkan custom-log kita. UserControl ini juga hasil modifikasi dari UserControl LogViewer-nya DotNetNuke. Pada UserControl tersebut, hanya beberapa baris saja yang perlu disesuaikan.
Pada file logviewer.ascx, sesuaikan Inherits class baris directive "<%@ Control ..." menjadi class lengkap dengan namespace yang digunakan:
<%@ Control CodeFile="ucLogViewer.ascx.vb" language="vb" AutoEventWireup="false" Explicit="true" Inherits="LogViewer" targetSchema="http://schemas.microsoft.com/intellisense/ie5"%>
Pada codebehind-nya, sesuaikan namespace dengan namespace module, pada method BindData() ganti deklarasi object objLogController dengan controller yang dibuat sebelumnya.
Dim objLogController As New MyModule.LoggingController
Pada method BindLogTypeDropDown(), sesuaikan juga deklarasi object objLogController dengan controller yang dibuat seperti pada method BindData().
Private Sub BindLogTypeDropDown()
Dim objLogController As New HollandTraining.LoggingController
'...
Satu lagi, jika paging tidak berjalan dengan baik, sesuaikan link paging pada method InitializePaging.
Original code:
1 Private Sub InitializePaging(ByVal ctlPagingControl As DotNetNuke.UI.WebControls.PagingControl, ByVal TotalRecords As Integer, ByVal PageSize As Integer)
2 ctlPagingControl.TotalRecords = TotalRecords
3 ctlPagingControl.PageSize = PageSize
4 ctlPagingControl.CurrentPage = PageIndex
5 Dim strQuerystring As String = ""
Ganti baris ke-5 sesuai dengan query link untuk control module kita, misalnya:
Dim strQuerystring As String = "&ctrl=logs"
Fasilitas logging untuk module kita telah siap digunakan, tahap akhir adalah penulisan log di tiap event module. Berikut adalah contoh code untuk menuliskan event tersebut. Buat method WriteLog sebagai berikut.
Private Sub WriteLog(ByVal LogKeyType As String, ByVal CustomerId As Integer, ByVal CustomerName As String)
'Add module log
Dim _logController As New DotNetNuke.Services.Log.EventLog.LogController
Dim _logInfo As New Log.EventLog.LogInfo()
_logInfo.LogCreateDate = DateTime.Now
_logInfo.LogPortalID = PortalId
_logInfo.LogUserID = UserController.GetCurrentUserInfo.UserID
_logInfo.LogUserName = UserController.GetCurrentUserInfo.Username
_logInfo.LogTypeKey = LogKeyType
_logInfo.AddProperty("Module Part", "Customers")
_logInfo.AddProperty("CustomerId", CustomerId.ToString())
_logInfo.AddProperty("Customer Name", CustomerName)
_logController.AddLog(_logInfo)
End Sub
Pada saat event "Add", "Update" dan "Delete" customer, -- sebagai contoh -- kita tuliskan log sebagai berikut:
Dim custId as Intenger = 0
Dim custName as String = ""
'custId = n, dimana n didapat dari data CustomerId
'custName = name, dinama name adalah nama customer untuk CustomerId
'Add customer
WriteLog("MY_CUSTOMER_CREATED", custId, custName)
'Update customer
WriteLog("MY_CUSTOMER_UPDATED", custId, custName)
'Delete customer
WriteLog("MY_CUSTOMER_DELETED", custId, custName)
Selesai sudah penambahan fasilitas log ke dalam module DotNetNuke. Terakhir yang harus dilakukan adalah pengujian.
Semoga tulisan ini bisa bermanfaat.