Log4j ou classe de log faite "maison" ?

Log4j ou classe de log faite "maison" ? - Java - Programmation

Marsh Posté le 10-03-2003 à 16:49:13    

Alors, voila ma situation actuelle :
J'utilise log4j depuis dans ma web-app, depuis sa création.
pour mon système de log, dans chacun de mes classes, je cré une instance statique de org.apache.log4j.Logger du nom de ma classe.
Les log ainsi générés sont plutôt orientés "développement", pour la débug quoi. c à dire que je loggue les exceptions, et d'autres infos utiles uniquement pour le débuggage.
Maintenant, dans ma web-app, je voudrais mettre un système de log orienté "exloitation", qui permettrait aux utilisateurs de me web-app de savoir qui s'est connecté, à quel moment, et qu'est ce qu'il à fait. Du coup, je pense que le système de log actuel ne conviendra pas, parce que, par exemple, à chaque message de log, je voudrais également préciser le login de l'utilisateur ayant engendré le message de log, et d'autre infos spécifiques à la session. Le système de classe statique ne convient donc plus (si !?).  
C'est pourquoi je pose la question : est ce vous pensez que j'ai intérêt à utiliser malgré tout log4j pour mes log d'exploitation, en changeant donc tout mon système de log actuel, ou est ce que, arrivé à ce point, je ferais mieux de me faire une petite classe de log toute bête, rien qu'a moi, pour logguer les quelques messages d'exploitation dont g besoin ? sachant également qu'il y a peu de messages à récolter pour l'expliotation (4 ou 5 types de messages possible, une vingtaine de message à logguer par session, à tout casser)

Reply

Marsh Posté le 10-03-2003 à 16:49:13   

Reply

Marsh Posté le 10-03-2003 à 18:37:27    

Pour associer une donnée à un thread et afficher cette donnée dans le message loggé par Log4J, tu peux utliser les MDC (Mapped Diagnotic Context) de Log4J, où à un Thread est associé un objet. Typiquement, dans ta servlet d'action, avant d'effectuer l'action, tu définis une valeur comme le login de l'utilisateur via le MDC. Tu peux alors afficher cette valeur dans le layout de ton message avec %x si je me rappelle bien. En fin de traitement, dans la servlet d'action, tu retires ce mapping avec la méthode MDC.remove();
 
Je sais pas si je suis très clair... :)
 
Mais je vois pas l'intêret de redévelopper une API de Log4J vu que Log4J existe et est très puissante... En paramétrant, tu dois pouvoir créer une log orientée exploit quitte à introduire un niveau de log type "exploitation"...

Reply

Marsh Posté le 10-03-2003 à 20:33:42    

le seul truc avec ça, c'est que les "logs d'exploitations" font partie de l'appli. Or si tu les configures au meme niveau que tu configures les logs "systeme" (=logs de dev.), y'a un truc qui est pas net.... [:gratgrat]


---------------
Hey toi, tu veux acheter des minifigurines Lego, non ?
Reply

Marsh Posté le 11-03-2003 à 08:55:43    

the real moins moins a écrit :

le seul truc avec ça, c'est que les "logs d'exploitations" font partie de l'appli. Or si tu les configures au meme niveau que tu configures les logs "systeme" (=logs de dev.), y'a un truc qui est pas net.... [:gratgrat]


 
Ouais, c ce que je me dis aussi. Dans l'idée, y a aucune raison que  le niveau d'un des 2 log interfère sur le niveau de l'autre log. Donc, j'vais pas créer un niveau de log "exploitation".
Alors, maintenant, j'hésite entre :
- créer une simple classe singleton capable d'écrire dans ma table de log (la méthode d'écriture n'a même pas besoin d'être synchronizée, j'utilise un pool de connections.
- utiliser le MDC dont m'a parlé MachinBidule, et log4j. Mais je suis pas sur que 2 systèmes de log bien séparés (possibilité de préciser 2 niveau de logging différents, car mon log d'exploitation doit aussi pouvoir êter filtré en fonction des priorités de messages). Le fait que tout les Logger (ou Category) héritent du "root", ça risque de poser pb, non !?

Reply

Marsh Posté le 11-03-2003 à 09:08:52    

