miércoles, 18 de julio de 2007

Implementado un Custom Trace Listener

Finalmente tengo el código del trace listener terminado, no es gran cosa pero es un recurso para quien quiera hacer el propio ya que no hay mucha documentación en castellano sobre esto.
   1:  [ConfigurationElementType(typeof(CustomTraceListenerData))]
   2:  public class ErrorDataBaseTraceListener : CustomTraceListener
   3:  {
   4:      private const string connectionStringAttributeName = "ConnectionString";
   5:      private const string storedProcedureAttributeName = "StoredProcedureName";
   6:      private static string connectionString = "";
   7:      private static string storedProcedureName = "";
   8:   
   9:      /// Método que se encarga de escribir el error
  10:      public override void TraceData(System.Diagnostics.TraceEventCache eventCache, string source, System.Diagnostics.TraceEventType eventType, int id, object data)
  11:      {
  12:          connectionString = Attributes[connectionStringAttributeName];
  13:          storedProcedureName = Attributes[storedProcedureAttributeName];
  14:   
  15:          if (connectionString == null || connectionString.Length == 0)
  16:              throw new ApplicationException("No se ha especificado el " + connectionStringAttributeName);
  17:   
  18:          if (storedProcedureName == null || storedProcedureName.Length == 0)
  19:              throw new ApplicationException("No se ha especificado el " + storedProcedureAttributeName);
  20:   
  21:          if (data is LogEntry)
  22:          {
  23:              LogEntry logEntry = data as LogEntry;
  24:              if (logEntry.ExtendedProperties.ContainsKey("ErrorObject"))
  25:              {
  26:                  if (logEntry.ExtendedProperties["ErrorObject"] is ErrorObject)
  27:                  {
  28:                      ErrorObject errorObject = logEntry.ExtendedProperties["ErrorObject"] as ErrorObject;
  29:                      WriteErrorEntry(errorObject);
  30:                  }
  31:              }
  32:              else if (this.Formatter != null)
  33:              {
  34:                  this.WriteLine(Formatter.Format(logEntry));
  35:              }
  36:              else
  37:              {
  38:                  this.WriteLine(data.ToString());
  39:              }
  40:          }
  41:      }
  42:   
  43:      /// Escribe el error en la base de datos
  44:      private int WriteErrorEntry(ErrorObject errorObject)
  45:      {
  46:          int retVal = 0;
  47:   
  48:          Database db = DatabaseFactory.CreateDatabase(connectionString);
  49:          DbCommand sp = db.GetStoredProcCommand(storedProcedureName);
  50:   
  51:          db.AddInParameter(sp, "ArchivoAdjunto", DbType.AnsiString, errorObject.ArchivoAdjunto);
  52:          db.AddInParameter(sp, "Asunto", DbType.AnsiString, errorObject.Asunto);
  53:          db.AddInParameter(sp, "Categoria", DbType.AnsiString, errorObject.Categoria);
  54:          db.AddInParameter(sp, "Destino", DbType.AnsiString, errorObject.Destino);
  55:          db.AddInParameter(sp, "Enviado", DbType.Boolean, errorObject.Enviado);
  56:          db.AddInParameter(sp, "FechaEnvio", DbType.DateTime, errorObject.FechaEnvio);
  57:          db.AddInParameter(sp, "FechaGeneracion", DbType.DateTime, DateTime.Now);
  58:          db.AddInParameter(sp, "MailTo", DbType.AnsiString, errorObject.MailTo);
  59:          db.AddInParameter(sp, "Mensaje", DbType.AnsiString, errorObject.Mensaje);
  60:          db.AddInParameter(sp, "Origen", DbType.AnsiString, errorObject.Origen);
  61:          db.AddInParameter(sp, "Tipo", DbType.AnsiString, errorObject.Tipo);
  62:   
  63:          retVal = db.ExecuteNonQuery(sp);
  64:   
  65:          return retVal;
  66:   
  67:      }
  68:   
  69:      protected override string[] GetSupportedAttributes()
  70:      {
  71:          return new string[] { connectionStringAttributeName, storedProcedureAttributeName };
  72:      }
  73:   
  74:      public override void Write(string message)
  75:      {
  76:      }
  77:   
  78:      public override void WriteLine(string message)
  79:      {
  80:      }
  81:   
  82:  }
Para usarlo hay que agregarlo como un Custom Trace Listener, y pasarle dos atriguros ConnectionString y StoredProcedureName. Al hacer Logger.Write es necesario agregar al objeto LogEntry un ExtentdedProperty de nombre ErrorObject de tipo ErrorObject, con los datos para guardar en la base. Dejó un diagrama de ErrorObject, lo que falta es hacer el store procedure para que inserte en la tabla, hasta la próxima.