142 lines
4.1 KiB
C++
142 lines
4.1 KiB
C++
|
#include "RiderLogging.hpp"
|
||
|
|
||
|
#include "BlueprintProvider.hpp"
|
||
|
#include "IRiderLink.hpp"
|
||
|
#include "Model/Library/UE4Library/LogMessageInfo.Pregenerated.h"
|
||
|
#include "Model/Library/UE4Library/StringRange.Pregenerated.h"
|
||
|
#include "Model/Library/UE4Library/UnrealLogEvent.Pregenerated.h"
|
||
|
|
||
|
#include "Internationalization/Regex.h"
|
||
|
#include "Misc/DateTime.h"
|
||
|
#include "Modules/ModuleManager.h"
|
||
|
|
||
|
#define LOCTEXT_NAMESPACE "RiderLogging"
|
||
|
|
||
|
DEFINE_LOG_CATEGORY(FLogRiderLoggingModule);
|
||
|
|
||
|
IMPLEMENT_MODULE(FRiderLoggingModule, RiderLogging);
|
||
|
|
||
|
namespace LoggingExtensionImpl
|
||
|
{
|
||
|
static TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetPathRanges(
|
||
|
const FRegexPattern& Pattern,
|
||
|
const FString& Str)
|
||
|
{
|
||
|
using JetBrains::EditorPlugin::StringRange;
|
||
|
FRegexMatcher Matcher(Pattern, Str);
|
||
|
TArray<rd::Wrapper<StringRange>> Ranges;
|
||
|
while (Matcher.FindNext())
|
||
|
{
|
||
|
const int Start = Matcher.GetMatchBeginning();
|
||
|
const int End = Matcher.GetMatchEnding();
|
||
|
FString PathName = Str.Mid(Start, End - Start);
|
||
|
if (BluePrintProvider::IsBlueprint(PathName))
|
||
|
Ranges.Emplace(StringRange(Start, End));
|
||
|
}
|
||
|
return Ranges;
|
||
|
}
|
||
|
|
||
|
static TArray<rd::Wrapper<JetBrains::EditorPlugin::StringRange>> GetMethodRanges(
|
||
|
const FRegexPattern& Pattern,
|
||
|
const FString& Str)
|
||
|
{
|
||
|
using JetBrains::EditorPlugin::StringRange;
|
||
|
FRegexMatcher Matcher(Pattern, Str);
|
||
|
TArray<rd::Wrapper<StringRange>> Ranges;
|
||
|
while (Matcher.FindNext())
|
||
|
{
|
||
|
Ranges.Emplace(StringRange(Matcher.GetMatchBeginning(), Matcher.GetMatchEnding()));
|
||
|
}
|
||
|
return Ranges;
|
||
|
}
|
||
|
|
||
|
static bool SendMessageToRider(const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo, const FString& Message)
|
||
|
{
|
||
|
static const FRegexPattern PathPattern = FRegexPattern(TEXT("(/[\\w\\.]+)+"));
|
||
|
static const FRegexPattern MethodPattern = FRegexPattern(TEXT("[0-9a-z_A-Z]+::~?[0-9a-z_A-Z]+"));
|
||
|
|
||
|
return IRiderLinkModule::Get().FireAsyncAction(
|
||
|
[&MessageInfo, &Message] (JetBrains::EditorPlugin::RdEditorModel const& RdEditorModel)
|
||
|
{
|
||
|
rd::ISignal<JetBrains::EditorPlugin::UnrealLogEvent> const& UnrealLog = RdEditorModel.get_unrealLog();
|
||
|
UnrealLog.fire({
|
||
|
MessageInfo,
|
||
|
Message,
|
||
|
GetPathRanges(PathPattern, Message),
|
||
|
GetMethodRanges(MethodPattern, Message)
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
void SendMessageInChunks(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)
|
||
|
{
|
||
|
static int NUMBER_OF_CHUNKS = 1024;
|
||
|
while (!Msg->IsEmpty())
|
||
|
{
|
||
|
SendMessageToRider(MessageInfo, Msg->Left(NUMBER_OF_CHUNKS));
|
||
|
*Msg = Msg->RightChop(NUMBER_OF_CHUNKS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ScheduledSendMessage(FString* Msg, const JetBrains::EditorPlugin::LogMessageInfo& MessageInfo)
|
||
|
{
|
||
|
FString ToSend;
|
||
|
while (Msg->Split("\n", &ToSend, Msg))
|
||
|
{
|
||
|
SendMessageInChunks(&ToSend, MessageInfo);
|
||
|
}
|
||
|
|
||
|
SendMessageInChunks(Msg, MessageInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void FRiderLoggingModule::StartupModule()
|
||
|
{
|
||
|
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("STARTUP START"));
|
||
|
|
||
|
static const auto START_TIME = FDateTime::UtcNow().ToUnixTimestamp();
|
||
|
static const auto GetTimeNow = [](double Time) -> rd::DateTime
|
||
|
{
|
||
|
return rd::DateTime(START_TIME + static_cast<int64>(Time));
|
||
|
};
|
||
|
|
||
|
ModuleLifetimeDef = IRiderLinkModule::Get().CreateNestedLifetimeDefinition();
|
||
|
LoggingScheduler = MakeUnique<rd::SingleThreadScheduler>(ModuleLifetimeDef.lifetime, "LoggingScheduler");
|
||
|
ModuleLifetimeDef.lifetime->bracket(
|
||
|
[this]()
|
||
|
{
|
||
|
OutputDevice.Setup([this](const TCHAR* msg, ELogVerbosity::Type Type, const FName& Name, TOptional<double> Time)
|
||
|
{
|
||
|
if (Type > ELogVerbosity::All) return;
|
||
|
|
||
|
rd::optional<rd::DateTime> DateTime;
|
||
|
if (Time)
|
||
|
{
|
||
|
DateTime = GetTimeNow(Time.GetValue());
|
||
|
}
|
||
|
const FString PlainName = Name.GetPlainNameString();
|
||
|
const JetBrains::EditorPlugin::LogMessageInfo MessageInfo{Type, PlainName, DateTime};
|
||
|
|
||
|
LoggingScheduler->queue([Msg = FString(msg), MessageInfo]() mutable
|
||
|
{
|
||
|
LoggingExtensionImpl::ScheduledSendMessage(&Msg, MessageInfo);
|
||
|
});
|
||
|
});
|
||
|
},
|
||
|
[this]()
|
||
|
{
|
||
|
OutputDevice.TearDown();
|
||
|
});
|
||
|
|
||
|
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("STARTUP FINISH"));
|
||
|
}
|
||
|
|
||
|
void FRiderLoggingModule::ShutdownModule()
|
||
|
{
|
||
|
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("SHUTDOWN START"));
|
||
|
ModuleLifetimeDef.terminate();
|
||
|
UE_LOG(FLogRiderLoggingModule, Verbose, TEXT("SHUTDOWN FINISH"));
|
||
|
}
|
||
|
|
||
|
#undef LOCTEXT_NAMESPACE
|