El_gringo a écrit :


 
Ouais, c ce que je me dis aussi. Dans l'idée, y a aucune raison que  le niveau d'un des 2 log interfère sur le niveau de l'autre log. Donc, j'vais pas créer un niveau de log "exploitation".
Alors, maintenant, j'hésite entre :
- créer une simple classe singleton capable d'écrire dans ma table de log (la méthode d'écriture n'a même pas besoin d'être synchronizée, j'utilise un pool de connections.
- utiliser le MDC dont m'a parlé MachinBidule, et log4j. Mais je suis pas sur que 2 systèmes de log bien séparés (possibilité de préciser 2 niveau de logging différents, car mon log d'exploitation doit aussi pouvoir êter filtré en fonction des priorités de messages). Le fait que tout les Logger (ou Category) héritent du "root", ça risque de poser pb, non !?


 
je vois pas la tronche de tes logs mais clairement tu dois loguer avec deux loggers différents, je te l'ai déjà expliqué dans un autre post en plus :sarcastic:


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 11-03-2003 à 09:20:59    

DarkLord a écrit :


 
je vois pas la tronche de tes logs mais clairement tu dois loguer avec deux loggers différents, je te l'ai déjà expliqué dans un autre post en plus :sarcastic:


 
Non, c pas vrai d'abbord !  :sweat:  
Mais le pb, c que si je crée un 2e Logger, il va lui aussi hériter de mon root, et donc hériter de ses Appender. A moins que je mette la propriété système "log4j.disableOverride" à true ?
Et puis si j'utilise Log4j je vais aussi devoir utiliser le système du MDC (vous au dessus pour explications pour ceux comprennent pas !). Donc, on résume, si j'utilise Log4j, je vais devoir :  
- Créer un Appender (ou un Logger, je sais pas trop, je m'perd un peu moi) capable d'exploiter les données d'un MDC.
- Apprendre à utiliser un MDC et l'utiliser.
- Modifier mon code source.
- Gérer le problème d'héritage des appenders.
 
Un simple singleton me parait vachement plus simple. Quel inconvénient ça a ? Sachant, je le répète, que je n'aurait pas à synchroniser la méthode d'écroture, donc, pas de goulet d'étranglement dans ce log...

Reply

Marsh Posté le 11-03-2003 à 09:37:52    

Pour éviter que des events de logs ne remontent jusqu'au logger root, tu disposes de l'attribut "additivity" que tu mets à false pour stopper la remontée de l'event...

Reply

Marsh Posté le 11-03-2003 à 09:41:26    

Quitte à changer de système de logs, je suggère d'utiliser celui proposé en standard par le JDK 1.4 (si bien sûr tu utilises ce JDK-là).

Reply

Marsh Posté le 11-03-2003 à 09:44:01    

BifaceMcLeOD a écrit :

Quitte à changer de système de logs, je suggère d'utiliser celui proposé en standard par le JDK 1.4 (si bien sûr tu utilises ce JDK-là).


 
Je parle pas de changer de système de log. Je suis content de log4j pour mes logs de développement.  
Je parle de ne pas utiliser log4j pour des traces d'exploitation que je souhaite inscrire dans une table de log.

Reply

Marsh Posté le 11-03-2003 à 09:44:17    

BifaceMcLeOD a écrit :

Quitte à changer de système de logs, je suggère d'utiliser celui proposé en standard par le JDK 1.4 (si bien sûr tu utilises ce JDK-là).


 
je pensais qu'il était moins puissant que log4j ???

Reply

Marsh Posté le 11-03-2003 à 09:44:17   

Reply

Marsh Posté le 11-03-2003 à 09:46:58    

El_gringo a écrit :


 
Je parle pas de changer de système de log. Je suis content de log4j pour mes logs de développement.  
Je parle de ne pas utiliser log4j pour des traces d'exploitation que je souhaite inscrire dans une table de log.


 
faut faire comme darklord dit:
- utiliser 2 loggers différents pour les 2 types de log, quitte à encapsuler un logger dans un singleton comme tu dis (il doit quand même y avoir des inconvénients)
- utiliser le MDC (géré en standard, rien à coder) pour lier une chaîne de caractères à un thread d'exécution donné

Reply

Marsh Posté le 11-03-2003 à 10:20:05    

MachinBidule1974 a écrit :


 
faut faire comme darklord dit:
- utiliser 2 loggers différents pour les 2 types de log, quitte à encapsuler un logger dans un singleton comme tu dis (il doit quand même y avoir des inconvénients)
- utiliser le MDC (géré en standard, rien à coder) pour lier une chaîne de caractères à un thread d'exécution donné


 
Heu, avant de me lancer dans le truc, j'voudrais être sur de qqch :  
comment ça s'utilise un appender, dis moi le système que g imaginé te semble correcte stp :
Quand un client se connecte, je lui cré un "Logger" spécifique, et... sniff, j'comprend pas comment on utilise le MDC ! :sweat:

Reply

Marsh Posté le 11-03-2003 à 10:23:52    

je comprend pas à quel moment je peut attacher mon objet au thread courant, par la méthode put(String key, Object o) de MDC.

Reply

Marsh Posté le 11-03-2003 à 10:33:13    

Dans la servlet d'action de ta webapp, avant d'appeler la méthode execute de ta classe de type Action, tu fais un
 

Code :
  1. MDC.put("keyLogin", userLogin);


 
puis un truc du genre
 

Code :
  1. ...
  2. action.execute(request, response);
  3. ...


 
Pendant l'exécution de ta classe d'action, tu logges normalement en passant par un logger et dans le layout (PatternLayout) de ce logger, tu appelles la variable stockée sous la clé "keyLogin" par %x{keyLogin} (cf doc de PatternLayout). Le layout va alors déterminer le thread courant puis son contexte MDC et dans ce contexte la valeur associée à la clé "keyLogin" (cf MDC.put())
 
quand le thread repasse dans ta servle d'action, tu supprimes l'entrée du MDC en faisant (dans un bloc finally)
 

Code :
  1. MDC.remove("keyLogin" );


 
J'espère avoir été clair... Y'a que du paramétrage et deux lignes de codes à écrire !  

Reply

Marsh Posté le 11-03-2003 à 10:35:11    

El_gringo a écrit :

Mais le pb, c que si je crée un 2e Logger, il va lui aussi hériter de mon root, et donc hériter de ses Appender.  


 
je comprends mieux pq tu as des problèmes (additivity="falses" pour éviter cela). Et sinon ca n'a aucun sens d'avoir un système différent pour les logs de dev/prod. A la base tu valides un soft comme un tout. si tu commences à rajouter des brols uniquement pour la prod ca va pas le faire.
 
Et je JDBCAppender te permet de loguer en base. Tu peux imaginer un singleton qui prend en param la source et le message par exemple avec des méthode info, debug, error etc dans le singleton. Comme ca ton 2eme logger est abstrait par le singleton et tu peux utiliser l'argument source (par exemple class name) passé en param.  
 
Tout dépend de ce que tu dois loguer en fait.


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 11-03-2003 à 10:49:48    

MachinBidule1974 a écrit :

Dans la servlet d'action de ta webapp, avant d'appeler la méthode execute de ta classe de type Action, tu fais un
 

Code :
  1. MDC.put("keyLogin", userLogin);


 
puis un truc du genre
 

Code :
  1. ...
  2. action.execute(request, response);
  3. ...


 
Pendant l'exécution de ta classe d'action, tu logges normalement en passant par un logger et dans le layout (PatternLayout) de ce logger, tu appelles la variable stockée sous la clé "keyLogin" par %x{keyLogin} (cf doc de PatternLayout). Le layout va alors déterminer le thread courant puis son contexte MDC et dans ce contexte la valeur associée à la clé "keyLogin" (cf MDC.put())
 
quand le thread repasse dans ta servle d'action, tu supprimes l'entrée du MDC en faisant (dans un bloc finally)
 

Code :
  1. MDC.remove("keyLogin" );


 
J'espère avoir été clair... Y'a que du paramétrage et deux lignes de codes à écrire !  


 
Non, y a pas vraiment 2 lignes de code à écrire : dans ma web-app, j'utilise un pool de connexions, et la manière dont le JDBCAppender gère les connexion ne me va pas, 'va falloir que j'étende l'existant, et surcharge qqs méthodes (getConnection, execute, ...)
Autre problème (THE problème) : C'est dans mon appender que j'ai besoin de récupérer les données spécifiques à un client, le problème, c'est que, dans mon appender, je ne connais pas la clé "keyLogin" (qui, au passage, ne sera pas le login, mais l'id de session)

Reply

Marsh Posté le 11-03-2003 à 10:56:39    

DarkLord a écrit :


Et je JDBCAppender te permet de loguer en base. Tu peux imaginer un singleton qui prend en param la source et le message par exemple avec des méthode info, debug, error etc dans le singleton. Comme ca ton 2eme logger est abstrait par le singleton et tu peux utiliser l'argument source (par exemple class name) passé en param.  
 
Tout dépend de ce que tu dois loguer en fait.


 
Je comprend pas ce que tu tentes de m'expliquer là. G besion de logguer les données suivantes :
- Date / Heure, comme d'hab.
- Login du client ayant engendré le log, et autres données relatives à la session (c ça qui me pose pb surtout)
- Contenu du message de log

Reply

Marsh Posté le 11-03-2003 à 10:59:40    

ça serait crade si je faisais ça :
dans mon code, quand je veux logger qqch, je fais :

Code :
  1. MessDeLog log = new MessDeLog (login, application, document, message);
  2. monLoggerExploitation.info (log);


 
Et que, d'un autre côté, je surcharge la méthode doAppend de JDBCAppender, afin qu'il utilise mon Objet MessDeLog entant que tel...

Reply

Marsh Posté le 11-03-2003 à 11:02:12    

El_gringo a écrit :


 
Non, y a pas vraiment 2 lignes de code à écrire : dans ma web-app, j'utilise un pool de connexions, et la manière dont le JDBCAppender gère les connexion ne me va pas, 'va falloir que j'étende l'existant, et surcharge qqs méthodes (getConnection, execute, ...)
Autre problème (THE problème) : C'est dans mon appender que j'ai besoin de récupérer les données spécifiques à un client, le problème, c'est que, dans mon appender, je ne connais pas la clé "keyLogin" (qui, au passage, ne sera pas le login, mais l'id de session)


 
T'as sûrement plus que deux lignes de codes à modifier/écrire pour ton application mais pour mettre en place la gestion par MDC, t'as besoin de deux lignes (push() et remove())...
 
