Download

UE_LOG with format as variable

All I want to do is pass a variable into the 3rd parameter of UE_LOG. No matter what I do, whether I pass an FString, const char*, or even a TCHAR*, it still complains.


UE_LOG(LogTemp, Warning, ???, FString(TEXT("text here")));

Logging | UE4 Community Wiki

If you read the documentation yourself, you’d see that it doesn’t answer my question.

My macro skills are weak. Passing a macro into a macro where the TEXT macro is putting an L in front of the “xxx” to make a unicode TCHAR array.


 /**
* A macro that outputs a formatted message to log if a given logging category is active at a given verbosity level
* @param CategoryName name of the logging category
* @param Verbosity, verbosity level to test against
* @param Format, format text
***/
#define UE_LOG(CategoryName, Verbosity, Format, ...) \
{ \
static_assert(TIsArrayOrRefOfType<decltype(Format), TCHAR>::Value, "Formatting string must be a TCHAR array."); \
static_assert((ELogVerbosity::Verbosity & ELogVerbosity::VerbosityMask) < ELogVerbosity::NumVerbosity && ELogVerbosity::Verbosity > 0, "Verbosity must be constant and in range."); \
CA_CONSTANT_IF((ELogVerbosity::Verbosity & ELogVerbosity::VerbosityMask) <= ELogVerbosity::COMPILED_IN_MINIMUM_VERBOSITY && (ELogVerbosity::Warning & ELogVerbosity::VerbosityMask) <= FLogCategory##CategoryName::CompileTimeVerbosity) \
{ \
UE_LOG_EXPAND_IS_FATAL(Verbosity, PREPROCESSOR_NOTHING, if (!CategoryName.IsSuppressed(ELogVerbosity::Verbosity))) \
{ \
auto UE_LOG_noinline_lambda = ](const auto& LCategoryName, const auto& LFormat, const auto&... UE_LOG_Args) FORCENOINLINE \
{ \
TRACE_LOG_MESSAGE(LCategoryName, Verbosity, LFormat, UE_LOG_Args...) \
UE_LOG_EXPAND_IS_FATAL(Verbosity, \
{ \
FMsg::Logf_Internal(UE_LOG_SOURCE_FILE(__FILE__), __LINE__, LCategoryName.GetCategoryName(), ELogVerbosity::Verbosity, LFormat, UE_LOG_Args...); \
_DebugBreakAndPromptForRemote(); \
FDebug::ProcessFatalError(); \
}, \
{ \
FMsg::Logf_Internal(nullptr, 0, LCategoryName.GetCategoryName(), ELogVerbosity::Verbosity, LFormat, UE_LOG_Args...); \
} \
) \
}; \
UE_LOG_noinline_lambda(CategoryName, Format, ##__VA_ARGS__); \
UE_LOG_EXPAND_IS_FATAL(Verbosity, CA_ASSUME(false);, PREPROCESSOR_NOTHING) \
} \
} \
}

We use the following. The project is called “Sandbox”.

Put this in your ProjectName.h file:



// custom log category
DECLARE_LOG_CATEGORY_EXTERN(Sandbox, Log, All);

// custom log macro
#define LOG(x, ...) UE_LOG(Sandbox, Log, TEXT(x), __VA_ARGS__)
#define LOG_WARNING(x, ...) UE_LOG(Sandbox, Warning, TEXT(x), __VA_ARGS__)
#define LOG_ERROR(x, ...) UE_LOG(Sandbox, Error, TEXT(x), __VA_ARGS__)


Put this in your ProjectName.cpp file:



// custom log category
DEFINE_LOG_CATEGORY(Sandbox);


Now you can log like this:



// simple text
LOG("Some stuff to put in the log");

// errors and warnings
LOG_WARNING("something bad happened!");
LOG_ERROR("something really bad happened!");

// log an fstring
LOG("AGameMode::ProcessLoadMapRequest(): %s", *requestedMapName);

// log int
LOG("AGameMode:: player %i has logged out!", playerId);

// log bool
bool myBool = false;
LOG("T or F? %s", *FString(myBool ? "True" : "False"));

// log multiple fstrings
FString cameraPos = cameraViewInfo.Location.ToString();
FString boomPos = _cameraBoom->GetComponentLocation().ToString();
LOG("AInteractiveCamera:: Camera:%s Boom:%s", *cameraPos, *boomPos);


This is about the simplest logging I’ve seen. If anyone knows of anything even more convenient please let us know. :wink: