1

I am trying to log basic information in a text file while performing testing with google test. My ultimate goal is to log the trace of an exception.

In the project I am using C++11, the latest version of Google tests added to the project through CMake and spdlog as header-only (added to project inside libs).

For some reason, the logger is not writing to file, even after trying to force the flush. I've tried different "quickstart" from the internet but nothing is working for me. I don't believe it could be an issue, but one hypothesis is that you can't write to a file within the context of a test. The structure of the project is the following:

.
|
├── build
├── cmake
├── libs
|   ├── ...
|   └── spdlog (*)
├── src
|   ├── ...
|   ├── main.cpp
|   └── CMakeLists.txt
├── test
|   ├── ...
|   ├── CMakeLists.txt
|   └── core
|       └── logging
|           ├── log
|           |   └── logger.txt
|           └── logging_test.cpp
├── ...
└── CMakeLists.txt 

(*) files inside the directory are the ones inside spdlog/include/spdlog https://github.com/gabime/spdlog/tree/v1.x/include/spdlog

And this is the code within the test class logging_test.cpp. After running the test check_exception_thrown_equal nothing has been written to logger.txt. What could be the issue?

#include <exception>
#include "gtest/gtest.h"
#include <spdlog/spdlog.h>
#include <spdlog/sinks/basic_file_sink.h>


class LoggingTest: public testing::Test {

 protected:
  std::shared_ptr<spdlog::logger> logger;

  struct ExceptionTemplate : std::exception {
    const char* what() { return "ExceptionTemplate triggered!"; }
  };

 // create logger 
 void create_logger() {
   // Create basic file logger (not rotated)
   logger = spdlog::basic_logger_mt("logger", "log/logger.txt");
 }

  // setup logger configurations 
  void set_up() {
    logger->set_level(spdlog::level::info);
    logger->flush_on(spdlog::level::info);
    logger->info("Debug logger setup done. \n");
  }

  // critical method that generates and returns my exception of type ExceptionTemplate
  ExceptionTemplate exception_generator() {
    try {

      ///////////////////////////////
      // call to critical method here
      ///////////////////////////////

      throw ExceptionTemplate();
    }
    catch (ExceptionTemplate &e) {
      log_exception(e);
      return e;
    }
  }

  // write to logger 
  void log_exception(ExceptionTemplate e) {
    try {

      LoggingTest::create_logger();
      LoggingTest::set_up();

      logger->info("Exception raised! {}", e.what());
    }
    catch (const spdlog::spdlog_ex &ex) {
      std::cout << "Log initialization failed: " << ex.what() << std::endl;
    }
  }
};


TEST_F(LoggingTest, check_exception_thrown_equal) {
  ASSERT_STREQ(LoggingTest::exception_generator().what(), "ExceptionTemplate triggered!");
}
Mattia Strocchi
  • 25
  • 1
  • 1
  • 5

1 Answers1

3

Try using a simpler setup, you don't need all of the "helper" functions and such, or the exception-related stuff at first. Just log a message when your class' constructor is called.

class LoggingTest {
  LoggingTest() {
    auto logger = spdlog::basic_logger_mt("test_logger", "logs/test.txt");
    spdlog::set_default_logger(logger);
    spdlog::flush_on(spdlog::level::info);

    spdlog::get("test_logger")->info("LoggingTest::ctor");
  }
}

Then just create an instance of that class in your main (or anywhere else). Make sure the directory exists and is writable (although this usu. results in an error, not a silent failure).

Dan1701
  • 447
  • 5
  • 14
  • Mine just throws exception for not finding file though. No such file or directory. Shouldn't spdlog create the file on its own? – John Demetriou Jun 03 '20 at 08:02
  • 1
    It will create the log file, but not any directories. So if specifying `logs/test.txt` as the path, you'll have to ensure that `logs/` exists. – Dan1701 Jun 03 '20 at 15:28
  • as it turns out My issue was multiple issues. Wstring and string when defining the logger, relative path not existing, folder not existing, etc – John Demetriou Jun 04 '20 at 11:27