IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Modélisation : classe de logs


Sujet :

C++

  1. #1
    Membre chevronné
    Inscrit en
    Novembre 2006
    Messages
    362
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 362
    Par défaut Modélisation : classe de logs
    Bonjour.

    Je cherche à modéliser une classe qui permettra à mon programme de tracer tout ce qu'il fait.

    Je voudrais pouvoir m'en servir comme ça (en gros) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    LogsManager a;
    a->log("Je commençe le programme"); // certains des logs sont statiques
    a->log("Zut, j'ai un objet d'id " + id + " qui est négatif"); // mais pas tous
     
    // on peut (doit) donner un type à un log
    a->log("Je commençe à parser", LogsManager::Parsing);
     
    // on peut même en donner plusieurs
    std::list<LogsManager::LogsTypes> types;
    types.push_back(LogsManager::Parsing);
    types.push_back(LogsManager::StrangeData);
    a->log("J'ai parsé la valeur " + val + " qui est supérieure à 100", types);
    Dans cet exemple, je suppose quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    class LogsManager
    {
    public :
    	...
     
    public :
    	enum LogsTypes
    	{
    		Parsing = 0,
    		StrangeData,
    		...
    	}
    	....
    }
    Ceci ne semble pas présenter de grandes difficultés.
    Sauf que cela me chagrine que les types soient aussi dynamiques.

    Cela va me donner derrière une fonction qui aura comme tête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    void LogsManager::log(const std::string& log, const std::list<LogsManager::LogsTypes>* types)
    {
    	if (types)
    	{
    		std::list<LogsManager::LogsTypes>::iterator it;
    		for(it = types.begin(); it != types.end(); it++)
    		{
    			switch (*it)
    			{
    				case Parsing :
    					...
    					break;
    				case StrangeData :
    					...
    					break;
    				...
    			}
    		}
     
    		....
    	}
    }
    Et ça ce n'est pas très joli.
    J'imagine qu'il existe une chouette solution pour faire cela statiquement, peut-être avec un genre de typelist, mais tout ce que je peux imaginer est terriblement compliqué.

    Est-ce que quelqu'un saurait m'orienter vers une solution plus élégante ?

    Merci par avance

  2. #2
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    C'est l'inconvénient de programmer en C++ sans jamais avoir vu de vrai code C !

    Donc, la solution la plus utilisée en C (encore valable en C++), c'est de passer par un enum. -> pour les questions là dessus.

  3. #3
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Enum ??

    Je suggérerais au contraire de transformer les enums en vraies classes avec du code dedans, quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    class LogType
    {
        void log( ... ) = 0;
    };
     
    class Parsing : public LogType
    {
      ...
    };
     
    void LogsManager::log( const std::string& log, const std::list<LogType>& types )
    {
        for( std::list<LogsManager::LogsTypes>::iterator it = types.begin(); it != types.end(); it++)
            it->log( ... );
    }
    Ca me parait plus souple quand même.
    (au passage je pense qu'il vaut mieux plusieurs versions de la méthode log plutôt que de passer un pointeur sur une std::list pour tester s'il vaut 0 par la suite, mais bon c'est un choix)

    Cela dit, comme toujours, peut-être qu'une solution (open-source) existante permettrait de gagner du temps ?
    Il y a par exemple log4cxx, que je n'ai jamais essayé cela dit, en général je ne log jamais rien je ne trouve pas que ça soit très utile comme pratique...

    MAT.

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Ce n'est pas tant des enum que des manipulations de bits dont voulait parler mchk0123. Je me trompe ? Les enums ne sont pas si adaptés à cela vu que le nombre composé ... n'est plus du type de l'énuméré.

    Si ces traitements particuliers peuvent être réalisés avec une même fonction (pas d'arguments propres à un traitement) c'est très bien comme ça (les enums)

    Etant dans une situation avec des traitements différents à réaliser selon les destinations, j'ai tendance à plutôt partir sur des sytèmes qui s'utilisent de la sorte.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    LOG( formatter("toto %2 titi %1") % 42 % "tutu" ) 
        .trace("[Nom Fonction]", OPERATION) // fichier de log
        .alarm(CRITICAL, vehicle1) // notification d'un composant particulier
        .logbook(CRITICAL, vehicle1, composantEmeteur, dateBord) // notif d'un autre composant
        .exception(); // throw est un mot clé déjà résérvé
    // le code permettant d'arriver à cela n'est pas forcément simple.
    Il y a plein de façons différentes de s'y prendre, et je ne trouve pas qu'il y en ait une qui soit meilleure que les autres.

    PS: Ces dernières semaines, il y a eu quelques discussions relatives aux sytèmes de log.

    PPS: Je loggue énormément. Il s'agit d'un gros composant multi-tâche qui doit tourner pendant des jours et des jours sans s'arréter. D'autant qu'il n'est pas rare que l'on ne dispose plus des binaires associés à un crash (-> coredump inexploitable). Bref, il n'y a souvent que cela pour nous aider à diagnostiquer les anomalies de fonctionnement.
    Après l'analyse des logs se fait les doigts dans le nez quand on dispose d'un outil adapté (gvim au hasard )
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Membre émérite Avatar de mchk0123
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    816
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Janvier 2007
    Messages : 816
    Par défaut
    Pour les enums, oui l'utilisation bas niveau se fait à base d'opérations binaires, mais les enums sont là pour avoir une sélection des options sous forme symbolique et pas numérique (quelques petits pbs. de conversions entre énums et entier, mais ça reste confiné à l'intérieur de la classe Log).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    log.options(Log::no_echo | Log::named_pipe | Log::only_criticals);
    log.filename("log.txt");
    log.print(format("%s : %s\n", nom_composant, msg));
    C'est vrai qu'avec ma solution, je suis obliger de cinder le paramétrage du log en 2 : les options d'un côté (enums), les valeurs de l'autre (int, string, ...).

    Trés élégante et flexible ta solution Luc Hermitte (j'avais pas penser à utiliser la même notion qui existe sur les fstream). :roi2:
    Je me la note dans un coin du cerveau !

    Sans parler du "%" ! On dirait presque du P.... (je tairais le nom ).
    Le C++ n'as pas fini de nous étonner !

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 292
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 292
    Par défaut
    Tout n'est pas incompatible.
    Ce que j'ai montré, c'est l'utilisation (au travers d'une macro qui va mémoriser __FILE__ et __LINE__ pour les injecter dans l'exception levée). Tu peux en plus initialiser ton loggeur comme il te plait, avant. Voire avoir une option pour logguer via le logger "log".
    (Il y a tellement de choix possibles, que j'ai le plus grand mal à définir un système de logs véritablement générique)

    Le truc est que dans notre application certains messages ne partent que dans l'unique fichier de traces du composant, d'autres sont envoyés (via Corba) vers un composant (ou l'autre) qui va redispatcher les alertes (typées) aux IHMs. Chaque message va avoir son traitement qui lui est propre. Avec les paramètres associés.

    Du coup, j'ai besoin de paraméter le message dans les fonctions "génériques" qui ont un véhicule déternimé au dernier moment.
    Quand le seul choix c'est fichier1, fichier2, ou console, pas besoin de sortir un truc aussi compliqué.


    Pour le %1, ce n'est pas de moi. boost.format propose cela -- autant dire, que le formateur, je ne tiens pas particulièrement à l'implémenter personnellement. Et la première fois que je l'avais croisé, c'était en TCL.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [MCD] Modélisation classe d'élèves
    Par max87 dans le forum Schéma
    Réponses: 2
    Dernier message: 23/12/2009, 23h14
  2. Classe de logging utilitaire
    Par dobfatch dans le forum Logging
    Réponses: 7
    Dernier message: 04/08/2009, 18h16
  3. Réponses: 8
    Dernier message: 13/11/2006, 16h45
  4. Classe de log
    Par rh0D'm@n dans le forum Logging
    Réponses: 4
    Dernier message: 19/10/2005, 15h47
  5. Une classe de log ?
    Par chronos dans le forum Java ME
    Réponses: 2
    Dernier message: 21/06/2005, 14h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo