Does filters work on custom tracelistner?

Topics: Logging Application Block
Apr 21, 2010 at 5:59 AM

hi,

i have created a custom tracelistner. The problem i'm facing is filters are not working.

public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data) 

       {      

     try 

           {          

     if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))      

         {                

   if (data is ExtendedLogEntry)        

           {                  

     ExtendedLogEntry entry = data as ExtendedLogEntry;            

           if (entry != null)            

           {                      

     db = DatabaseFactory.CreateDatabase(databaseName);            

               DbCommand cmd = db.GetStoredProcCommand(writeLogSproc);
                            db.AddInParameter(cmd, "eventID", DbType.Int32, entry.EventId);    

                       db.AddInParameter(cmd, "priority", DbType.Int32, entry.Priority);        

                   db.AddParameter(cmd, "severity", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.Severity.ToString());            

               db.AddParameter(cmd, "title", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.Title);            

               db.AddInParameter(cmd, "timestamp", DbType.DateTime, entry.TimeStamp);                    

       db.AddParameter(cmd, "machineName", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.MachineName);      

                     db.AddParameter(cmd, "AppDomainName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.AppDomainName);                            db.AddParameter(cmd, "ProcessID", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.ProcessId);    

                       db.AddParameter(cmd, "ProcessName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.ProcessName);                            db.AddParameter(cmd, "ThreadName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.ManagedThreadName);                  

         db.AddParameter(cmd, "Win32ThreadId", DbType.String, 128, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.Win32ThreadId);    

                       db.AddParameter(cmd, "message", DbType.String, 1500, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Default, entry.Message);            

               db.AddInParameter(cmd, "formattedmessage", DbType.String, entry.ErrorMessages);                  

         //extended                          

 db.AddInParameter(cmd, "AppId", DbType.Guid, entry.AppId);                        

   
                            db.AddOutParameter(cmd, "LogId", DbType.Int32, 4);
                            db.ExecuteNonQuery(cmd);                    

   }            

       }            

   }            

}          

 catch (Exception ex)  

         {        

       EventLog.WriteEntry("Unable to log to the database", ex.Message);    

       }    

   }

 

Please let me know what i'm missing here.

 

regards,

sumeeth

Apr 21, 2010 at 7:21 AM

What do you mean by filters are not working?  Do you mean that the value does not correspond with what you set in the config?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 21, 2010 at 7:30 AM

sarah,

i have added logenabled filter. i have set it to true. As for my understanding, it should not log the message. but it still logs to the database.

 if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))    this lines actually checks it. Please correct me if am wrong.

Apr 21, 2010 at 8:55 AM

The LogEnabledFilter you added under the Filters section doesn't correspond to the Filter property in the custom trace listener.  The logic for checking if logging should proceed based on the LogEnabledFilter and all others under the Filters section is already placed in the LogWriter class.. You need not check for it in your custom trace listener.  Are you logging using the Logger.Write API? Or are you directly instantiating your custom trace listener?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 21, 2010 at 11:44 AM

i'm wrtitng the message to MSMQ. then using the distributor service i log to the database using my custom tracelistner. Distributor service has the configuration. if i add filter there it is not working.

Am i missing something?

Apr 22, 2010 at 12:48 AM
Edited Apr 22, 2010 at 1:32 AM

Did you restart the distributor service when you added the LogEnabledFilter? Changes to the config would be applied upon restarting the service.  If you did, would you mind posting the configuration of the distributor service?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 6:00 AM

sure.

