Open sandboxFocusImprove this doc
  • Article

Defining Your Own Logging Transactions

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:

  1. Choose a name for your transaction type, for instance MorningBatch.

  2. 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;
    
    }
    
  3. 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 );
    
    }
    
  4. 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.

  5. 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.

  6. Call the OpenActivity<T>(in T, in OpenActivityOptions) method at the beginning of your transaction.

  7. 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;
    	}
    }
    
  8. 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>
    
  • Navigation