Audit Logging

posted May 11, 2012, 6:33 AM by Eric Patrick


Given the inclusion of Microsoft's ETL Logging pattern in QBO 3, we can leverage logging in a number of interesting ways, including:
  • Tracking performance (execution time) of methods and statements,
  • Tracking time spent on the phone by agents doing skip tracing,
  • Tracking who is executing "sensitive" methods or statements


The ETL Logging pattern has some very nice features, including:
  • It is very lightweight, having minimal impact on the performance of code calling logging methods
  • If a log is broken, errors are not raised in code
  • Logging can be turned on or off from a configuration file (web.config)
  • When logging an activity, one can data-drive which logging sinks should record the activity
  • Custom logging sinks are easy to write, enabling us to log to a text file, Amazon Simple DB, our own Message or LedgerItem tables

Audit Logging

Each method or statement can include an Audit property, with a string of categories to log to. Examples:

In Decision.config
<Statement Name="Cancel" Query="UPDATE Decision SET CanceledDate=GETDATE()..." Audit="SecurityLog"/>
<Statement Name="ProcessStep" Query="..." Audit="BillingLog, SecurityLog"/>

In PaymentMessage.config
<Statement Name="StartCall" Query="..." Audit="AgentLog, BillingLog"/>

In ContactMethod.cs
public void CallOutbound(string phoneNumber) {...}


In web.config, the logging section can be configured like this:

<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
<!-- These are the "sinks": classes we write to save logging data somewhere
<add name="FlatFile" type="..." listenerDataType="..." fileName="flatFile.log" formatter="Text Formatter" rollInterval="Day" />
<add name="LedgerItem" type="..." listenerDataType="..." rollInterval="Month" formatter="Ledger Formatter" />
<add name="Message" type="..." listenerDataType="..." formatter="Message Formatter" /> 
<add name="SkipTraceMessage" type="..." listenerDataType="..." formatter="SkipTrace Message" /> 
<!-- These allow a sink to data-drive the "body" of the log -->
<add type="..." template="{templated data goes here, including method and parameters}" name="Text Formatter" />
<add type="..." template="{templated data goes here, including method and parameters}" name="Message Formatter" />
<add type="..." template="{templated data goes here, including method and parameters}" name="SkipTrace Message" />
<!-- This allows turning all, or partial, logging on or off -->
<add type="..." enabled="true" name="Logging Enabled Filter" />
<-- This is where we map what audited logs are actually written to; if there is no listener defined, the log can be ignored -->
<add switchValue="All" name="BillingLog">
<add name="LedgerItem" />
<add switchValue="All" name="AgentLog">
<add name="Message" />