Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macro expansion which converts Google Logger print format(i.e. <<) to spdlog print format #1804

Closed
MaximAxelrod opened this issue Jan 17, 2021 · 10 comments

Comments

@MaximAxelrod
Copy link

I have tons of code which uses Google Logger style of log printing:
LOG(ERROR) << "AAAA" <<< 123;

And currently I need to replace Google logger by spdlog logger, which supports python like format:
logger->error("{} {}", "param1", 123);

Of course I don't want to change each log line in the code. What I am trying to do, is to rewrite LOG(severity) macro definition. The original macro implementation is:
#define LOG(severity) COMPACT_GOOGLE_LOG_ ## severity.stream()

Can you please recommend me how should I implement the macro? My idea was that the original arguments that were passed to LOG(ERROR) (i.e. << "AAAA" <<< 123) should be printed to a string buffer(str_buffer), and the string buffer will be printed to the destination spdlog logger instance like this: logger->error("{}", str_buffer.c_str());

What is the best idea for doing this? Thanks so much!!!

@artemyv
Copy link

artemyv commented Jan 18, 2021

I did it like this

#define SPDLOG_LOGGER_STREAM(log, lvl)                                                                   \
    log && log->should_log(lvl) &&                                                                       \
        LogStream(log, lvl, spdlog::source_loc{__FILE__, __LINE__, SPDLOG_FUNCTION}) == \
            LogLine()

LogLine class implements operator<< and stores everything on the right into internal stringstream bugger
LogStream class implements operator==(const LogLine& line) which retrieves the content of LogLine internal buffer and outputs it to logger

@artemyv
Copy link

artemyv commented Jan 18, 2021

Here is the very basic demo of the approach https://github.com/artemyv/cmake_spdlog_example/tree/main/src

@MaximAxelrod
Copy link
Author

Than you very much

@tangm421
Copy link

tangm421 commented Nov 2, 2021

Here is the very basic demo of the approach https://github.com/artemyv/cmake_spdlog_example/tree/main/src

👍 excellent way. Unfortunately, streaming output like std::endl cannot be supported

@gabime
Copy link
Owner

gabime commented Nov 2, 2021

Also, I would replace the shared_ptr with regular pointer to logger for better performance since it get copied/destroyed in macro each call.

@tangm421
Copy link

tangm421 commented Dec 9, 2022

Here is the very basic demo of the approach https://github.com/artemyv/cmake_spdlog_example/tree/main/src

Not sure if this way is thread safe

@artemyv
Copy link

artemyv commented Dec 11, 2022

LogStream variable instance is created locally inside the function - so you should not have any threading issues with it

@gabime
Copy link
Owner

gabime commented Dec 11, 2022

I thinks the line

 m_log->log(m_loc, m_lvl, "{}", line.str());  

can be optimized to

  m_log->log(m_loc, m_lvl, line.str());  // skip formatting by logging the string directly

bachittle pushed a commit to bachittle/spdlog that referenced this issue Dec 22, 2022
@BullyWiiPlaza
Copy link

It seems like the provided code only compiles using gcc and not on MSVC. The following code is more straight-forward for providing streaming functionality and it compiles on both compilers:

#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/spdlog.h>
#include <sstream>

class streamable_logger_t {
    spdlog::level::level_enum log_level_;
    std::ostringstream log_stream_;

public:
    explicit streamable_logger_t(const spdlog::level::level_enum log_level)
        : log_level_(log_level) {
	    
    }

    template <typename T>
    streamable_logger_t& operator<<(const T& value) {
        log_stream_ << value;
        return *this;
    }

    ~streamable_logger_t() {
        spdlog::log(log_level_, "{}", log_stream_.str());
    }
};

/* Might cause macro redefinition errors, you can comment them out if needed */
// #define INFO info
// #define WARNING warn
// #define ERROR err

// loguru
#define LOG_S(log_level) streamable_logger_t(spdlog::level::log_level)

// glog
#define LOG(log_level) LOG_S(log_level)

int main() {
    set_default_logger(spdlog::stdout_color_mt("console"));

    LOG_S(info) << "This is an info message: " << 42;
    LOG_S(err) << "This is an error message.";

    LOG(info) << "This is an info message: " << 42;
    LOG(err) << "This is an error message.";

    return EXIT_SUCCESS;
}

Maybe someone will find it useful.

@gabime
Copy link
Owner

gabime commented Aug 31, 2023

Thanks @BullyWiiPlaza. This is indeed useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants