operator<< für eine Logger Klasse



  • Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.



  • Super, jetzt funktioniert es. Jetzt muss ich nur noch angucken warum genau 😕

    queer_boy schrieb:

    btw. ich finde bei dir kein delete für _instance. nur null setzen reicht nicht.
    außerdem ist das nette am CRTP, dass du den destruktor gerade *nicht* virtuell machen musst, weil das delete im destruktor von Singleton<logger> automatisch logger::~logger aufruft. und andersrum brauchst du in logger auch keine methode instance().

    Ich hatte das Singleton und seine Benutzung irgendwo im Netz gefunden. Es sah weniger verwirrend aus als die meisten Anderen. Und ich hab mir ehrlich gesagt nicht viel Kopf um die Richtigkeit gemacht. Aber du hast natürlich recht, die logger::instance() Funktion ist überflüssig.
    Ich habe noch zwei Fragen:
    1. Warum ist der Unterschied virtuell oder nicht für den Destruktor in dieser Klasse wichtig? Funktionieren scheint beides.
    2. Ich habe nicht ganz verstanden wie du das mit dem delete meinst, kannst du das genauer erklären?

    this->that schrieb:

    Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.

    In diesem Falle weil es sich um ein spezielles Problem handelt. Ich muss einen etwas nervigen Fehler in einem Projekt finden der sich aber über mehrere Klassen erstreckt. Und da dachte ich, eh ich immer nen Zeiger mitschleife und alle Funktionen änderen muss, kann ich auch mal ein Singleton ausprobieren.



  • ElClowno schrieb:

    this->that schrieb:

    Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.

    In diesem Falle weil es sich um ein spezielles Problem handelt. Ich muss einen etwas nervigen Fehler in einem Projekt finden der sich aber über mehrere Klassen erstreckt. Und da dachte ich, eh ich immer nen Zeiger mitschleife und alle Funktionen änderen muss, kann ich auch mal ein Singleton ausprobieren.

    Dann mach dir lieber ein gescheites Logsystem, das du auch wieder verwenden kannst... Dies wird nicht der letzte Fall sein bei dem du was mitloggen willst.



  • ElClowno schrieb:

    this->that schrieb:

    Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.

    In diesem Falle weil es sich um ein spezielles Problem handelt. Ich muss einen etwas nervigen Fehler in einem Projekt finden der sich aber über mehrere Klassen erstreckt. Und da dachte ich, eh ich immer nen Zeiger mitschleife und alle Funktionen änderen muss, kann ich auch mal ein Singleton ausprobieren.

    Schon mal was von debuggen gehört?



  • David_pb schrieb:

    Dann mach dir lieber ein gescheites Logsystem, das du auch wieder verwenden kannst... Dies wird nicht der letzte Fall sein bei dem du was mitloggen willst.

    Ich hab im Moment nicht die Zeit das zu tun. Das Projekt existiert schon, weswegen das einflechten im Nachhinein ziemlich (zu) aufwendig ist. Und wieso ist dieses nicht wiederverwendbar, eigentlich ist es nur ein ofstream den es nur einmal gibt?

    sag mal schrieb:

    Schon mal was von debuggen gehört?

    Ja, half hier bisher nicht wirklich weil der Fehler etwas fließend ist. Außerdem, was spricht dagegen dieses Konzept mal zu probieren wenn es in diesem Fall sinnvoll ist. Gut, ne einfache Klasse mit nem static ofstream hätte es wohl auch getan, aber ich wollte dabei auch was lernen.



  • this->that schrieb:

    Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.

    Kannst du mir sagen wie man Logger ohne Singletons vernünftig einsetzen kann?
    Gerade das, also Logging, ist eine Sache wo man IMO ohne Singletons fast nicht auskommt. Allen Klassen und Funktionen einen Logger mitzugeben ist IMO halt etwas umständlich und klobig.

    Die einzige IMO brauchbare Möglichkeit die mir dazu bis jetzt eingefallen ist, ist thread-lokale Variablen zu verwenden.
    Dann kann man solche Konstrukte schreiben:

    void bar();
    
    void foo()
    {
        Logger l;
        LoggerScope s(l); // setzt die thread-lokale variable
        bar();
    }
    
    void bar()
    {
        GetLogger() << "blah"; // GetLogger liest die thread lokale variable
    }
    

    Allerdings funktioniert das auch nur genau solange bis man es irgendwo mit Callbacks aus Threads zu tun bekommt, die man nicht selbst kontrolliert.

    Wenn du mir da also einen Tip geben könntest wäre ich sehr froh, da ich echt keine Vernünftige Lösung kenne.



  • hustbaer schrieb:

    this->that schrieb:

    Nur so nebenbei: Wieso ist dein Logger ein Singleton? Wieso verwährst du dir damit die Möglichkeit, mehrere Logger zu benutzen?
    Singletons sind zu 99% überflüssig.

    Kannst du mir sagen wie man Logger ohne Singletons vernünftig einsetzen kann?

    Kann ich, auch wenn ich die Singletonvariante nicht ablehne (Eine Variante):

    ...
    boost::shared_ptr<Logger> GetLogger(std::string const & loggerName)
    {
      static std::map<std::string, boost::shared_ptr<Logger> > LogList;
      ...
      return LogList[loggerName];
    }
    
    int main()
    {
      GetLogger("error.log")->Log("Something");
    }
    

    hustbaer schrieb:

    Gerade das, also Logging, ist eine Sache wo man IMO ohne Singletons fast nicht auskommt. Allen Klassen und Funktionen einen Logger mitzugeben ist IMO halt etwas umständlich und klobig.

    Deinen letzten Satz stimme ich zu, deinen ersten nicht zwangsweise. Siehe mein Beispiel. Ich habe das obere jetzt nicht irgendwie Threadsicher gemacht, aber ich schätze mal das sollte ohne Probleme machbar sein...

    cu André



  • @asc:
    Äh. Ich habe geschrieben ohne Singletons.

    static std::map<std::string, boost::shared_ptr<Logger> > LogList;
    

    Hallo, Singleton? 🙂

    Klar kann man das Problem so ein Stück weiter schieben, das machen ja auch fast alle üblichen Logging Libraries so. Aber man kann dadurch immer noch nicht erreichen dass eine einzige Funktion in verschiedene Logfiles loggt, je nachdem aus welchem Programmteil sie aufgerufen wurde.

    Und in Programmen die verschiedene Dinge tun, und daher u.u. auch verschiedene Logfiles schreiben wollen, wäre das eine tolle Sache.



  • hustbaer schrieb:

    @asc:
    Äh. Ich habe geschrieben ohne Singletons.

    static std::map<std::string, boost::shared_ptr<Logger> > LogList;
    

    Hallo, Singleton? 🙂

    Ich sehe darin kein Singleton, zumindestens nicht unter den klassischen Begriff das es nur eine Instanz geben kann. Eine statische Variable alleine ist für mich noch kein Singleton - Ich kann zwar über den Methodenzugriff die Erzeugung kontrollieren, könnte den Logger aber auch beliebig anders verwenden, und mein Konstrukt sieht auch mehrere Logger vor (z.B. Einen pro Ziel).

    cu André



  • hustbaer schrieb:

    Und in Programmen die verschiedene Dinge tun, und daher u.u. auch verschiedene Logfiles schreiben wollen, wäre das eine tolle Sache.

    Und? Wo ist bei meinen Einsatz die Einschränkung?

    ...
    boost::shared_ptr<Logger> GetLogger(std::string const & loggerName)
    {
      static std::map<std::string, boost::shared_ptr<Logger> > LogList;
      // <-- Prüfen ob Logger existiert, sonst ggf. neuen anlegen...
      return LogList[loggerName];
    }
    
    int main()
    {
      GetLogger("error.log")->Log("Something");
      GetLogger("test.log")->Log("Something Other");
    }
    

    Ja, ich habe nur einen Minimalcode Geschrieben, aber sag mir bitte wo hier ein Singleton ist und NUR ein Logger?


Anmelden zum Antworten