Writing Flat File Trace Listener with a LogWriter

Topics: Exception Handling Application Block, Logging Application Block
Mar 24, 2014 at 10:38 PM
Hi good day!

My problem is with LogWriter when i want write repeatedly a exception, this no write or write one time and no more when success this create other file with a guid name with error or in blank.

The question is why happend this i want write the same file repeatedly time with the error, i work with a ASP.NET MVC app, this is my code:

Web Config:

<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging" requirePermission="true" />

<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General">
<listeners>
  <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
      listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
      fileName="C:\Logs\trace.log" formatter="Text Formatter" />
</listeners>
<formatters>
  <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
      template="Timestamp: {timestamp}{newline}{newline}Title: {title}{newline}{newline}MessageErrores: {message}{newline}{newline}Extended Properties: {dictionary({key} - {value}{newline})}"
      name="Text Formatter" />
</formatters>
<categorySources>
  <add switchValue="All" name="General">
    <listeners>
      <add name="Flat File 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="Flat File Trace Listener" />
    </listeners>
  </errors>
</specialSources>
</loggingConfiguration>


Code:


public class UserController : Controller
{
    IPersonaBLL personaBLL;
    LogWriter logWriter;

    public UserController(IPersonaBLL personaBLL)
    {
        this.personaBLL = personaBLL;

        logWriter = new LogWriterFactory().Create();
    }


   public ActionResult Delete(Guid UserId)
    {
        aspnet_Users eliminarPersona = null;

        if (UserId == null)
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);

        try
        {
            eliminarPersona = personaBLL.GetPersonById((Guid)UserId);

            if (eliminarPersona == null)
                return HttpNotFound();
            else
            {
                personaBLL.DeletePerson(eliminarPersona);

                MvcApplication.exceptionManager.Process(() =>
                {
                    personaBLL.CommitAll();
                },
                "Policy");

                ViewData["EstaEliminado"] = "El Usuario se Elimino Correctamente";
            }
        }
        #region Exception
        catch (Exception ex)
        {
            LogExcepcionesPersona(eliminarPersona, ex);

            TempData["EstaEliminado"] = ex.Message; //"No se elimino porque tiene muchas dependencias";
            return RedirectToAction("Index");
        }
        #endregion

        return RedirectToAction("Index");
    }

void LogExcepcionesPersona(aspnet_Users persona, Exception ex)
    {
        //Se creal Diccionario con los datos de la persona que se quieran guardar en el log
        Dictionary<string, object> personaLog = new Dictionary<string, object>();

        if (persona != null)
        {
            personaLog.Add("Persona Guid", persona.UserId);
            personaLog.Add("Nombre", persona.Nombre);
            personaLog.Add("Apellido", persona.Apellido);
            personaLog.Add("Cedula", persona.Cedula);
            personaLog.Add("FlagEmail", persona.FlagEmail);
            personaLog.Add("Validado", persona.Validado);
        }

        LogEntry log = new LogEntry();
        log.Categories.Add("General");
        log.Title = "Delete Person";

        if (ex.InnerException.InnerException.InnerException.Message != null)
        {
            log.Message = string.Format("Error Mensaje: {0} InnerException: {1}",
                                    ex.InnerException.InnerException.Message,
                                    ex.InnerException.InnerException.InnerException.Message);
        }
        else
        {
            log.Message = string.Format("Error Mensaje: {0} InnerException: {1}",
                                    ex.InnerException.Message,
                                    ex.InnerException.InnerException.Message);
        }

        log.ExtendedProperties = personaLog;

        //Escribe el log con toda la info de LogEntry
        logWriter.Write(log);
    }
Thanks for you Help, Regards!
Mar 25, 2014 at 5:32 AM
The issue is here:
    public UserController(IPersonaBLL personaBLL)
    {
        this.personaBLL = personaBLL;

        logWriter = new LogWriterFactory().Create();
    }
Each controller instance is creating an entirely new logWriter (and associated trace listeners). Since LogWriter locks the file you will see the GUID prepending behavior when the file cannot be created (due to another LogWriter already having it locked).

The solution is to use one LogWriter for the application (it is thread-safe so no issue with threading). Either pass it in to the controller, access it as a singleton or use the static Logger facade (most preferable to least preferable order IMO). The controller is already accepting the business logic so change to also inject the LogWriter (which will depend on the implementation you are using).

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Marked as answer by daemons88 on 3/26/2014 at 8:15 AM
Mar 25, 2014 at 5:06 PM
Hi good day

Thanks for your reply!

I trying this putting the logWriter in global.asax and declare this how public and static, but this approach write randomly the log not ever where get up the exception.

how make this singleton to manage?

Happy day
Mar 26, 2014 at 1:51 PM
Edited Mar 26, 2014 at 1:52 PM
If you make the LogWriter instance public and static then that should be a singleton; just initialize the LogWriter at Application_Start to set the value only once. Could you be adding null values to the Extended Properties IDictionary<>? This could cause the LogEntry's to not log (there is a known issue).

If you are still having issues I would recommend posting a small sample application that recreates the behavior you are seeing.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Mar 26, 2014 at 4:14 PM
Ok thanks for all