Custom rolling flat file trace listener

Topics: Logging Application Block
Sep 13, 2012 at 11:19 AM

How can I create custom trace listener that keeps all rolling flat file trace listener functionality?

 

Sep 13, 2012 at 6:19 PM

There is no simple way to just extend the existing Listener.  However you can look at the Rolling XML Trace Listener Sample & (Rolling) Flat File Trace Listeners (Samples.TraceListeners.zip) from the Sample Projects page.  That project has custom rolling trace listeners (using full integration) based off of the Enterprise Library source code.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Sep 14, 2012 at 7:04 AM

Why can't I open and see the App.config file with the enterprise library tool?

When I am trying to open the App.config with Enterprise Library Configuration Application Block Console, it does not open.

I am getting an error on the line directing to the custom rolling file in app.config..... (line 13 if it helps..)

Sep 14, 2012 at 2:03 PM

The Trace Listeners support full design time integration with the Enterprise Library configuration tool.  Simply build and copy the assembly into the config tool working folder (e.g. C:\Program Files (x86)\Microsoft Enterprise Library 5.0\Bin) so it can load the trace listener type.  If you are using EnterpriseLibrary.config as the configuration tool (Right click on app.config "Edit configuration file") then you will need to build the solution before opening with the configuration tool.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Sep 15, 2012 at 10:58 PM

I added to that custom rolling flat file trace listener another field called "file header"

In order to do so, I added the field to the .resx file by copy the "message header", paste it and change the relevant to 'file' instead of 'message'.

 

  <data name="FlatFileTraceListenerDataHeaderDescription" xml:space="preserve">
    <value>The text of the header to add to the log message.</value>
  </data>
  <data name="FlatFileTraceListenerDataHeaderDisplayName" xml:space="preserve">
    <value>Message Header</value>
  </data>
  <data name="FlatFileTraceListenerDataFileHeaderDescription" xml:space="preserve">
    <value>The text of the header to add to the log file.</value>
  </data>
  <data name="FlatFileTraceListenerDataFileHeaderDisplayName" xml:space="preserve">
    <value>File Header</value>

and

  <data name="RollingFlatFileTraceListenerDataHeaderDescription" xml:space="preserve">
    <value>The text of the header to add to the log message.</value>
  </data>
  <data name="RollingFlatFileTraceListenerDataHeaderDisplayName" xml:space="preserve">
    <value>Message Header</value>
  </data>
  <data name="RollingFlatFileTraceListenerDataFileHeaderDescription" xml:space="preserve">
    <value>The text of the header to add to the log file.</value>
  </data>
  <data name="RollingFlatFileTraceListenerDataFileHeaderDisplayName" xml:space="preserve">
    <value>File Header</value>
  </data>

The problem is when I open app.config file using configuration tool, I keep getting two fields named "message header"

It seems like when I am trying to change the resx file, it doesn't update (maybe not doing flush or something....)

How can I fix this?

 

Sep 16, 2012 at 1:18 AM

If you want to add a new property (FileHeader in this case) you can do so using the following steps:

In RollingFlatFileTraceListenerData add the following code:

        const string fileHeaderPropertyName = "fileHeader";

        /// <summary>
        /// Gets and sets the file header.
        /// </summary>
        [ConfigurationProperty(fileHeaderPropertyName, IsRequired = false, DefaultValue = "FileHeader----------------------------------------")]
        [ResourceDescription(typeof(DesignResources), "RollingFlatFileTraceListenerDataFileHeaderDescription")]
        [ResourceDisplayName(typeof(DesignResources), "RollingFlatFileTraceListenerDataFileHeaderDisplayName")]
        public string FileHeader
        {
            get { return (string)base[fileHeaderPropertyName]; }
            set { base[fileHeaderPropertyName] = value; }
        }

This adds the property to the configuration class then update the resource file by adding the two new keys for the FileHeader (RollingFlatFileTraceListenerDataFileHeaderDescription and RollingFlatFileTraceListenerDataFileHeaderDisplayName).  

Then in DesignResources.resx add:

 

  <data name="RollingFlatFileTraceListenerDataFileHeaderDescription" xml:space="preserve">
    <value>The header information that is written to the top of the file.</value>
  </data>
  <data name="RollingFlatFileTraceListenerDataFileHeaderDisplayName" xml:space="preserve">
    <value>File Header</value>
  </data>

 

The config work is done.  The next step is to modify the RollingFlatFileTraceListener to store the new property.

Add:

        private readonly string fileHeader;

Then modify the constructor to accept the new property:

 public RollingFlatFileTraceListener(
            string fileName,
            string header,
            string footer,
            ILogFormatter formatter,
            int rollSizeKB,
            string timeStampPattern,
            RollFileExistsBehavior rollFileExistsBehavior,
            RollInterval rollInterval,
            int maxArchivedFiles,
            string fileHeader)
            : base(fileName, header, footer, formatter)
        {
            this.rollSizeInBytes = rollSizeKB * 1024;
            this.timeStampPattern = timeStampPattern;
            this.rollFileExistsBehavior = rollFileExistsBehavior;
            this.rollInterval = rollInterval;
            this.maxArchivedFiles = maxArchivedFiles;

            this.rollingHelper = new StreamWriterRollingHelper(this);

            this.fileHeader = fileHeader;
        }

The last change (besides implementing the actual fileHeader logic is to modify the configuration class, RollingFlatFileTraceListenerData, to pass in the fileHeader.  So modify the GetCreationExpression method to pass in the FileHeader to the new RollingFlatFileTraceListener constructor:

        protected override Expression<Func<TraceListener>> GetCreationExpression()
        {
            return
                () =>
                    new RollingFlatFileTraceListener(
                        this.FileName,
                        this.Header,
                        this.Footer,
                        Container.ResolvedIfNotNull<ILogFormatter>(this.Formatter),
                        this.RollSizeKB,
                        this.TimeStampPattern,
                        this.RollFileExistsBehavior,
                        this.RollInterval,
                        this.MaxArchivedFiles
                        this.FileHeader);
        }

Recompile (and if appropriate redeploy the assembly to the config tool directory) and then you should be able to edit the config file and pass in the config information to the trace listener.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com