FCF 2.0 development in progress...
> > > > > > > >
[News] [C++ Libraries API] [C++ Downloads] [Donate to the project] [Contacts]

dataFactory from class fcf::NTest::Logger::Format

Property: dataFactory

Type: fcf::NTest::Logger::DataFactory

Class: fcf::NTest::Logger::Format

Package: fcfTest

File: test.hpp

Available from version: 1.2.1

A factory function used to initialize and provide a unique fcf::NTest::SharedPtrAny data object for a specific fcf::NTest::Logger::OutputTarget and fcf::NTest::Logger::Format combination.

The dataFactory property is a callback function that enables lazy and dynamic initialization of metadata for a logger target. Instead of providing a pre-constructed object, you provide a factory that is invoked only when the logger needs to create the data container for a specific fcf::NTest::Logger::OutputTarget and fcf::NTest::Logger::Format pair.

This mechanism is highly efficient and flexible, making it ideal for scenarios where:

  • The metadata object is resource-intensive to construct and should only be created if the specific output target is actually used.
  • The metadata must be unique for every distinct fcf::NTest::Logger::OutputTarget (e.g., different file streams or different console configurations).
  • The metadata depends on runtime information that is only available during the logger's initialization phase.

Example: Dynamic Metadata Initialization via Data Factory

Demonstrating how to use the dataFactory to inject a custom object into the logger's context, which is then retrieved by a custom formatter.

#define FCF_TEST_IMPLEMENTATION #include <fcfTest/test.hpp> #include <iostream> #include <string> // Define a custom structure that we want to attach to the logger context struct SessionInfo { std::string sessionId; int userLevel; }; FCF_TEST_DEFINE("FactoryDemo", "Logger", "DataFactoryTest") { // Trigger a log message to initiate the formatting process fcf::NTest::log() << "Hello with dynamic metadata!" << std::endl; FCF_TEST(true); } int main(int a_argc, char* a_argv[]) { // Define a custom prefix that retrieves the data from the context fcf::NTest::Logger::Prefix prefix; prefix.name = "session-prefix"; prefix.category = fcf::NTest::LMC_USER_GROUP; prefix.handler = []( fcf::NTest::Logger&, fcf::NTest::Logger::MessageContext& a_context) { // Cast the type-erased pointer back to our known type SessionInfo* info = a_context.data->cast<SessionInfo>(); // Check if the data exists in the context if (info) { return std::string() + "[Session: " + info->sessionId + " (Level: " + std::to_string(info->userLevel) + ")] "; } return std::string(); }; // Use the dataFactory to create the object on demand prefix.dataFactory = []( fcf::NTest::Logger&, fcf::NTest::Logger::OutputTarget&) { // This lambda is called when the logger first encounters this format for a target return fcf::NTest::SharedPtrAny::make<SessionInfo>(SessionInfo{"ABC-123", 5}); }; // Apply the prefix to the logger fcf::NTest::logger().appendPrefix(prefix); // Run the tests bool error = false; fcf::NTest::cmdRun(a_argc, a_argv, fcf::NTest::CRM_RUN, &error); return error ? 1 : 0; }

Output:

Performing the test: "FactoryDemo" -> "Logger" -> "DataFactoryTest" ... > [Session: ABC-123 (Level: 5)] Hello with dynamic metadata! [SUCCESS] Test completed successfully (0.000`016`464 sec) [SUCCESS] All tests were completed. Tests: 1 passed, 0 failed, 0 skipped, 1 total Duration: 0.000`016`464 sec

The dataFactory allowed us to inject a SessionInfo object into the logging pipeline without manually managing its lifecycle for every single log call. The logger handled the creation and destruction of the object via the fcf::NTest::SharedPtrAny mechanism.