Poesía Binaria

Guardar un log con las excepciones producidas en C++

Sobre todo a la hora de crear un programa se pueden generar muchas excepciones, bueno y cuando estamos usándolo de forma normal también, y todos sabemos del típico cliente/amigo/usuario que nos llama de madrugada o a una hora normal diciendo:
– «El programa me da error» –
– «¿Qué error te da el programa?» – respondemos
– «Nada error, solo eso» –
– «Bueno, ¿seguro que no salía nada más?» – insistimos
– «Sí, muchas letras y cosas que no tenían sentido» – nos responde para bajarnos la moral – «¿qué puede ser?»
Nuestra respuesta ahora depende de la relación que tengamos con esa persona, ya sea cliente, amigo, usuario, desconocido… o destornillador, digo, desarrollador (que hay algunos que también…).

Bueno, el código de hoy es una primera fase de cómo podemos construirnos un informe de todas las excepciones producidas por nuestros programas, es muy mejorable, podemos extenderlo hasta el infinito y más allá, pero aquí está un código de ejemplo (está dividido en 5 archivos y al final del post se pueden descargar):

myException.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/* @(#)myException.h
 */


#ifndef _CBIEXCEPTION_H
#define _CBIEXCEPTION_H 1

#include <string>
#include <exception>

using namespace std;

class MyException : public exception
{
 private:
  string error;

 public:  
  MyException(string error);
  ~MyException() throw();
  string str();
};


#endif /* _CBIEXCEPTION_H */

myException.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "myException.h"
#include "myExceptionLogger.h"
#include <iostream>

MyException::MyException(string error)
{
  MyExceptionLogger logger;

  logger.log("Error: "+error);
  this->error=error;
}

MyException::~MyException() throw()
{
}

string MyException::str()
{
  return "Error: "+error;
}

myExceptionLogger.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* @(#)myExceptionLogger.h
 */


#ifndef _CBIEXCEPTIONLOGGER_H
#define _CBIEXCEPTIONLOGGER_H 1
#include <string>

using namespace std;

class MyExceptionLogger
{
 public:
  MyExceptionLogger();
  ~MyExceptionLogger();
  void setLogFile(string logFile);
  void disableLog();
  bool enableLog();
  void log(string data);
  void setDateFormat(string dateFormat);
 private:
  string getLogTime();

  static string logFile;
  static bool logEnabled;
  static string dateFormat;  
};


#endif /* _CBIEXCEPTIONLOGGER_H */

myExceptionLogger.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/**
*************************************************************
* @file myExceptionLogger.cpp
* @brief Logs exceptions into a File
*
* @author Gaspar Fernández <blakeyed@totaki.com>
* @version
* @date 28 may 2012
* Historial de cambios:
*
*
*
*
*************************************************************/


#include <fstream>
#include <ctime>
#include <iostream>

#include "myExceptionLogger.h"

using namespace std;

// Default values for static constants
bool MyExceptionLogger::logEnabled=false;
string MyExceptionLogger::dateFormat="%Y/%m/%d %H:%M:%S";
string MyExceptionLogger::logFile;

MyExceptionLogger::MyExceptionLogger()
{
  // Si queremos podemos hacer que este constructor escriba en el log y nos ahorramos
  // tener que llamar todo el rato al método log()
}


MyExceptionLogger::~MyExceptionLogger()
{
}


void MyExceptionLogger::setLogFile(string logFile)
{
  this->logFile=logFile;
  this->logEnabled=true;  
}


void MyExceptionLogger::disableLog()
{
  this->logEnabled=false;
}


bool MyExceptionLogger::enableLog()
{
  if (this->logFile.empty())
    return false;

  this->logEnabled=true;
  return true;
}

string MyExceptionLogger::getLogTime()
{
  time_t t;
  struct tm *tm;
  char datetime[50];
  string res;

  t=time(NULL);
  tm=localtime(&t);
  strftime(datetime, 50, dateFormat.c_str(), tm);
  res=datetime;

  return res;
}

void MyExceptionLogger::log(string data)
{
  ofstream out;
  if ( (!logEnabled) || (logFile.empty()) )
    return;
 
  out.open(logFile.c_str(), ios::app);
  if (out.fail())
    return;
 
  out << getLogTime() <<": "<<data << endl;

  out.close();
}

void MyExceptionLogger::setDateFormat(string dateFormat)
{
  this->dateFormat=dateFormat;
}

Y aquí un ejemplo de uso

myExceptionExample.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
#include "myExceptionLogger.h"
#include "myException.h"

using namespace std;

int main(int argc, char *argv[])
{
  MyExceptionLogger *logger =new MyExceptionLogger();
  logger->setLogFile("log.txt");
  delete logger;

  try
    {
      throw MyException("Ha ocurrido un error grave y tengo que guardar un registro");
    } catch (MyException e)
    {
      cout << "Excepcion capturada: "<<e.str()<<endl;
    }

  cout << "Fin del programa"<<endl;

  logger =new MyExceptionLogger();
  logger->setLogFile("log.txt");
  logger->log("También puedo escribir cualquier cosa que quiera en el log");
  delete logger;

  return 0;
}

Actualizado 21/06:2012 14:20 Gracias m4r14h por avisarme del link que no tenía link.

Es todo el código muy intuitivo y sencillo, listo para probarlo. Y podéis descargar todo de exceptionlogstar1 (1.6Kb)
Foto: lotus8 (Flickr) Creative Commons el 10/6/2012

También podría interesarte....