StrataFrame Forum

Status/features of auditing?

http://forum.strataframe.net/Topic6131.aspx

By Greg McGuffey - 1/23/2007

What is the status of the auditing feature of the security module?



How will it work?


By Steve L. Taylor - 1/24/2007

What is the status of the auditing feature of the security module?

Currently the auditing feature is slated to be released 2nd-3rd quarter, range.  As the time comes closer we will release beta copies for your enjoyment or frustration, depending on your viewpoint. w00t

How will it work?

The auditing will have two major functions: application events and data events.  The application events will be used within your application to monitor user traffic.  For example, you may want to log an event every time the user logs into the system.  The data event trapping will be used to monitor how data is created, updated, and queried.  Obviously, this will create overhead but could be used to monitor a user if they are manipulating data. 

This feature is important to us since it is necessary for medical certification.

By Greg McGuffey - 1/24/2007

Thanks for the update.



I also have to have auditing. Here are the features that I'm currently using, most implemented via Instead Of triggers (big, ugly triggers).



- Audit history is tracked. For each record, there is a history which includes the user who made the change, the data and time and what type of change (add, edit, delete).

- Audited Field history is tracked. A history of each field that is changed is kept. So for a given audit history item (item 1 above), there is associated with that the set of fields that where changed (only the fields that were changed), including the old and new values.

- User can enter an audit comment about why a change was made. This can be turned on/off by business users as needed (that is to say it can be required or not, but it is always available).



These features are the minimum set required for my app. The one I'm most concerned about is the last item, as this is critical. I hope this information helps in your deciding what features to implement.
By Steve L. Taylor - 1/24/2007

These features are the minimum set required for my app.

It is an unreleased product and I don't want to debate its entire functionality, until beta.  At a glance I think you will generally be satisfied, although the user comment feature will not be included. 

By Greg McGuffey - 1/24/2007

I wasn't really trying to debate the features, just providing some feedback as to what features one of your customers will need, hoping that it might be provided early enough that a) you might decide to support some/all of these features or b) you at least keep in mind these features so the product can be customized to handle the feature needed but not implemented by the framework. I look forward to trying out the beta when it gets built. BigGrin
By Steve L. Taylor - 1/24/2007

I wasn't really trying to debate the features

Poor word choice on my part:  let's day discuss versus debate.  BigGrin

I agree input is healthy -- extremely so when your opinion agrees with mine. Smile

Nevertheless, we aim to please and will strive to produce something that has some WOW factor.

By Greg McGuffey - 1/24/2007

Thanks for the reply. I know it is hard to manage customer expectations (especially demanding ones Wink ). Of course, it is hard for us customers to manage the developers of our favorite framework to implement our pet features too! w00t
By Crones - 11/16/2007

Are there any new developments on the Auditing feature?  I'm needing to implement data change auditing and if it's going to be released with the next major version (shortly I hope with VS2008 releasing soon BigGrin),  I would much rather utilize this vs having to invent my own lopsided wheel. Hehe
By Guillermo Vilas - 2/5/2008

This is something I would like to know too, since is the must wanted feature that helped me decide to buy StrataFrame Tongue
By Trent L. Taylor - 2/5/2008

Actually the we have been implementing the auditing portion of RBS and implementing it into our medical software...so the creation of audit records has actually been completed and is being tested.  However, we still have to write the user control that will allow you to view and navigate through the records.  The next update will include the code, at least, that allows records to be created (including the CRUD options).  However, I am not sure that we will have full released the auditing portion in this next build and it will probably be full released and documented in the following update (which should be a smaller update and inlcude the finalized auditing).
By Greg McGuffey - 5/16/2008

I'm wondering what the current status of auditing is?
By Trent L. Taylor - 5/19/2008

Actually, it has already been plumbed into framework and could technically be used...we have just not mentioned it as there are still a few things that need to be done.  You have already seen the auditing files in the DDT, and probably some of the properties on the BO through the designer.  We have not created the auditing viewer yet and so we have not yet "released" it.  But we are using the auditing features already and working through the "issues" and will release all of it probably in the 1.6.7 version.

You can see another post about it here: http://forum.strataframe.net/FindPost16202.aspx

By Greg McGuffey - 5/19/2008

Cool. I must have missed that post. I check it out some more. BigGrin



Thanks!
By Alex Luyando - 12/1/2008

Good Morning!



I'm running the latest beta (1.6.7) and am seeing a discrepancy between the help for the Permission Editor and the actual dialog. Specifically, the Help shows a dialog that has Auditing options for Application and Data Events; the actual Permission dialog I am seeing does not.



Should I be seeing the two additional options?



Thanks.


By Trent L. Taylor - 12/2/2008

The auditing features have not been fully implemented (or released).  If you notice, you will actually find the Auditor class within the framework as well as the SFSAuditing tables that get imported when importing the security tables into a DDT project.  However, though the BOs technically support this, we have not fully released this as of yet as we intend to add some additional functionality in the form of a control that allows you to place a viewer for teh audit records on a dialog.  Once this has been completed, then the user-level actions will be enabled.
By Chan - 12/2/2008

