WElche Logging-Bibliothek?



  • Hoi!
    Ich suche eine Logging-Bibliothek für mein Projekt. (C++)

    Folgende Anforderungen habe ich:
    - Möglichst Header-only oder wenigstens mit CMake ausgeliefert.
    - Läuft auf Linux, OsX, Windows.
    - 4 Log-Stufen (Info, Warning, Error, Debug) reichen mir.
    - Sauberes C++, ich möchte keine 10 Warnungen pro Sourcefile.
    - std::ostream als Backend.
    - Integrierte Zeitausgabe.
    - Simple Bedienung.

    Also eigentlich total Standard. Da es aber im als Paradebeispiel für Reinventing-the-Wheel vorgehalten wird seine eigene Logging-Bibliothek zu schreiben, frage ich eben hier.

    Ich tendiere ja zu Boost.Log, was aber ja leider noch nicht zu Boost gehört.
    Und ja, ich habe gesucht. Nur gibts die Dinger auch wie Sand am Meer.

    Danke und Grüße,
    Flo



  • Boost.Log gehört nicht offiziel zu Boost? 😕



  • Es ist seit 2010 akzeptiert aber immer noch nicht dabei.





  • Aus den wenigen Antworten hier entnehme ich, das kaum jemand der mit C++ arbeitet Logging verwendet.



  • pagina schrieb:

    Aus den wenigen Antworten hier entnehme ich, das kaum jemand der mit C++ arbeitet Logging verwendet.

    logging ist auch einfach unschön und bläst den code unnötig auf.



  • log4cplus ist sicher auch noch zu erwähnen.

    Ich hatte neulich gerade eine Logging Library für ein C++ Projekt evaluiert - log4cplus war der Gewinner. 🙂 Hier noch grob meine Erfahrungen mit den Libraries:
    log4cplus buildete out-of-the-box unter Linux und Windows und bietet viele nützliche Features.

    Mit Boost.Log hatte ich Probleme zu builden (Compiler Errors) unter MSVC 2010 SP1, was mich dazu veranlasste die Library nicht mehr zu berücksichtigen obwohl die Features und die Konzepte vielversprechend sind. Auch scheint die Library zwar bei Boost angenommen zu sein, jedoch mit Vorbehalten - und in dieser Richtung scheint nicht mehr viel gegangen zu sein.

    logog habe ich mir auch angesehen, da fehlten einige Features, die aber nachgerüstet werden könnten. Die Library sieht sehr vielversprechend aus, wurde jedoch auch nicht berücksichtigt. Das grösste Problem war, dass unser Projekt aus vielen DLLs/SOs besteht (welche alle in einem Prozess laufen) und die Library unter Windows nicht alls DLL benutzt werden kann. Das führt führt zu Problemen (interne statische Strukturen der Library sind dann pro DLL vorhanden.

    Andere Libraries wie log4cxx, rlog, Boost Logging (die andere von John Torjo) etc. wurden angeschaut wurden jedoch nicht berücksichtigt weil das Featureset nicht ausreichend war oder sie sehr alt sind.

    Hoffe das hilft ein wenig. Ev. ist die Restriktion, dass logog unter Windows nur als static Library Sinn macht, für dein Projekt kein Problem?



  • Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.



  • Danke für die Antworten. 😉
    Hab mich jetzt erstmal für logog entschieden.

    Die Millionen GCC-Warnungen nerven tierisch und ich hatte schon 2 Segfaults weil ich mich ausversehen bei den Formatstrings vertan habe. Ansonsten gefällt sie mir aber. 😉



  • li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?



  • theta schrieb:

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?

    google glog
    http://code.google.com/p/google-glog/



  • just a hint schrieb:

    theta schrieb:

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?

    google glog
    http://code.google.com/p/google-glog/

    aber das hat doch erst die versionsnummer 0.3.2 was bedeutet das es völlig unausgereift ist



  • just a hint schrieb:

    theta schrieb:

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?

    google glog
    http://code.google.com/p/google-glog/

    Die API gefällt mir 👍



  • versionsdeuter schrieb:

    google glog
    http://code.google.com/p/google-glog/

    aber das hat doch erst die versionsnummer 0.3.2 was bedeutet das es völlig unausgereift ist[/quote]
    Versionsnummern deuten ist ungefähr so aussagekräftig wie Kaffeesatzlesen.


  • Administrator

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    lol, würde man dann wohl auch bei zlib oder libpng sagen müssen. Aber irgendwie habe ich das Gefühl, dass den Programmierer ziemlich egal ist, wie die Internetpräsenz aussieht, solange die benötigten Daten geliefert werden und die Bibliothek gut ist.

    Noch zwei Logging-Frameworks, welche nicht erwähnt wurden:
    http://www.pantheios.org/
    http://axter.com/ezlogger/

    Grüssli



  • fdfdg schrieb:

    just a hint schrieb:

    theta schrieb:

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?

    google glog
    http://code.google.com/p/google-glog/

    Die API gefällt mir 👍

    i used to like the arrow in the knee joke, but then i took an arrow to the knee.



  • mysweetestfriend schrieb:

    fdfdg schrieb:

    just a hint schrieb:

    theta schrieb:

    li on schrieb:

    Niemand wird log4cplus ernst nehmen, bei so einer altbackenen Internetpräsenz.

    Ich bin an Alternativen interessiert - hast Du welche?

    google glog
    http://code.google.com/p/google-glog/

    Die API gefällt mir 👍

    i used to like the arrow in the knee joke, but then i took an arrow to the knee.

    Ich bin an Alternativen interessiert - hast Du welche?



  • mysweetestfriend schrieb:

    i used to like the arrow in the knee joke, but then i took an arrow to the knee.

    http://www.youtube.com/watch?v=mSDfxde8fSg



  • So, hab mir jetzt einfach selbst etwas zusammen gehackt. Da mir ein einziger Sink reicht, erfüllt das für mich den Zweck besser als alle anderen Bibliotheken, die ich in Betracht gezogen habe:

    #ifndef __SYNTHETIC_COMMON_LOG_HPP__
    #define __SYNTHETIC_COMMON_LOG_HPP__
    
    // C++ Standard Library:
    #include <ostream>
    #include <thread>
    #include <cstring>
    
    #define SYNTHETIC_LOGLEVEL_LOGNONE 0
    #define SYNTHETIC_LOGLEVEL_CRITICAL 1
    #define SYNTHETIC_LOGLEVELL_ERROR 2
    #define SYNTHETIC_LOGLEVEL_WARN 3
    #define SYNTHETIC_LOGLEVEL_INFO 4
    #define SYNTHETIC_LOGLEVEL_DEBUG  5
    #define SYNTHETIC_LOGLEVEL_LOGALL 100
    
    namespace synthetic
    {
        namespace common
        {
            namespace logging
            {
                typedef std::ostream backend_type;
    
                /**
                 * @brief Set the backend messages are written to.
                 *
                 * @param out A stream to write to. This function doesn't make a
                 * copy, so you are responsible for proper lifetime of the object.
                 **/
                void set_backend(backend_type& out) throw();
    
                /**
                 * @brief Set the backend messages are written to.
                 *
                 * @param file The name of a file messages are sent to.
                 * 
                 * An exception is thrown in case of error, eg. if the file can't
                 * be opened in read-mode. You may NOT use any logging or use
                 * get_backend if that happens, set a new backend before !
                 **/
                void set_backend(char const* file);
    
                /**
                 * @brief Get a reference to the backend in use.
                 *
                 * @return :common::logging::backend_type& The current backend.
                 **/
                backend_type& get_backend() throw();
    
                namespace detail
                {
                    typedef std::mutex mutex_type;
                    typedef std::lock_guard<std::mutex> scoped_lock_type;
    
                    // Retrieve the internally stored mutex.
                    mutex_type& get_mutex() throw();
    
                    // Prints the last value and stops recursion.
                    template<typename Head>
                    void print_out(Head const& head)
                    {
                        get_backend() << head << "\n";
                    }
    
                    // Begin of printer.
                    template<typename Head, typename... Tail>
                    void print_out(backend_type::char_type sep, Head const& head,
                        Tail const&... tail)
                    {
                        get_backend() << head << sep;
                        print_out(sep, tail...);
                    }
                }
    
                /**
                 * @brief The log level.
                 **/
                enum class log_level
                {
                    critical = 1,
                    error = 2,
                    warn = 3,
                    info = 4,
                    debug = 5
                };
    
                /**
                 * @brief Prints the log level to the backend.
                 *
                 * @param lhs The backend to print to.
                 * @param rhs The log level to print.
                 * @return :common::logging::backend_type& lhs
                 **/
                backend_type& operator<<(backend_type& lhs, log_level rhs);
    
                /**
                 * @brief Formatter to print the current time.
                 * See std::strftime for documentation about the format string.
                 **/
                struct current_time
                {
                    char const* format_string;
    
                    inline current_time(char const* format)
                        : format_string(format)
                    { }
                };
    
                /**
                 * @brief Prints the current time to the backend.
                 *
                 * @param lhs The backend to print to.
                 * @param rhs The time format.
                 * @return :common::logging::backend_type& lhs
                 **/
                backend_type& operator<<(backend_type& lhs, current_time rhs);
    
                /**
                 * @brief Formatter to print group names.
                 **/
                struct group_name
                {
                    char const* name;
                    std::size_t name_length;
    
                    template<std::size_t Size>
                    inline group_name(char name[Size])
                        : name(name), name_length(Size)
                    { }
    
                    inline group_name(char const* name)
                        : name(name), name_length(std::strlen(name))
                    { }
                };
    
                /**
                 * @brief Prints a group name to the backend.
                 *
                 * @param lhs The backend to print to.
                 * @param rhs The groupname to print.
                 * @return :common::logging::backend_type& lhs
                 **/
                backend_type& operator<<(backend_type& lhs, group_name const& rhs);
    
                /**
                 * @brief Prints a log message.
                 *
                 * @param sep The seperator between every printed value.
                 * @param values A variadic number of values to print. Every
                 * backend-compatible formatter is allowed.
                 **/
                template<typename... Values>
                void basic_log(backend_type::char_type sep,
                    Values const&... values)
                {
                    detail::scoped_lock_type lock(detail::get_mutex());
                    detail::print_out(sep, values...);
                }
            }
        }
    }
    
    // Default log message implementation.
    #define SYNTHETIC_LOG_DEFAULT(_m__level, ...)                               \
        synthetic::common::logging::basic_log(' ',                              \
            synthetic::common::logging::current_time("%x %X"),                  \
            synthetic::common::logging::log_level::_m__level,                 \
            __VA_ARGS__ )
    
    // Implementation for SYNTHETIC_CRITICAL
    #if SYNTHETIC_LOGLEVEL >= SYNTHETIC_LOGLEVEL_CRITICAL
    #define SYNTHETIC_CRITICAL(...) \
        SYNTHETIC_LOG_DEFAULT(critical, __VA_ARGS__)
    #else
    #define SYNTHETIC_CRITICAL(...)
    #endif
    
    // Implementation for SYNTHETIC_ERROR
    #if SYNTHETIC_LOGLEVEL >= SYNTHETIC_LOGLEVEL_ERROR
    #define SYNTHETIC_ERROR(...) \
        SYNTHETIC_LOG_DEFAULT(error, __VA_ARGS__)
    #else
    #define SYNTHETIC_ERROR(...)
    #endif
    
    // Implementation for SYNTHETIC_WARN
    #if SYNTHETIC_LOGLEVEL >= SYNTHETIC_LOGLEVEL_WARN
    #define SYNTHETIC_WARN(...) \
        SYNTHETIC_LOG_DEFAULT(warn, __VA_ARGS__)
    #else
    #define SYNTHETIC_WARN(...)
    #endif
    
    // Implementation for SYNTHETIC_INFO
    #if SYNTHETIC_LOGLEVEL >= SYNTHETIC_LOGLEVEL_INFO
    #define SYNTHETIC_INFO(...) \
        SYNTHETIC_LOG_DEFAULT(info, __VA_ARGS__)
    #else
    #define SYNTHETIC_INFO(...)
    #endif
    
    // Implementation for SYNTHETIC_DEBUG
    #if SYNTHETIC_LOGLEVEL >= SYNTHETIC_LOGLEVEL_DEBUG
    #define SYNTHETIC_DEBUG(...) \
        SYNTHETIC_LOG_DEFAULT(info, __VA_ARGS__)
    #else
    #define SYNTHETIC_DEBUG(...)
    #endif
    
    #endif // __SYNTHETIC_COMMON_LOG_HPP__
    

Log in to reply