Les données spécifiques à un client, c'est toi qui les indique dans ta servlet d'action ! Par la méthode push(), tu dis "A tel thread donc à tel client, j'associe une variable spécifique que je nomme "userLogin" et qui prend la valeur xxx"... Cette valeur, ça peut être un username, une adresse IP, etc... Ensuite, par le "template" %x{userLogin} tu appelles cette variable... Tu peux définir tout en n'importe quoi comme variable... Tu n'as absolument rien à faire sur ton logger ou ton appender, c'est la classe layout qui gère l'appel à cette variable spécifique à ton thread par %x{leNomDeCetteVariableSpécifiqueAMonThread}

Reply

Marsh Posté le 11-03-2003 à 11:04:29    

est-ce-que j'ai été clair ce coup-ci ?  :??:

Reply

Marsh Posté le 11-03-2003 à 16:50:27    

MachinBidule1974 a écrit :


 
T'as sûrement plus que deux lignes de codes à modifier/écrire pour ton application mais pour mettre en place la gestion par MDC, t'as besoin de deux lignes (push() et remove())...
 
Les données spécifiques à un client, c'est toi qui les indique dans ta servlet d'action ! Par la méthode push(), tu dis "A tel thread donc à tel client, j'associe une variable spécifique que je nomme "userLogin" et qui prend la valeur xxx"... Cette valeur, ça peut être un username, une adresse IP, etc... Ensuite, par le "template" %x{userLogin} tu appelles cette variable... Tu peux définir tout en n'importe quoi comme variable... Tu n'as absolument rien à faire sur ton logger ou ton appender, c'est la classe layout qui gère l'appel à cette variable spécifique à ton thread par %x{leNomDeCetteVariableSpécifiqueAMonThread}


 
Oui, très clair, merci.
Sauf qu'apparement, tu confond le NDC et le MDC. En gros, le NDC est une pile de thread, alors que le MDC est une hashtable de thread.
Par contre, je voudrais bien comprendre 2, 3 trucs :  
- avec des servlet, on à un thread par client, oui ?
- avec log4j, chaque logging se déroule dans le même thread que le thread client qu'il l'a appelé (une servlet par exemple), oui ?
- Les MDC et NDC, ça peut être carrément utile pour d'autres truc que log4j, c génial ces trucs...
 
