GetLastError custom attribute

35 Views Asked by At

I would like to include GetLastError in each log output but the value is overwritten when boost::log calls another Windows API before the attribute value is queried. Anyone know a nice way around this?

class get_last_error_attribute_impl : public boost::log::attribute::impl {
public:
  boost::log::attribute_value get_value() {
    return boost::log::attributes::make_attribute_value(GetLastError());
  }
};

class get_last_error_attribute : public boost::log::attribute {
public:
  get_last_error_attribute() : 
    boost::log::attribute(new get_last_error_attribute_impl()) {
  }
};

void init_logging() {
  auto core = boost::log::core::get();
  core->add_global_attribute("GetLastError", get_last_error_attribute());

  auto sink = boost::make_shared<
    boost::log::sinks::synchronous_sink<boost::log::sinks::debug_output_backend>>();
  sink->set_formatter(
    boost::log::expressions::stream
    << boost::log::trivial::severity
    << ": " << boost::log::expressions::smessage
    << " (" << boost::log::expressions::attr<DWORD>("GetLastError") << ")"
  );

  core->add_sink(sink);
}

void main() {
  init_logging();

  if (!DeleteFileA("c:\\foo.bar")) {
    BOOST_LOG_TRIVIAL(warning) << "delete failed";
  }
}

Log output:

warning: delete failed (0)

1

There are 1 best solutions below

3
Bevan Collins On

I solved this by using an assert to capture GetLastError instead

#define BOOST_ENABLE_ASSERT_HANDLER 1
#include <boost/assert.hpp>

namespace boost {
  void assertion_failed([[maybe_unused]] char const* expr, [[maybe_unused]] char const* function, char const* file, long line) {
    auto err = GetLastError();
    BOOST_LOG_TRIVIAL(warning) << file << "(" << line << ") [" << err << "] assert failed";
    SetLastError(err);
  }
}

void init_logging() {
  auto sink = boost::make_shared<boost::log::sinks::synchronous_sink<boost::log::sinks::debug_output_backend>>();

  boost::log::core::get()->add_sink(sink);
}

void main() {
  init_logging();

  BOOL rc;
  BOOST_VERIFY(rc = DeleteFileA("c:\\foo.bar"));
  if (!rc) {
    BOOST_LOG_TRIVIAL(warning) << "delete failed";
  }
}