Type: fcf::NTest::Logger::DataFactory
Class: fcf::NTest::Logger::Prefix
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::Prefix combination.
The dataFactory property is a callback function that allows for lazy and dynamic initialization of metadata for a logger target for a given prefix. Instead of providing a static object, you provide a factory that is invoked only when the logger needs to create the data container for a specific output target.
This is particularly useful when:
- The metadata object is expensive to construct and should only be created if the target is actually used.
- The metadata needs to be unique for every different fcf::NTest::Logger::OutputTarget (e.g., different file streams or different console settings).
- The metadata depends on runtime information available only 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_DECLARE("FactoryDemo", "Logger", "DataFactoryTest") {
// Trigger a log message
fcf::NTest::log() << "Hello with dynamic metadata!" << std::endl;
FCF_TEST(true);
}
int main(int a_argc, char* a_argv[]) {
fcf::NTest::Logger::Prefix prefix;
prefix.name = "session-prefix";
prefix.category = fcf::NTest::LMC_USER_GROUP;
// 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});
};
prefix.handler = []( fcf::NTest::Logger&, fcf::NTest::Logger::MessageContext& a_context) {
// Cast the type-erased pointer back to our SessionInfo type
SessionInfo* info = a_context.data->cast<SessionInfo>();
// Check if the data exists in the context
if (info) {
return std::string() + "[Session: " + info->sessionId + "] ";
}
return std::string();
};
// Apply the prefix to the logger
fcf::NTest::logger().appendPrefix(prefix);
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] Hello with dynamic metadata!
[SUCCESS] Test completed successfully (0.000`017`259 sec)
[SUCCESS] All tests were completed.
Tests: 1 passed, 0 failed, 0 skipped, 1 total
Duration: 0.000`017`259 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.