Hi,

I would like to know, how would the auditing feature work in RBS? What would be audited? and etc...



Thank you
By Guillermo Vilas - 12/8/2008

Hi guys,

Can you post a sample that shows the best place to put the Audit logic, I was trying in the AfterSave and AfterDelete events in my Base BO but I can not trap the row changes when deleted. At this moment I'm able to capture the Added and Modifed changes in the row. but if the BO is deleted I can't log it.



Thanks for your help
By Ivan George Borges - 12/8/2008

Hi Guillermo.

Have a look at this post:

http://forum.strataframe.net/FindPost12173.aspx

By Guillermo Vilas - 12/8/2008

Hi Ivan,

The fields that I want to capture are:

- DocumentCode

- TransactionType

- ChangesDescription

- UpdateType

- TableSourceName

- UserCreated

- DateCreated

- UserModified

- DateModified



I´ve created a custom method the retreive Audit data, I´m not using SF Audit methods yet.

I´m currently using the Audit logic at the OnBeforeSave And OnBeforeDelete Events, I´m still having some problems.



1) In the OnBeforeSave Event the Object is not saved so if an error happens how can I stop the Auditing to be captured.

2) As the BO is not yet saved I can´t retrieve the PK generated for this Object.

3) If I put the Audit logic in the OnAfterSave then I do get the PK but can not log Modified BO´s because the state has changed.

4) I can´t Audit deleted BO´s



This are the methods I´m using on the Base BO







Private Sub AuditChanges(ByVal table As DataTable, ByVal transactionType As String, ByVal transactionDescription As String)

If (Not table.GetChanges Is Nothing) Then

Dim num4 As Integer = (table.Rows.Count - 1)

Dim i As Integer = 0

Do While (i <= num4)

Dim loTable As DataTable = table

If loTable.Rows.Item(i).RowState <> DataRowState.Unchanged Then

If (loTable.Rows.Item(i).RowState <> DataRowState.Deleted) Then

loTable.Rows.Item(i).BeginEdit()

If ((loTable.Rows.Item(i).RowState = DataRowState.Detached) OrElse (loTable.Rows.Item(i).RowState = DataRowState.Added)) Then

If (loTable.Columns.Contains("UserCreated")) Then

loTable.Rows.Item(i).Item("UserCreated") = MicroFour.StrataFrame.Security.SecurityBasics.CurrentUser.UserName

End If

If loTable.Columns.Contains("DateCreated") Then

loTable.Rows.Item(i).Item("DateCreated") = DateTime.Now

End If

End If

If loTable.Columns.Contains("UserModified") Then

loTable.Rows.Item(i).Item("UserModified") = MicroFour.StrataFrame.Security.SecurityBasics.CurrentUser.UserName

End If

If loTable.Columns.Contains("DateModified") Then

loTable.Rows.Item(i).Item("DateModified") = DateTime.Now

End If

loTable.Rows.Item(i).EndEdit()

End If

If (table.TableName <> "AuditTrail") Then

Me.CreateAuditTrail(loTable.Rows.Item(i), transactionType, transactionDescription)

End If

loTable = Nothing

End If

i += 1

Loop

End If

End Sub



Private Sub CreateAuditTrail(ByVal rowValue As DataRow, ByVal transactionType As String, ByVal transactionDescription As String)



If Me.EnableAuditTrail Then

Using bo As New AuditTrailBO

bo.NewRow()

Dim current As DataRowVersion = DataRowVersion.Current

Dim builder As New StringBuilder

If (rowValue.RowState = DataRowState.Deleted) Then

current = DataRowVersion.Original

End If

bo.CurrentRow.BeginEdit()

If rowValue.Table.Columns.Contains("Counter") Then

bo.CurrentRow.Item("DocumentID") = System.Runtime.CompilerServices.RuntimeHelpers.GetObjectValue(rowValue.Item("Counter", current))

End If

Dim num2 As Integer = (rowValue.Table.PrimaryKey.Length - 1)

Dim i As Integer = 0

Do While (i <= num2)

If (i = 0) Then

builder.Append(rowValue.Item(rowValue.Table.PrimaryKey(i).ColumnName, current).ToString)

Else

builder.Append(("," & rowValue.Item(rowValue.Table.PrimaryKey(i).ColumnName, current).ToString))

End If

i += 1

Loop

bo.CurrentRow.Item("AuditTrailGUID") = Guid.NewGuid

bo.CurrentRow.Item("DocumentCode") = builder.ToString

bo.CurrentRow.Item("TransactionType") = transactionType



If String.IsNullOrEmpty(transactionDescription) Then

bo.CurrentRow.Item("TransactionDescription") = GetCurrentDescription(rowValue, True)

Else

