Associer un code d'erreur spécifique au contexte dans Log4J

Associer un code d'erreur spécifique au contexte dans Log4J - Java - Programmation

Marsh Posté le 12-02-2004 à 10:32:49    

Salut,
 
Je viens de me faire "avoir" encore chez un de mes clients chez qui je viens de passer une appli Java en production. Comme la machine va être infogérée, l'infogéreur va utiliser un système de "monitoring" genre Tivoli pour automatiser la surveillance des applis.
 
Problème: mon appli qui génère une log au format Log4J n'est pas "pluggable" telle quelle "sur" Tivoli. Il faut que pour chaque exception, message d'erreur qui est susceptible d'arriver, j'associe un code sur 4 positions numériques (par exemple) identifiant le contexte de l'erreur. A partir de ce code, Tivoli est capable de déclencher des alertes s'il a été correctement paramétre. Ensuite, pour chaque code d'erreur, on doit spécifier l'action que l'infogérance doit entreprendre...
 
Question: Comment puis-je faire sans avoir a me repalucher toutes les throw & catch d'exceptions pour insérer un code d'erreur spécifique au contexte de mon exception ?
 
PS: Dans le pire des cas, je mets en début du message que je logge mon code d'erreur comme "VWXY - Erreur JMS", ce qui crée une pseudo-colonne dans ma log... Mais je trouve pas ça terrible quand même :/
 
Merci de vos réponses

Reply

Marsh Posté le 12-02-2004 à 10:32:49   

Reply

Marsh Posté le 12-02-2004 à 10:35:00    

Ta question n'est pas claire. Quels sont les contextes en question?


Message édité par darklord le 12-02-2004 à 10:35:10
Reply

Marsh Posté le 12-02-2004 à 10:38:36    

Eh bien, par exemple, si je suis susceptible de lever une exception comme une XMLException. Dans un cas ma XMLException sera associée à un code d'erreur 100 car elle intervient dans le chargement du paramétrage. Puis dans un cas de traitement d'un fichier XML quelconque, ce devra être un autre code d'erreur, disons 200, car le contexte sera différent.
 
Bref, le code d'erreur n'est pas spécifique à l'exception mais au contexte dans lequel celle-ci a été rencontrée.

Reply

Marsh Posté le 12-02-2004 à 10:39:59    

Ca me fait vraiment marrer ca. Et donc log4j il est censé trouver tout seul les contextes en question. C'est meme pas basé sur l'exception?
Tu comptais faire comment excepté te palucher toutes tes lignes de log comme tu dis?

Reply

Marsh Posté le 12-02-2004 à 11:13:05    

Est-ce-que t'es obligé de tout le temps prendre les gens de haut comme ça ? On sait que t'es une bête en java, c'est bon...
 
Je me doute bien que je vais être obligé, si je veux mettre quelquechose de propre en place, de retoucher à toute la gestion des exceptions. J'aurai pas dû mettre ça dans mon 1er post (que je voulais pas me "repalucher toute la gestion des exceptions" ).  
 
Maintenant, comment est-ce-que je peux mettre en place de système de code d'erreur basé sur le contexte de la levée de l'exception ?
 
J'avais pensé à déclarer un attribut errorCode de type int dans une exception générique dont hériterait toutes mes exceptions. Puis à étendre les classes de Log4J pour gérer ce nouvel attribut...

Reply

Marsh Posté le 12-02-2004 à 11:16:55    

non mais attends ca n'a rien à voir avec le fait d'etre bon en X ou Y. Je sais que je suis intélorant, je ne le nie pas mais bon ton post m'a donné l'impression que t'as pas réfléchi plus de 3 secondes et ca ca m'énerve [:spamafote]
 
Bon alors y a plusieurs solutions.
 
# Tu crées ton propre logger qui hérite du logger de log4j et tu redéfinis les méthodes de log pour qu'elle accepte un code d'erreur
# Y a un truc en log4j qui permet d'attacher un contexte à une exception (MDC si mes souvenirs sont bon). Rien ne t'empeche d'attacher le code d'erreur en question et redéfinir PatternLayout pour qu'il accpète un nouveau tag qui serait un attribute de conctexte (ton code d'erreur quoi).
 
Si tu veux une autre solution que logger.error("[XYZA] Failed to ...", e); il va falloir redéfinir le comportement par défaut (toujours à ce que je sais)