<?xml version="1.0" encoding="utf-8"?><configuration>  <configSections>    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />    <section name="msmqDistributorSettings" type="Microsoft.Practices.EnterpriseLibrary.Logging.MsmqDistributor.Configuration.MsmqDistributorSettings, MsmqDistributor" />  </configSections>  <loggingConfiguration name="Logging Application Block" tracingEnabled="true"    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">    <listeners>      <add FilePath="E:\TestProject\trace.log" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        traceOutputOptions="None" filter="All" type="CustomHandlersAndTraceListners.CustomTraceListner.CustomFlatFileTraceListner, CustomHandlersAndTraceListners, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"        name="Custom Trace Listener" initializeData="" formatter="Text Formatter" />      <add fileName="trace.log" header="----------------------------------------"        footer="----------------------------------------" formatter=""        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        name="FlatFile TraceListener" />      <add source="Enterprise Library Logging" formatter="Text Formatter"        log="" machineName="." listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        traceOutputOptions="None" filter="All" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        name="Formatted EventLog TraceListener" />    </listeners>    <formatters>      <add template="Timestamp: {timestamp(local)}{newline}Message: {message}{newline}Category: {category}{newline}Priority: {priority}{newline}EventId: {eventid}{newline}Severity: {severity}{newline}Title:{title}{newline}Machine: {machine}{newline}App Domain: {appDomain}{newline}ProcessId: {processId}{newline}Process Name: {processName}{newline}Thread Name: {threadName}{newline}Win32 ThreadId:{win32ThreadId}{newline}Extended Properties: {dictionary({key} - {value}{newline})}"        type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        name="Text Formatter" />    </formatters>    <logFilters>      <add enabled="true" type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"        name="LogEnabled Filter" />    </logFilters>    <categorySources>      <add switchValue="All" name="General">        <listeners>          <add name="Custom Trace Listener" />        </listeners>      </add>    </categorySources>    <specialSources>      <allEvents switchValue="All" name="All Events" />      <notProcessed switchValue="All" name="Unprocessed Category" />      <errors switchValue="All" name="Logging Errors &amp; Warnings">        <listeners>          <add name="FlatFile TraceListener" />        </listeners>      </errors>    </specialSources>  </loggingConfiguration>  <connectionStrings>    <add name="Connection String" connectionString=[connectionstring]     providerName="System.Data.SqlClient" />    <add name="Logging" connectionString=[connectionstring]   providerName="System.Data.SqlClient" />  </connectionStrings>  <msmqDistributorSettings msmqPath=".\Private$\myQueue" queueTimerInterval="1000" serviceName="Enterprise Library Distributor Service" /> </configuration>

Apr 22, 2010 at 6:08 AM

Your LogEnabledFilter's enabled attribute is set to true.  It should be false if you don't want logging to occur.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 6:11 AM

even if i set false. it was not working.

Apr 22, 2010 at 6:13 AM

Did you restart the distributor service after changing it to false?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 6:35 AM

yes i did

Apr 22, 2010 at 6:40 AM

Hmm, I can't repro this.  What about the config of your app?  Are you sure you didn't configure your Custom Trace Listener under the General category?  Or probably there are other categories to which you are logging to which uses that trace listener?  The log coming into the database might be coming from your app and not from the distributor service.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 7:22 AM

i have sent you the configuration right. its the same configuration i have. I dont know what is going wrong?

Apr 22, 2010 at 7:29 AM

I meant the other configuration, the one used by your main application and having the msmq trace listener.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 8:00 AM

do we need to disable in that configuration? But i have written custom MSMQ handler, that will write to MSMQ. It does not use any tracelistner to write to msmq.  

Apr 22, 2010 at 8:22 AM

No, I thought you were logging to msmq using the MSMQ Tracelistener.  This is weird, it would look like a bug on your end but as I can't repro it on my machine, I think we're just missing something here.  Are you sure there are no other method calls in your application that could be possibly writing logs to the database?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 22, 2010 at 8:32 AM

this is the custom handler i have written for writing it to MSMQ.

 public Exception HandleException(Exception exception, Guid handlingInstanceId)  

     {
            // Open the queue.
            using (MessageQueue queue = new MessageQueue(@".\Private$\myQueue"))        

   {        

       try          

     {                

   // Enable the AppSpecific field in the messages.          

         //queue.MessageReadPropertyFilter.AppSpecific = true;
                    // Set the formatter to binary.                  

 queue.Formatter = new BinaryMessageFormatter();      

             // Create a simple text message.            

       Message msg = CreateMessage(exception);          

         // Send the message.          

         queue.Send(msg);        

       }
                catch (Exception ex)          

     {            

       EventLog.WriteEntry("Writing to Queue", ex.Message);      

         }    

       }        

   return exception;  

     }

 

Everything is working fine for me. only the filter property seems to be not working

Apr 22, 2010 at 9:24 AM
Edited Apr 22, 2010 at 9:26 AM

Ok, as I'm running out of ideas here, I'm gonna have to add some extra lines of code in your custom trace listener.  Just put this right before the code when your trace listener is about to log to the database.

ILogFilter filter = Logger.GetFilter("LogEnabled Filter");
bool shouldLog = filter.Filter(new LogEntry());
//Just write the value of the shouldLog variable anywhere (file, event log, etc), somewhere where you can see its value

If you see the value is true, then clearly, the version of the config that the distributor service is currently using is the one whose LogEnabledFilter enabled property is set to true.

Make sure to update first the version of your custom trace listener's assembly after applying the code change and before running the distributor service. 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com


Apr 22, 2010 at 10:50 AM

sarah,

Thanks for the help. It is working now. am getting the value. After changing the App.config, i need to rebuild the solution. After that it will work.  changing config file and restart of the service should work right.

Apr 23, 2010 at 8:06 AM

It should work without rebuilding the solution right? 

Apr 26, 2010 at 12:56 AM

Yes.  I don't know how rebuilding the solution fixed the problem. 

"It is working now. am getting the value."  - What value are you referring to?  Wasn't your problem was the fact that logging to database proceeds even if the LogEnabledFilter was set to false? 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com