Merci beaucoup, et longue vie à log4j ! :hello:

Reply

Marsh Posté le 11-03-2003 à 17:10:21    

El_gringo a écrit :


- avec des servlet, on à un thread par client, oui ?


 
 [:darklord]  
 
http://developer.java.sun.com/deve [...] #lifeCycle


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 11-03-2003 à 17:33:25    


 
Heu... g pas trop l'temps de lire tout ça là.
ta réponse, ça veut dire que j'me plante complètement ?

Reply

Marsh Posté le 11-03-2003 à 22:17:52    

El_gringo a écrit :


 
Heu... g pas trop l'temps de lire tout ça là.
ta réponse, ça veut dire que j'me plante complètement ?


 
oui :D


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 12-03-2003 à 08:52:23    


 
Ouais, en fait, un thread par client, c'était pas trop possible...
Donc il peut y avoir plusieurs threads en même temps. Surements pas un par client.
Pour mon truc, ça a donc la conséquence suivante : les infos complémentaires que j'apporte pour mon logging, avec le MDC doivent être renseignée juste avant l'appel à la méthode de logging, ou au moins dans le traitement de la même requête, on est d'accord ?

Reply

Marsh Posté le 12-03-2003 à 09:02:31    

J'veux dire, 'faudrai pas que je m'ammuse à faire ça :
lors du traitement d'une requête par ma servlet, renseigner le MDC, et puis lors du traitement d'une autre requête, logguer qqch, en tentant d'utiliser les infos précédement insérées dans le MDC.

Reply

Marsh Posté le 14-03-2003 à 23:43:06    

Rien a voir, mais Log4J tourne avec quelle version de la JDK ? (j'ai une plateforme qui va etre utilisee dans le cadre d'un projet pour controler un robot industriel et la VM disponible est une 1.1)  
 
(P.S. c'est serieux)
 
Merci ;)

Reply

Marsh Posté le 01-08-2003 à 11:39:30    

MachinBidule1974 a écrit :

Pour associer une donnée à un thread et afficher cette donnée dans le message loggé par Log4J, tu peux utliser les MDC (Mapped Diagnotic Context) de Log4J, où à un Thread est associé un objet. Typiquement, dans ta servlet d'action, avant d'effectuer l'action, tu définis une valeur comme le login de l'utilisateur via le MDC. Tu peux alors afficher cette valeur dans le layout de ton message avec %x si je me rappelle bien. En fin de traitement, dans la servlet d'action, tu retires ce mapping avec la méthode MDC.remove();
 
Je sais pas si je suis très clair... :)
 
Mais je vois pas l'intêret de redévelopper une API de Log4J vu que Log4J existe et est très puissante... En paramétrant, tu dois pouvoir créer une log orientée exploit quitte à introduire un niveau de log type "exploitation"...


 
Je ressort ça, parce qu'il y a un truc qui me travail.
Je rapelle que je suis ds le cadre d'une web-app. Comment ce MDC assure que les données ne vont pas être melangées entre les clients ? Parce que, si je n'me trompe pas, chaque client n'a pas son propre thread...

Reply

Marsh Posté le 01-08-2003 à 12:40:37    

bin si un thread est associé à un objet ...


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 01-08-2003 à 14:13:28    

DarkLord a écrit :

bin si un thread est associé à un objet ...


 
Comment ça ?
Tu connais le système du MDC dans log4j ?
Et si oui, c'est ok si on y met des données spécifiques à un client ?

Reply

Marsh Posté le 01-08-2003 à 14:15:06    

El_gringo a écrit :


 
Comment ça ?
Tu connais le système du MDC dans log4j ?
Et si oui, c'est ok si on y met des données spécifiques à un client ?


 
bin su tu considère qu'un client = un objet ....


---------------
Just because you feel good does not make you right
Reply

Marsh Posté le 01-08-2003 à 14:20:41    

DarkLord a écrit :


bin su tu considère qu'un client = un objet ....


 
Mais je comprends pas de quel "objet" tu parles.
Un MDC ça s'utilise avec des méthodes statiques...

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed