2

I feel like a fool asking this, as it is about as trivial example as I can think of, but it's holding me up.

I've implemented a very basic console-and-file logger:

    auto logger = spdlog::basic_logger_mt("console and file logger", filepath);
#ifdef NDEBUG
    spdlog::set_level(spdlog::level::info); // Set global log level to info
#else
    spdlog::set_level(spdlog::level::trace); // Set global log level to everything
#endif
    spdlog::set_pattern("%^%l: %v%$");    // see https://github.com/gabime/spdlog/wiki/3.-Custom-formatting
    spdlog::flush_on(spdlog::level::info);

This writes to the console perfectly in colours, but although it creates the log file, it never writes to it.

I want to try flushing it manually, but there is no spdlog::flush.

I had originally implemented this with two sinks (one console, one file), and had a similar problem: except in that case it would write the first (and only first) message to the log file, so long as it was an error.

I'm sorry for asking such a noddy question...

------------------------------ EDIT ---------------------------------------

Attempt 1 (from multi-sink example):

    // Creating console logger --------------------
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();

    // Creating file logger -----------------------
    auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filepath);

    // Creating multi-logger ----------------------
    spdlog::logger logger("console and file", { console_sink, file_sink });
    spdlog::flush_on(spdlog::level::info);

Result: log file is created, console logging is great, but file remains determinedly empty.

Attempt 2 (from basic example):

    // Creating the logger ------------------------
    auto logger = spdlog::basic_logger_mt("console and $ME file", filepath);
    spdlog::set_level(spdlog::level::trace); // Set global log level to everything
    spdlog::flush_on(spdlog::level::info);

Result: the same

The only time I seem to have got further is when I set the log level to "error", and then if the very next log is an error, it appears in the file. No other message appears in the file.

I have also been unable to find the manual flush. I've tried using the example:

spdlog::apply_all([&](std::shared_ptr<spdlog::logger> l) {l->flush(); });

but this doesn't appear to do anything...

Mike Sadler
  • 1,750
  • 1
  • 20
  • 37
  • 1
    Please provide a a complete reproducable example – GabiMe Nov 24 '18 at 11:10
  • try using the loggers methods instead of spdlog’s. or alternitavly, register the logger using spdlog:register_logger(logger). – GabiMe Dec 03 '18 at 10:01
  • @GabiMe - I then get an error from throw spdlog_ex("logger with name '" + logger_name + "' already exists"); – Mike Sadler Dec 04 '18 at 10:06
  • You need to call it only once per logger's name – GabiMe Dec 04 '18 at 10:32
  • It appears that the spdlog::basic_logger_mt has automatically registered the logger (which is good), so that you don't need to do the register_logger step. This fits with the rest of the behaviour (because it logs to console as expected). – Mike Sadler Dec 04 '18 at 11:39

1 Answers1

8

OK, after going through the spdlog code line-by-line, I've found the source of unexpected behaviour.

I've been using the

spdlog::error(message);

and related functions to do the logging, as these don't require creating any singletons or anything.

Looking at the code, these functions always use the default logger, and the method spdlog:register_logger does not set the default logger (I don't know what it does).

If you use the following code instead:

spdlog::set_default_logger(logger);

It seems to work OK.

Mike Sadler
  • 1,750
  • 1
  • 20
  • 37