Crear archivo log

Cuando una aplicacion falla y hay que averiguar donde esta el error, resulta util tener tener un registro donde hayan quedado guardados, tanto las acciones realizadas como una descripcion de los posibles errores. El siguiente codigo puede ser una solucion rapida y sencilla si necesitamos crear un log, solo tenemos que llamar a la funcion con el mensaje a registrar y la propia funcion se encarga de guardar tambien la fecha, se preocupa de no entrar en conflicto con otros threads y cuando el tamaño del archivo se vuelve excesivo lo renombra y crea uno nuevo. Es decir, nosotros solo tenemos que añadir esta funcion a nuestro codigo y despreocuparnos de lo demas.

procedure log(Mensaje: String);
var
  F: TextFile;
  Filename: String;
  Mutex: THandle;
  SearchRec: TSearchRec;
begin
  // Insertamos la fecha y la hora
  Mensaje:= FormatDateTime('[ddd dd mmm, hh:nn] ', Now) + Mensaje;
  // El nombre del archivo es igual al del ejecutable, pero con la extension .log
  Filename:= ChangeFileExt(ParamStr(0),'.log');
  // Creamos un mutex, usando como identificador unico la ruta completa del ejecutable
  Mutex:= CreateMutex(nil,FALSE,
    PChar(StringReplace(ParamStr(0),'\','/',[rfReplaceAll])));
  if Mutex <> 0 then
  begin
    // Esperamos nuestro turno para escribir
    WaitForSingleObject(Mutex, INFINITE);
    try
      // Comprobamos el tamaño del archivo
      if FindFirst(Filename,faAnyFile,SearchRec) = 0 then
      begin
        // Si es mayor de un mega lo copiamos a (nombre).log.1
        if SearchRec.Size > (1024*1024) then
          MoveFileEx(PChar(Filename),PChar(Filename + '.1'),
            MOVEFILE_REPLACE_EXISTING);
        FindClose(SearchRec);
      end;
      try
        AssignFile(F, Filename);
        {$I-}
          Append(F);
        if IOResult <> 0 then
          Rewrite(F);
        {$I+}
        if IOResult = 0 then
        begin
          // Escribimos el mensaje
          Writeln(F,Mensaje);
          CloseFile(F);
        end;
      except
        // 
      end;
    finally
      ReleaseMutex(Mutex);
      CloseHandle(Mutex);
    end;
  end;
end;

Una ejemplo sencillo de como usar esta función:

log('La aplicacion se inicio correctamente');

Aunque donde puede resultar muy util es, por ejemplo, dentro de un servicio para guardar la descripcion de las excepciones:

procedure TService1.ServiceExecute(Sender: TService);
begin
  try    
    log('Servicio iniciado');
    // Aqui una tarea que puede provocar excepciones
    log('Servicio finalizado');  
  except
    // Si se produce una excepcion guardamos su descripcion
    on E: Exception do
      log('Exception: ' + E.Message);
  end;
end;

Comentarios

Estupendo código.... e ideal para controlar servicio...tk!

Está muy bien Domingo. :)

Excelente!!!

Gracias por compartirlo