287 lines
7.8 KiB
C++
287 lines
7.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "CoreTypes.h"
|
|
|
|
#include "Trace/Trace.h" // TraceLog, for UE::Trace::FEventRef8
|
|
|
|
#include "Io.h"
|
|
|
|
namespace UE
|
|
{
|
|
namespace TraceAnalyzer
|
|
{
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class FTextSerializer
|
|
{
|
|
public:
|
|
FTextSerializer();
|
|
virtual ~FTextSerializer();
|
|
|
|
virtual void AppendChar(const ANSICHAR Value) = 0;
|
|
virtual void Append(const ANSICHAR* Text, int32 Len) = 0;
|
|
virtual void Append(const ANSICHAR* Text) = 0;
|
|
virtual void Appendf(const char* Format, ...) = 0;
|
|
virtual bool Commit() = 0;
|
|
|
|
//////////////////////////////////////////////////
|
|
// Attributes
|
|
|
|
void BeginAttributeSet()
|
|
{
|
|
AttributeCount = 0;
|
|
}
|
|
|
|
void BeginAttribute()
|
|
{
|
|
if (AttributeCount == 0)
|
|
{
|
|
AppendChar('\t');
|
|
}
|
|
else
|
|
{
|
|
AppendChar(' ');
|
|
}
|
|
++AttributeCount;
|
|
}
|
|
|
|
void EndAttribute()
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
// NEW_EVENT
|
|
|
|
void BeginNewEventHeader()
|
|
{
|
|
BeginAttributeSet();
|
|
if (bWriteEventHeader)
|
|
{
|
|
#if !UE_TRACE_ANALYSIS_DEBUG
|
|
// Add an empty line before a NEW_EVENT (if previous was an EVENT) to make it more visible.
|
|
if (!bLastWasNewEvent)
|
|
{
|
|
AppendChar('\n');
|
|
}
|
|
#endif
|
|
bLastWasNewEvent = true;
|
|
BeginAttribute();
|
|
Append("NEW_EVENT :");
|
|
EndAttribute();
|
|
}
|
|
}
|
|
void EndNewEventHeader()
|
|
{
|
|
if (AttributeCount > 0)
|
|
{
|
|
AppendChar('\n');
|
|
}
|
|
}
|
|
|
|
void BeginNewEventFields()
|
|
{
|
|
}
|
|
void BeginField()
|
|
{
|
|
BeginAttributeSet();
|
|
if (bWriteEventHeader)
|
|
{
|
|
AppendChar('\t');
|
|
}
|
|
BeginAttribute();
|
|
Append("FIELD :");
|
|
EndAttribute();
|
|
}
|
|
void EndField()
|
|
{
|
|
AppendChar('\n');
|
|
}
|
|
void EndNewEventFields()
|
|
{
|
|
// Add an extra empty line make each NEW_EVENT more visible.
|
|
AppendChar('\n');
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
// EVENT
|
|
|
|
bool IsWriteEventHeaderEnabled() const { return bWriteEventHeader; }
|
|
|
|
void BeginEvent(uint32 CtxThreadId)
|
|
{
|
|
BeginAttributeSet();
|
|
if (bWriteEventHeader)
|
|
{
|
|
bLastWasNewEvent = false;
|
|
BeginAttribute();
|
|
if (CtxThreadId != (uint32)-1)
|
|
{
|
|
Appendf("EVENT [%u]", CtxThreadId);
|
|
}
|
|
else
|
|
{
|
|
Append("EVENT");
|
|
}
|
|
EndAttribute();
|
|
}
|
|
}
|
|
|
|
void WriteEventName(const char* LoggerName, const char* Name)
|
|
{
|
|
if (bWriteEventHeader)
|
|
{
|
|
BeginAttribute();
|
|
Appendf("%s.%s :", LoggerName, Name);
|
|
EndAttribute();
|
|
}
|
|
}
|
|
|
|
void EndEvent()
|
|
{
|
|
if (AttributeCount > 0)
|
|
{
|
|
AppendChar('\n');
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
// Array: [1 2 3...]
|
|
|
|
void BeginArray()
|
|
{
|
|
AppendChar('[');
|
|
}
|
|
|
|
void NextArrayElement()
|
|
{
|
|
AppendChar(' ');
|
|
}
|
|
|
|
void EndArray()
|
|
{
|
|
AppendChar(']');
|
|
}
|
|
|
|
//////////////////////////////////////////////////
|
|
// Values
|
|
|
|
void WriteValueString(const char* Value)
|
|
{
|
|
AppendChar('\"');
|
|
Append(Value);
|
|
AppendChar('\"');
|
|
}
|
|
void WriteValueString(const char* Value, uint32 Len)
|
|
{
|
|
AppendChar('\"');
|
|
Append(Value, Len);
|
|
AppendChar('\"');
|
|
}
|
|
|
|
void WriteValueReference(const UE::Trace::FEventRef8& Value) { Appendf("R(%u,%u)", Value.RefTypeId, uint32(Value.Id)); }
|
|
void WriteValueReference(const UE::Trace::FEventRef16& Value) { Appendf("R(%u,%u)", Value.RefTypeId, uint32(Value.Id)); }
|
|
void WriteValueReference(const UE::Trace::FEventRef32& Value) { Appendf("R(%u,%u)", Value.RefTypeId, Value.Id); }
|
|
void WriteValueReference(const UE::Trace::FEventRef64& Value) { Appendf("R(%u,%llu)", Value.RefTypeId, Value.Id); }
|
|
|
|
void WriteValueBool(bool Value) { Append(Value ? "true" : "false"); }
|
|
|
|
void WriteValueInt8(int8 Value) { Appendf("%i", int32(Value)); }
|
|
void WriteValueInt16(int16 Value) { Appendf("%i", int32(Value)); }
|
|
void WriteValueInt32(int32 Value) { Appendf("%i", Value); }
|
|
void WriteValueInt64(int64 Value) { Appendf("%lli", Value); }
|
|
|
|
void WriteValueUInt8(uint8 Value) { Appendf("%u", uint32(Value)); }
|
|
void WriteValueUInt16(uint16 Value) { Appendf("%u", uint32(Value)); }
|
|
void WriteValueUInt32(uint32 Value) { Appendf("%u", Value); }
|
|
void WriteValueUInt64(uint64 Value) { Appendf("%llu", Value); }
|
|
|
|
void WriteValueHex8(uint8 Value) { Appendf("0x%X", uint32(Value)); }
|
|
void WriteValueHex16(uint16 Value) { Appendf("0x%X", uint32(Value)); }
|
|
void WriteValueHex32(uint32 Value) { Appendf("0x%X", Value); }
|
|
void WriteValueHex64(uint64 Value) { Appendf("0x%llX", Value); }
|
|
|
|
void WriteValueInt64Auto(int64 Value);
|
|
void WriteValueUInt64Auto(uint64 Value);
|
|
|
|
void WriteValueFloat(float Value) { Appendf("%f", Value); }
|
|
void WriteValueDouble(double Value) { Appendf("%f", Value); }
|
|
|
|
void WriteValueTime(double Time) { Appendf("%f", Time); }
|
|
void WriteValueNull() { Append("null"); }
|
|
|
|
void WriteValueBinary(const void* Data, uint32 Size);
|
|
|
|
//////////////////////////////////////////////////
|
|
// Key and Values
|
|
|
|
void WriteKey(const ANSICHAR* Name)
|
|
{
|
|
Append(Name);
|
|
AppendChar('=');
|
|
}
|
|
|
|
void WriteAttributeString(const ANSICHAR* Name, const ANSICHAR* Value) { BeginAttribute(); WriteKey(Name); WriteValueString(Value); EndAttribute(); }
|
|
void WriteAttributeString(const ANSICHAR* Name, const ANSICHAR* Value, uint32 Len) { BeginAttribute(); WriteKey(Name); WriteValueString(Value, Len); EndAttribute(); }
|
|
void WriteAttributeBool(const ANSICHAR* Name, bool Value) { BeginAttribute(); WriteKey(Name); WriteValueBool(Value); EndAttribute(); }
|
|
void WriteAttributeInteger(const ANSICHAR* Name, int64 Value) { BeginAttribute(); WriteKey(Name); WriteValueInt64(Value); EndAttribute(); }
|
|
void WriteAttributeIntegerHex(const ANSICHAR* Name, int64 Value) { BeginAttribute(); WriteKey(Name); WriteValueHex64(uint64(Value)); EndAttribute(); }
|
|
void WriteAttributeFloat(const ANSICHAR* Name, float Value) { BeginAttribute(); WriteKey(Name); WriteValueFloat(Value); EndAttribute(); }
|
|
void WriteAttributeDouble(const ANSICHAR* Name, double Value) { BeginAttribute(); WriteKey(Name); WriteValueDouble(Value); EndAttribute(); }
|
|
void WriteAttributeNull(const ANSICHAR* Name) { BeginAttribute(); WriteKey(Name); WriteValueNull(); EndAttribute(); }
|
|
void WriteAttributeBinary(const ANSICHAR* Name, const void* Data, uint32 Size) { BeginAttribute(); WriteKey(Name); WriteValueBinary(Data, Size); EndAttribute(); }
|
|
|
|
protected:
|
|
bool bWriteEventHeader = true;
|
|
bool bLastWasNewEvent = false;
|
|
uint32 AttributeCount = 0;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class FStdoutTextSerializer : public FTextSerializer
|
|
{
|
|
public:
|
|
FStdoutTextSerializer();
|
|
virtual ~FStdoutTextSerializer() {}
|
|
|
|
virtual void AppendChar(const ANSICHAR Value) override;
|
|
virtual void Append(const ANSICHAR* Text, int32 Len) override;
|
|
virtual void Append(const ANSICHAR* Text) override;
|
|
virtual void Appendf(const char* Format, ...) override;
|
|
virtual bool Commit() override;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
class FFileTextSerializer : public FTextSerializer
|
|
{
|
|
public:
|
|
FFileTextSerializer(FileHandle InHandle);
|
|
virtual ~FFileTextSerializer();
|
|
|
|
virtual void AppendChar(const ANSICHAR Value) override;
|
|
virtual void Append(const ANSICHAR* Text, int32 Len) override;
|
|
virtual void Append(const ANSICHAR* Text) override;
|
|
virtual void Appendf(const char* Format, ...) override;
|
|
virtual bool Commit() override;
|
|
|
|
private:
|
|
void* GetPointer(uint32 RequiredSize);
|
|
|
|
private:
|
|
FileHandle Handle = -1;
|
|
static constexpr int BufferSize = 1024 * 1024;
|
|
void* Buffer = nullptr;
|
|
static constexpr int FormatBufferSize = 64 * 1024;
|
|
void* FormatBuffer = nullptr;
|
|
uint32 Used = 0;
|
|
};
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
} // namespace TraceAnalyzer
|
|
} // namespace UE
|