Tener una forma de logear eventos es algo critico en una aplicacion. Desde hace un par de años he implementado la practica y es algo muy bueno en especial para detectar post-morten que paso con un error o problema.
Hay varias opciones en Delphi:
http://stackoverflow.com/questions/8...age-for-delphi
http://stackoverflow.com/questions/7...rary-is-better
Esta opcion open source de Synapse parece buena
http://blog.synopse.info/post/2011/0...-in-SynCommons
La idea es que insertas miles y miles de llamadas al log (si: Cuando logeas, mas es mejor!. Solo hay que tener cuidado a la hora de invocar funciones con efectos colaterales que pudieran corromper las cosas ie: No invocar una insercion en BD, modificacion archivos, etc)
Código Delphi
[-]
procedure TMyDB.SQLExecute(const SQL: RawUTF8);
var ILog: ISynLog;
begin
ILog := TSynLogDB.Enter(self,'SQLExecute');
ILog.Log(sllInfo,'SQL=%',[sql]);
end;
Resultado:
Código PHP:
20110325 19325801 + MyDBUnit.TMyDB(004E11F4).SQLExecute
20110325 19325801 info SQL=SELECT * FROM Table;
20110325 19325801 - MyDBUnit.TMyDB(004E11F4).SQLExecute
Ahora bien, el siguiente problema es como rayos examinar esos logs. Porque se vuelven grandes. Y como hacer para leer los logs sin ir a cada cliente y abrir los archivos locales. Para eso hay servicios como
http://loggly.com/ que permtien enviar por APIs el log a un servidor central y usarlo como un visor global de TODOS los logs.
Luego de experimentar mucho, he llegado a un estilo que me permite injectar multiples logeadores y notificadores (por ejemplo, tengo llamadas a un servicio que me guarda la info de desempeño, memoria, CPU del codigo para ver si la APP esta corriendo por debajo de lo usual, y otros sensores de datos).
Lo que he hecho es tener una libreria llamada "notify" que me encapsula todo. Esta en python, pero la idea es masomenos:
Notificador por
GROWL, que puede o no estar instalado
Código PHP:
growl = gntp.notifier.GrowlNotifier(
applicationName=settings.APP_NAME,
notifications = ["Teleport"],
defaultNotifications = ["Teleport"],
# hostname = "computer.example.com", # Defaults to localhost
# password = "abc123" # Defaults to a blank password
)
try:
growl.register()
except Exception, e:
growl = None
def sendGrowl(title, description=None, icon=None):
if growl:
growl.notify(
noteType="Teleport",
title=title,
description=description,
icon=icon,
)
else:
print "Growl not available: %s" % title
Logeo de eventos:
Código PHP:
def debug(text, *args, **kwargs):
log.debug(text, *args, **kwargs)
def info(text, *args, **kwargs):
log.info(text, *args, **kwargs)
def warning(text, *args, **kwargs):
log.warning(text, *args, **kwargs)
def error(exc, silent=False, *args, **kwargs):
log.exception(exc, *args, **kwargs)
sendGrowl(title='Error in teleport', description=exc.message)
if not silent:
raise
#raise
Y envio el log al servidor remoto:
Código PHP:
class LoggyHandler(logging.Handler):
def __init__(self):
logging.Handler.__init__(self)
def emit(self, record):
s = self.format(record)
try:
if not settings.DEBUG:
requests.post(settings.LOGGY, s)
except Exception:
pass # Ignorar errores al enviar log. La app debe seguir siempre, no fallar si el servicio de terceros tiene problemas
Y sensor (invoca un servicio web, asincronicamente. Si falla? Se pierde el dato pero la app sigue):
Código PHP:
def requestTimeNumber(num):
dash = sensor()
dash.pushNumber("requestTime", num)
Y luego lo extiendes a mandar correos y mas cosas.
Es mucho mas centralizado de lo que muestro, es para que quede mas claro la idea. Eso quiere decir que cuando llamo:
Código PHP:
notify.error(err,silent=False)
Pasa lo siguiente:
1- Se va el error a la consola DOS/terminal *nix (si la app corre en consola)
2- Se guarda en un archivo log, que se rota cada 7 dias
3- Se envia (si es posible) el error a loggy
4- Se notifica por email al usuario que el servidor a fallado (porque puede que el servidor este en un equipo lejano)
5- Se envia por growl el error (si esta instalado, por ejemplo, se corre la app en la maquina del usuario, no tienen equipo servidor aparte)