Reply

Marsh Posté le 12-02-2004 à 11:26:34    

Merci pour ta réponse.
 
En fait, si j'ai réfléchi + de 3 secondes à ce problème car j'y ai été déjà confronté par le passé chez 2 clients différents. A l'époque, j'avais créé une sorte de ApplicationException avec un attribut de type errorCode (int). A chaque fois que je levais une ApplicationException ou l'une de ses sous-classes, je passais au constructeur ce fameux code d'erreur dépendant du contexte.
 
J'avais aussi modifié le PatternLayout afin de gérer un nouveau "joker" (%e si je me rappelle bien) qui tentait sur l'exception à logger d'extraire le code d'erreur... Et aussi crée un nouveau PatternParser...
 
Ca marchait bien mais uniquement dans le cas où l'on loggait des exceptions.
 
Désormais je veux mettre en place le code d'erreur aussi quand je logge de simples messages...
 
je pense que je vais devoir m'en tenir à ce que j'ai déjà fait + faire ce que tu me conseilles, c-a-d, créer mon propre logger avec des méthodes error(int, String)...

Reply

Marsh Posté le 12-02-2004 à 11:35:23    

si tu sais poster la solution, ca m'intéresse, j'ai jamais fait ca
 
:jap:
 
J'ai acheté le bouquin de log4j et ca fait 2 semaines que j'attends que le poste me l'envoie :fou:
 
:sweat:


Message édité par darklord le 12-02-2004 à 11:35:53
Reply

Marsh Posté le 12-02-2004 à 12:32:52    

Voici les classes dont je parlais:
 
Exception "encapsulante" permettant de faire l'association exception <-> code d'erreur
 

Code :
  1. package xxx.exceptions;
  2. /**
  3. * Exception générique destinée à la journalisation Tivoli, caractérisée par un code
  4. * d'erreur passé au constructeur de la classe.
  5. *
  6. * Cette exception enveloppe une autre exception (l'exception mère)
  7. */
  8. public class TivoliException extends Exception {
  9. // Attribut privé contenant l'exception mère de cette exception
  10. private Throwable cause = null;
  11. // Code d'erreur associé à l'exception
  12. private int errorCode;
  13. /**
  14.  * Constructeur
  15.  * <br>
  16.  * @param errorCode
  17.  */
  18. public TivoliException(int errorCode) {
  19.  super();
  20.  this.errorCode = errorCode;
  21. }
  22. /**
  23.  * Constructeur
  24.  * <br>
  25.  * Method TivoliException.
  26.  * @param errorCode
  27.  * @param cause
  28.  */
  29. public TivoliException(int errorCode, Throwable cause) {
  30.  this(errorCode);
  31.  this.cause = cause;
  32. }
  33. /**
  34.  * Method getCause.
  35.  * Retourne l'exception mère de cette exception
  36.  * @return Throwable
  37.  */
  38. public Throwable getCause() {
  39.  return cause;
  40. }
  41. /**
  42.  * Method getErrorCode.
  43.  * Retourne le code d'erreur associé à cette exception
  44.  * @return int
  45.  */
  46. public int getErrorCode() {
  47.  return errorCode;
  48. }
  49. /**
  50.  * @see java.lang.Throwable#printStackTrace()
  51.  */
  52. public void printStackTrace() {
  53.  System.err.println("ErrorCode: " + getErrorCode());
  54.  if (cause != null) {
  55.   cause.printStackTrace();
  56.  }
  57. }
  58. /**
  59.  * @see java.lang.Throwable#printStackTrace(PrintStream)
  60.  */
  61. public void printStackTrace(java.io.PrintStream ps) {
  62.  ps.println("ErrorCode: " + getErrorCode());
  63.  if (cause != null) {
  64.   cause.printStackTrace(ps);
  65.  }
  66. }
  67. /**
  68.  * @see java.lang.Throwable#printStackTrace(PrintWriter)
  69.  */
  70. public void printStackTrace(java.io.PrintWriter pw) {
  71.  pw.println("ErrorCode: " + getErrorCode());
  72.  if (cause != null) {
  73.   cause.printStackTrace(pw);
  74.  }
  75. }
  76. }


 
Classe de type Layout spécialisée pour appeler le PatternParser qui va bien...
 

Code :
  1. /*
  2. * Created on 12 févr. 2004
  3. */
  4. package org.apache.log4j;
  5. import org.apache.log4j.helpers.PatternParser;
  6. import org.apache.log4j.helpers.TivoliPatternParser;
  7. /**
  8. * Layout spécialisé afin de gérer le code d'erreur spécifique à une
  9. * exception de type TivoliException
  10. *  
  11. * Date: 12 févr. 2004
  12. */
  13. public class TivoliPatternLayout extends PatternLayout {
  14. public TivoliPatternLayout() {
  15.  super();
  16. }
  17. public TivoliPatternLayout(String pattern) {
  18.  super(pattern);
  19. }
  20. /* (non-Javadoc)
  21.  * @see org.apache.log4j.PatternLayout#createPatternParser(java.lang.String)
  22.  */
  23. protected PatternParser createPatternParser(String pattern) {
  24.  return new TivoliPatternParser(pattern);
  25. }
  26. }


 
Parser spécialisé afin de gérer le joker ("%E" ) qui appelle le code d'erreur d'une TivoliException
 

Code :
  1. /*
  2. * Created on 12 févr. 2004
  3. */
  4. package org.apache.log4j.helpers;
  5. import org.apache.log4j.spi.LoggingEvent;
  6. import org.apache.log4j.spi.ThrowableInformation;
  7. import xxx.exceptions.TivoliException;
  8. /**
  9. * Parser de pattern capable de gérer le joker spécifique au code d'erreur (%E)
  10. * d'une exception
  11. *   
  12. * Date: 12 févr. 2004
  13. */
  14. public class TivoliPatternParser extends PatternParser {
  15. /**
  16.  * Constructeur
  17.  *  
  18.  * @param pattern
  19.  */
  20. public TivoliPatternParser(String pattern) {
  21.  super(pattern);
  22. }
  23. /* (non-Javadoc)
  24.  * @see org.apache.log4j.helpers.PatternParser#finalizeConverter(char)
  25.  */
  26. protected void finalizeConverter(char c) {
  27.  if (c == 'E') {
  28.   PatternConverter pc = new ErrorCodeConverter();
  29.   currentLiteral.setLength(0);
  30.   addConverter(pc);
  31.  } else {
  32.   super.finalizeConverter(c);
  33.  }
  34. }
  35. // ------------------------------------------------- //
  36. // Classe de génération du texte associé au joker %E //
  37. // ------------------------------------------------- //
  38. private static class ErrorCodeConverter extends PatternConverter {
  39.  ErrorCodeConverter() {
  40.   super();
  41.  }
  42.  public String convert(LoggingEvent event) {
  43.   ThrowableInformation ti = event.getThrowableInformation();
  44.   if (ti != null) {
  45.    Throwable t = ti.getThrowable();
  46.    if ((t != null) && (t instanceof TivoliException)) {
  47.     return Integer.toString(
  48.      ((TivoliException) t).getErrorCode());
  49.    }
  50.   }
  51.   return "";
  52.  }
  53. }
  54. }


 
Classe de test
 

Code :
  1. /*
  2. * Created on 12 févr. 2004
  3. */
  4. package xxx.test;
  5. import org.apache.log4j.ConsoleAppender;
  6. import org.apache.log4j.Logger;
  7. import org.apache.log4j.TivoliPatternLayout;
  8. import xxx.exceptions.TivoliException;
  9. /**
  10. * Classe de test
  11. *   
  12. * Date: 12 févr. 2004
  13. */
  14. public class TivoliExceptionTest {
  15. /** Logger */
  16. private static final Logger logger =
  17.  Logger.getLogger(TivoliExceptionTest.class);
  18. public static void main(String[] args) {
  19.  logger.addAppender(
  20.   new ConsoleAppender(
  21.    new TivoliPatternLayout("%d - %c - %E - %m%n" )));
  22.  logger.info("début" );
  23.  logger.error("Error 1", new RuntimeException("Yep" ));
  24.  logger.error(
  25.   "Error 2",
  26.   new TivoliException(1000, new RuntimeException("Nope" )));
  27.  logger.info("fin" );
  28. }
  29. }


 
J'ai étendu les classes de Log4J car ma 1ère implémentation était dégueulasse. J'avais fait ça dans l'urgence à l'époque !

Reply

Sujets relatifs:

Leave a Replay

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