You can use the codeless configuration system even if your application is not based on ASP.NET. For instance, you can define transactions in a service processing requests from a queue, or files from an input directory.
This article explains how to do it.
To define custom transactions and use them in the policy XML file:
Choose a name for your transaction type, for instance MorningBatch.
Create the expression model class, for instance
MorningBatchExpressionModel
. That will become the type of the Request property that is visible to the XML policy file.public readonly struct MorningBatchExpressionModel { internal MorningBatchExpressionModel( string fileName ) { this.FileName = fileName; } public string FileName { get; } public DateTime LastWriteTime => File.GetLastWriteTime(this.FileName); public int Size => new FileInfo(this.FileName).Length; }
Derive a class from LogEventMetadata and use your expression model type as the generic parameter instance. Expose a singleton instance of this class.
internal sealed class MorningBatchMetadata : LogEventMetadata<MorningBatchExpressionModel> { public static readonly MorningBatchMetadata Instance = new MorningBatchMetadata(); private MorningBatchMetadata() : base( "MorningBatch" ) { } public override MorningBatchExpressionModel GetExpressionModel( object data ) => new MorningBatchExpressionModel( (string) data ); }
In your source code, find the place where the transaction starts and ends. Create an OpenActivityOptions instance and pass a LogEventData created from your singleton LogEventMetadata.
Call the ApplyTransactionRequirements(ref OpenActivityOptions) method. This will apply the logging policies to the OpenActivityOptions. You can skip this method call and force a transaction to be opened by directly setting the TransactionRequirement property.
Call the OpenActivity<T>(in T, in OpenActivityOptions) method at the beginning of your transaction.
Call SetSuccess(in CloseActivityOptions) or SetException(Exception, in CloseActivityOptions) at the end.
Your transaction code will now look like this:
var logSource = LogSource.Get(); foreach ( var fileName in Directory.GetFiles( ".", "*.batch") ) { var options = new OpenActivityOptions( LogEventData.Create( filename, MorningBatchMetadata.Instance ), LogActivityKind.Transaction ); logSource.ApplyTransactionRequirements( ref options ); var transaction = logSource.Default.OpenActivity( Formatted( "Processing {FileName}", fileName ), options ) try { // The original transaction processing code is here. transaction.SetSuccess(); } catch ( Exception e ) { transaction.SetException( e ); throw; } }
You can now create a configuration file that references your expression model. For instance, the following file will enable logging for batch files larger than a thousand bytes:
<logging> <verbosity level='warning'/> <transactions> <policy type='MorningBatch' if='t.Request.Size > 1000' name='Policy1'> <verbosity> <source level='debug'/> </verbosity> </policy> </transactions> </logging>