Apr 26, 2010 at 10:37 AM
When i was changing the value in the app.config and restart the service, the value was actually not updating. so i rebuild it and restarted the service. Then it was taking the changed value.
Apr 26, 2010 at 10:45 AM

Oh, so you're referring to the value of the shouldLog variable?  Then the answer is yes, you need to rebuild the solution and update the custom trace listener assembly being used by the distributor service.  What I'm not clear now is if the distributor service now logs according to what is set in the LogEnabledFilter.

What is the value of the shouldLog variable when you set the LogEnabledFilter to false?  Does logging proceeds or not?

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 8:45 AM
No, i was referring to filter. you asked me to add following to check the value. ILogFilter filter = Logger.GetFilter("LogEnabled Filter"); bool shouldLog = filter.Filter(new LogEntry()); //Just write the value of the shouldLog variable anywhere (file, event log, etc), somewhere where you can see its value I'm not changing any value in my custom tracelistner. When i change the settings in the appconfig of distributor service, settings is not updated just by restarting the service. i need to rebuild the solution of distributor service, then the settings is updated. But i cant do this once it is deployed. Do i miss something? regards, sumeeth
Apr 28, 2010 at 8:51 AM

The additional code was meant for the custom trace listener, you don't need to modify anything in the solution of the distributor service.  The approach you've taken would really require you to rebuild that.  Anyway, since you've already done that, was the shouldLog variable correctly reflecting the value you set in the app.config?  If you set the LogEnabledFilter's Enabled property to false, did you also get a value of false for the shouldLog variable?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 9:05 AM
yes. i'm able to get it. Now whatever changes i make in app config of distibutor service will reflect only if i rebuild it. :( Any thoughts on this?
Apr 28, 2010 at 9:12 AM

Before answering your last question,

"yes. i'm able to get it." - Ok, but what is the value?   If you set the LogEnabledFilter's Enabled property to false, what is the value you're getting for the shouldLog variable? 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 9:16 AM
when i set it true. i'm able to see true in the eventviewer. And if i set it false and rebuild it. value is not logged to event viewer. That is, custom tracelistner is not called.
Apr 28, 2010 at 9:21 AM

Wasn't your initial problem was that even if you set the LogEnabledFilter property to false, your custom trace listener which logs to the database still performs logging?  Am I right?

If yes, then your testing just proves that this doesn't happen.  The distributor service works as expected.   You're able to see true in the eventviewer because logging proceeds (LogEnabledFilter =true).  If it's false, then your custom database trace listener won't get called, which means that logging to the database didn't happen. 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 9:25 AM
yes true. that is because i never rebuilt the distributor service solution. So the value was still true even if had changed to false. Now problem is why i have rebuild the distibutor solution, if i change anything in the app config?
Apr 28, 2010 at 9:30 AM

Are you using a modified version of the distributor service prior to the rebuilding you made as per my suggestion? 

Could you replace your distributor service with the original one?  The MsmqDistributor.exe that comes out of the box, the one from the entlib installation folder.  Just try it again if it really doesn't work as expected.  We're using the same version but I can't repro the behavior you're getting. 

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

Apr 28, 2010 at 9:36 AM
i have removed all the modification. now its the same which is provided by entlib. What might be the cause for this behavior?
Apr 28, 2010 at 9:38 AM

Ok, does it work as expected?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 28, 2010 at 10:41 AM
No. I have to rebuild the solution.
Apr 29, 2010 at 12:45 AM

Would you mind sending your copy of the MsmqDistributor.exe and MsmqDistributor.config? The one which doesn't work as expected.  Just want to see if I can repro it on my machine.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 29, 2010 at 6:17 AM
sarah, when i change the MsmqDistributor.config it works fine. What i was doing here was, i was changing the value in the app.config in the solution. I installed the service, giving the path of the Debug folder where our MSmqDistributor.exe resides. So to update the MsmqDistributor.Config, it think we need to build the solution. Am i right? i'm really happy using Enterprise Library, the reason is, the tremendous support you guys give. Thank you so much Sarah. i really appreciate. regards, sumeeth
Apr 29, 2010 at 6:45 AM
Edited Apr 29, 2010 at 7:02 AM

Ah, my fault.  You were telling me you were modifying app.config but I didn't realized that I didn't tell you it should be MsmqDistributor.config, sorry.  Another thing, if you're not modifying the source code of MSMQ distributor service, just use the exe and .config from the installation folder rather from the source code.   Adding the LogEnabledFilter and setting it's Enabled property to false in the MsmqDistributor.config should produce the correct behavior after restarting the service without needing to rebuild the source code.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 29, 2010 at 7:16 AM
:). we finally got the solution. thank you. keep up the good work