Blog
All Blog Posts | Next Post | Previous PostAudit Log using TMS Aurelius events
Friday, April 24, 2015
The latest release of TMS Aurelius introduces an event system that allows you to subscribe listeners to some events that might be fired while you are using Aurelius, especially the TObjectManager.One key difference between regular Delphi events and Aurelius events is that the latter are multicast events, meaning you can add listeners (handlers) to the events without worrying if you are replacing a listener that was already set to event. This way it's possible to create "plugins" to Aurelius that perform additional logic. For example you can easily add code that will be executed whenever an entity is inserted in the database:
TMappingExplorer.Default.Events.OnInserted.Subscribe( procedure(Args: TInsertedArgs) begin // Use Args.Entity to retrieve the inserted entity end );
One very common use of that feature is implementing Audit Trail, a mechanism where you can log every entity (or database record, if you prefer to see it that way) that is created (inserted), deleted or modified (updated). The Music Library demo included in TMS Aurelius distribution was updated to include a simple Audit Log Viewer that illustrates how to use the events.
In the demo, the Audit Log Viewer just listen to the events and log them in a memo component in a form. You can enable/disable the logging. In real applications, you will just log the modifications to another place, like a text log file, or even the database itself, using Aurelius, if you prefer.
You can check the demo for the full source code. In this blog post, I will show only the relevant parts, for the OnInserted and OnUpdated events. Other parts of the code even inside procedures were removed for simplicity. Here is how we subscribe to the events:
TfmAuditLogViewer = class(TForm) private FInsertedProc: TInsertedProc; FUpdatedProc: TUpdatedProc; procedure InsertedHandler(Args: TInsertedArgs); procedure UpdatedHandler(Args: TUpdatedArgs); procedure SubscribeListeners; procedure UnsubscribeListeners; {...} end; constructor TfmAuditLogViewer.Create(AOwner: TComponent); begin inherited; FInsertedProc := InsertedHandler; FUpdatedProc := UpdatedHandler; end; procedure TfmAuditLogViewer.SubscribeListeners; var E: TManagerEvents; begin E := TMappingExplorer.Default.Events; E.OnInserted.Subscribe(FInsertedProc); E.OnUpdated.Subscribe(FUpdatedProc); end;
Note that we set the method reference in field variables so that we can later unsubscribe them if we want to:
procedure TfmAuditLogViewer.UnsubscribeListeners; var E: TManagerEvents; begin E := TMappingExplorer.Default.Events; E.OnInserted.Unsubscribe(FInsertedProc); E.OnUpdated.Unsubscribe(FUpdatedProc); end;
And here is how we implemented our event listeners:
procedure TfmAuditLogViewer.InsertedHandler(Args: TInsertedArgs); begin Log(Format('Inserted: %s', [EntityDesc(Args.Entity, Args.Manager)])); BreakLine; end; procedure TfmAuditLogViewer.UpdatedHandler(Args: TUpdatedArgs); var Pair: TPair<string, Variant>; OldValue: Variant; begin Log(Format('Updated: %s', [EntityDesc(Args.Entity, Args.Manager)])); for Pair in Args.NewColumnValues do if not (Args.OldColumnValues.TryGetValue(Pair.Key, OldValue) and (OldValue = Pair.Value)) then Log(Format(' %s Changed from %s to %s', [Pair.Key, TUtils.VariantToString(OldValue), TUtils.VariantToString(Pair.Value)])); BreakLine; end;
Some different methods are called from those event handlers, but they are just helper methods. EntityDesc just retrieves a string representation of the entity being logged (class name and id), and Log and BreakLine just add text to the memo component:
function TfmAuditLogViewer.EntityDesc(Entity, Manager: TObject): string; var IdValue: Variant; IdString: string; begin IdValue := TObjectManager(Manager).Explorer.GetIdValue(Entity); IdString := TUtils.VariantToString(IdValue); Result := Format('%s(%s)', [Entity.ClassName, IdString]); end; procedure TfmAuditLogViewer.Log(const S: string); begin Memo.Lines.Add(S); end; procedure TfmAuditLogViewer.BreakLine; begin Memo.Lines.Add('================================================'); end;
After playing with Music Library demo for a while, adding and updating entities, we have our audit log results:
Wagner Landgraf
This blog post has received 2 comments.
2. Sunday, March 20, 2022 at 12:50:31 PM
It should work fine. In any case, use the Support Center to ask technical questions, it''s the best place: https://support.tmssoftware.com.
Wagner Landgraf
All Blog Posts | Next Post | Previous Post
Stapel Andreas