bo.CurrentRow.Item("TransactionDescription") = transactionDescription

End If

bo.CurrentRow.Item("UpdateAction") = rowValue.RowState.ToString

bo.CurrentRow.Item("TableSourceName") = rowValue.Table.TableName

bo.CurrentRow.Item("UserCreated") = MicroFour.StrataFrame.Security.SecurityBasics.CurrentUser.UserName

bo.CurrentRow.Item("DateCreated") = DateTime.Now

bo.CurrentRow.Item("UserModified") = MicroFour.StrataFrame.Security.SecurityBasics.CurrentUser.UserName

bo.CurrentRow.Item("DateModified") = DateTime.Now

bo.CurrentRow.EndEdit()

bo.Save()

End Using

End If

End Sub



Private Function GetCurrentDescription(ByVal row As DataRow, ByVal formatVertical As Boolean) As String

Dim builder As New StringBuilder

Dim column As DataColumn

For Each column In row.Table.Columns

If (row.RowState = DataRowState.Deleted) Then

If formatVertical Then

builder.AppendLine(String.Concat(New String() {"[-]", "", column.ColumnName, ": ", row.Item(column, DataRowVersion.Original).ToString}))

Else

builder.Append(String.Concat(New String() {"[-]", " ", column.ColumnName, ": ", row.Item(column, DataRowVersion.Original).ToString, ChrW(9)}))

End If

Continue For

End If

If (row.RowState = DataRowState.Added) Then

If formatVertical Then

builder.AppendLine(String.Concat(New String() {"[+]", " ", column.ColumnName, ": ", row.Item(column, DataRowVersion.Current).ToString}))

Else

builder.Append(String.Concat(New String() {"[+]", " ", column.ColumnName, ": ", row.Item(column, DataRowVersion.Current).ToString, ChrW(9)}))

End If

Continue For

End If

If ((row.RowState = DataRowState.Modified) Or (row.RowState = DataRowState.Unchanged)) Then

If Not row.Item(column, DataRowVersion.Original).ToString.Equals(row.Item(column, DataRowVersion.Current).ToString) Then

If formatVertical Then

builder.AppendLine(String.Concat(New String() {"[*]", " ", column.ColumnName, ": ", row.Item(column, DataRowVersion.Original).ToString, " -> ", row.Item(column, DataRowVersion.Current).ToString}))

Else

builder.Append(String.Concat(New String() {"[*]", " ", column.ColumnName, ": ", row.Item(column, DataRowVersion.Original).ToString, " -> ", row.Item(column, DataRowVersion.Current).ToString, ChrW(9)}))

End If

Continue For

End If

If formatVertical Then

builder.AppendLine((column.ColumnName & ": " & row.Item(column, DataRowVersion.Original).ToString))

Else

builder.Append((column.ColumnName & ": " & row.Item(column, DataRowVersion.Original).ToString & ChrW(9)))

End If

End If

Next

Return builder.ToString

End Function



Protected Overrides Sub OnBeforeSave(ByVal e As MicroFour.StrataFrame.Data.BeforeSaveUndoEventArgs)

MyBase.OnBeforeSave(e)



If Me.AuditDataChanges Then

If (Not e.Cancel) Then

Me.AuditChanges(Me.CurrentDataTable, Me.TableName, "")

End If

End If



End Sub



Protected Overrides Sub OnBeforeDelete(ByVal e As MicroFour.StrataFrame.Business.BeforeDeleteEventArgs)

MyBase.OnBeforeDelete(e)



If Me.AuditDataChanges Then

If (Not e.Cancel) Then

Me.AuditChanges(Me.CurrentDataTable, Me.TableName, "")

End If

End If



End Sub







I´ll keep searching the forum for SF Audit implementations
By Trent L. Taylor - 12/9/2008

Here is a suggestion.  First of all, any auditing logic that you are going to implement should be added to you BaseBO that all of your BOs inherit from.  The SF field level auditing hasn't been fully implemented or released due to the fact that implementing all field level auditing at the BO level isn't always going to be the best way to handle things.

The code that you have here is going to become noticably slower and slower the larger the table or rows that have to be auditing.  You will notice a performance hit if you are going to attempt to do this with every field.  I noticed that you had a set number of fields that you wanted to audit, and here is one suggestion.  If you are going to support a single database type, then creating triggers to handle the auditing may be a better way to go since this will all be done through UPDATEs, INSERTs, and DELETEs on the server side with no additional BO side programming logic...and it should be faster as well since all of the data is already server side.  You don't want to go crazy there either as you don't want to impact performance.  But you would probably have less impact there versus in the BO since the BO would require another trip to the server to save the audit records.

We will release field level auditing in the future, but fore now, this is the major argument why it has not been fully released.  It is relatively easy to add auditing yourself and you can optimize it more for your applicaiton.

By Guillermo Vilas - 12/9/2008

Thanks Trent,

I´ll follow your suggestion about using triggers