UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
LogScope.inl
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Trace/Config.h"
6
7#if TRACE_PRIVATE_MINIMAL_ENABLED
8
9#include "Atomic.h"
10#include "EventNode.h"
11#include "HAL/Platform.h" // for PLATFORM_BREAK
12#include "LogScope.h"
13#include "Protocol.h"
14#include "Writer.inl"
15#include "AutoRTFM.h"
16
17namespace UE {
18namespace Trace {
19namespace Private {
20
23extern TRACELOG_API uint32 volatile GLogSerial;
24
27inline void FLogScope::Commit() const
28{
29 AtomicStoreRelease((uint8**) &(Buffer->Committed), Buffer->Cursor);
30}
31
34inline void FLogScope::Commit(FWriteBuffer* __restrict LatestBuffer) const
35{
36 if (LatestBuffer != Buffer)
37 {
38 AtomicStoreRelease((uint8**) &(LatestBuffer->Committed), LatestBuffer->Cursor);
39 }
40
41 Commit();
42}
43
45template <uint32 Flags>
47inline auto FLogScope::EnterImpl(uint32 Uid, uint32 Size)
48{
49 TLogScope<(Flags & FEventInfo::Flag_MaybeHasAux) != 0> Ret;
50 if ((Flags & FEventInfo::Flag_NoSync) != 0)
51 {
52 Ret.EnterNoSync(Uid, Size);
53 }
54 else
55 {
56 Ret.Enter(Uid, Size);
57 }
58 return Ret;
59}
60
62template <class HeaderType>
64inline void FLogScope::EnterPrelude(uint32 Size)
65{
66 uint32 AllocSize = sizeof(HeaderType) + Size;
67
69 if (UNLIKELY(Buffer->Cursor + AllocSize > (uint8*)Buffer))
70 {
72 }
73
74#if !UE_BUILD_SHIPPING && !UE_BUILD_TEST
75 if (AllocSize >= Buffer->Size)
76 {
77 // This situation is terminal. Someone's trying to trace an event that
78 // is far too large. This should never happen as 'maximum_field_count *
79 // largest_field_size' won't exceed Buffer.Size.
81 }
82#endif
83
84 Ptr = Buffer->Cursor + sizeof(HeaderType);
85 Buffer->Cursor += AllocSize;
86}
87
90inline void FLogScope::Enter(uint32 Uid, uint32 Size)
91{
93
94 uint16 Uid16 = uint16(Uid) | int32(EKnownEventUids::Flag_TwoByteUid);
96
97 // Event header FEventHeaderSync
98 memcpy(Ptr - 3, &Serial, sizeof(Serial)); /* FEventHeaderSync::SerialHigh,SerialLow */
99 memcpy(Ptr - 5, &Uid16, sizeof(Uid16)); /* FEventHeaderSync::Uid */
100}
101
104inline void FLogScope::EnterNoSync(uint32 Uid, uint32 Size)
105{
107
108 uint16 Uid16 = uint16(Uid) | int32(EKnownEventUids::Flag_TwoByteUid);
109
110 // Event header FEventHeader
111 auto* Header = (uint16*)(Ptr);
112 memcpy(Header - 1, &Uid16, sizeof(Uid16)); /* FEventHeader::Uid */
113}
114
116template <bool bMaybeHasAux>
118inline void TLogScope<bMaybeHasAux>::operator += (const FLogScope&) const
119{
120 if constexpr (bMaybeHasAux)
121 {
122 FWriteBuffer* LatestBuffer = Writer_GetBuffer();
123 LatestBuffer->Cursor[0] = uint8(EKnownEventUids::AuxDataTerminal << EKnownEventUids::_UidShift);
124 LatestBuffer->Cursor++;
125
126 Commit(LatestBuffer);
127 }
128 else
129 {
130 Commit();
131 }
132}
133
135inline void FScopedLogScope::Deinit()
136{
137 if (!bActive)
138 {
139 return;
140 }
141
142 if (AutoRTFM::IsClosed())
143 {
144 // If we are operating closed (in a transaction) we have to forget about
145 // our previously registered on-abort handler, because we're currently
146 // about to close out the scope within the transaction.
147 AutoRTFM::PopOnAbortHandler(this);
148 AutoRTFM::Open([this] { this->Deinit(); });
149 return;
150 }
151
152 uint8 LeaveUid = uint8(EKnownEventUids::LeaveScope << EKnownEventUids::_UidShift);
153
155 if (UNLIKELY(int32((uint8*)Buffer - Buffer->Cursor) < int32(sizeof(LeaveUid))))
156 {
158 }
159
160 Buffer->Cursor[0] = LeaveUid;
161 Buffer->Cursor += sizeof(LeaveUid);
162
163 AtomicStoreRelease((uint8**) &(Buffer->Committed), Buffer->Cursor);
164}
165
167inline FScopedLogScope::~FScopedLogScope()
168{
169 Deinit();
170}
171
173inline void FScopedLogScope::SetActive()
174{
175 if (bActive)
176 {
177 // We don't want to re-activate an already active scope!
178 return;
179 }
180
181 if (AutoRTFM::IsClosed())
182 {
183 // If we are operating closed (in a transaction) we could abort before
184 // `this` hits its destructor. In that case we need to remember when
185 // we abort to close out the scoped trace event.
186 AutoRTFM::PushOnAbortHandler(this, [this] { this->Deinit(); });
187 AutoRTFM::Open([this] { this->SetActive(); });
188 return;
189 }
190
191 bActive = true;
192}
193
195inline void FScopedStampedLogScope::Deinit()
196{
197 if (!bActive)
198 {
199 return;
200 }
201
202 if (AutoRTFM::IsClosed())
203 {
204 // If we are operating closed (in a transaction) we have to forget about
205 // our previously registered on-abort handler, because we're currently
206 // about to close out the scope within the transaction.
207 AutoRTFM::PopOnAbortHandler(this);
208 AutoRTFM::Open([this] { this->Deinit(); });
209 return;
210 }
211
213
215 if (UNLIKELY(int32((uint8*)Buffer - Buffer->Cursor) < int32(sizeof(Stamp))))
216 {
218 }
219
220 Stamp <<= 8;
221 Stamp += uint8(EKnownEventUids::LeaveScope_TB) << EKnownEventUids::_UidShift;
222 memcpy((uint64*)(Buffer->Cursor), &Stamp, sizeof(Stamp));
223 Buffer->Cursor += sizeof(Stamp);
224
225 AtomicStoreRelease((uint8**) &(Buffer->Committed), Buffer->Cursor);
226}
227
229inline FScopedStampedLogScope::~FScopedStampedLogScope()
230{
231 Deinit();
232}
233
235inline void FScopedStampedLogScope::SetActive()
236{
237 if (bActive)
238 {
239 // We don't want to re-activate an already active scope!
240 return;
241 }
242
243 if (AutoRTFM::IsClosed())
244 {
245 // If we are operating closed (in a transaction) we could abort before
246 // `this` hits its destructor. In that case we need to remember when
247 // we abort to close out the scoped trace event.
248 AutoRTFM::PushOnAbortHandler(this, [this] { this->Deinit(); });
249 AutoRTFM::Open([this] { this->SetActive(); });
250 return;
251 }
252
253 bActive = true;
254}
255
257template <class EventType>
259FORCENOINLINE auto FLogScope::Enter()
260{
261 uint32 Size = EventType::GetSize();
262 uint32 Uid = EventType::GetUid();
264}
265
267template <class EventType>
269FORCENOINLINE auto FLogScope::ScopedEnter()
270{
271 uint8 EnterUid = uint8(EKnownEventUids::EnterScope << EKnownEventUids::_UidShift);
272
274 constexpr int32 EventHeaderSize = (EventType::EventFlags & FEventInfo::Flag_NoSync) != 0 ? sizeof(FEventHeader) : sizeof(FEventHeaderSync);
275 constexpr int32 RequiredSize = sizeof(EnterUid) + EventHeaderSize + EventType::GetSize();
276 if (UNLIKELY(int32((uint8*)Buffer - Buffer->Cursor) < RequiredSize))
277 {
279 }
280
281 Buffer->Cursor[0] = EnterUid;
282 Buffer->Cursor += sizeof(EnterUid);
283
284 AtomicStoreRelease((uint8**) &(Buffer->Committed), Buffer->Cursor);
285
286 return Enter<EventType>();
287}
288
290template <class EventType>
292FORCENOINLINE auto FLogScope::ScopedStampedEnter()
293{
295
297 constexpr int32 EventHeaderSize = (EventType::EventFlags & FEventInfo::Flag_NoSync) != 0 ? sizeof(FEventHeader) : sizeof(FEventHeaderSync);
298 constexpr int32 RequiredSize = sizeof(Stamp) + EventHeaderSize + EventType::GetSize();
299 if (UNLIKELY(int32((uint8*)Buffer - Buffer->Cursor) < RequiredSize))
300 {
302 }
303
305 Stamp <<= 8;
306 Stamp += uint8(EKnownEventUids::EnterScope_TB) << EKnownEventUids::_UidShift;
307 memcpy((uint64*)(Buffer->Cursor), &Stamp, sizeof(Stamp));
308 Buffer->Cursor += sizeof(Stamp);
309
310 AtomicStoreRelease((uint8**) &(Buffer->Committed), Buffer->Cursor);
311
312 return Enter<EventType>();
313}
314
315
316
318template <typename FieldMeta, typename Type>
319struct FLogScope::FFieldSet
320{
322 static void Impl(FLogScope* Scope, const Type& Value)
323 {
324 uint8* Dest = (uint8*)(Scope->Ptr) + FieldMeta::Offset;
325 ::memcpy(Dest, &Value, sizeof(Type));
326 }
327};
328
330template <typename FieldMeta, typename Type>
331struct FLogScope::FFieldSet<FieldMeta, Type[]>
332{
334 static void Impl(FLogScope*, Type const* Data, int32 Num)
335 {
336 static const uint32 Index = FieldMeta::Index & int32(EIndexPack::NumFieldsMask);
337 int32 Size = (Num * sizeof(Type)) & (FAuxHeader::SizeLimit - 1) & ~(sizeof(Type) - 1);
338 Field_WriteAuxData(Index, (const uint8*)Data, Size);
339 }
340};
341
342#if STATICALLY_SIZED_ARRAY_FIELDS_SUPPORT
344template <typename FieldMeta, typename Type, int32 Count>
345struct FLogScope::FFieldSet<FieldMeta, Type[Count]>
346{
347 static void Impl(FLogScope*, Type const* Data, int32 Num=-1) = delete;
348};
349#endif // STATICALLY_SIZED_ARRAY_FIELDS_SUPPORT
350
352template <typename FieldMeta>
353struct FLogScope::FFieldSet<FieldMeta, AnsiString>
354{
356 static void Impl(FLogScope*, const ANSICHAR* String, int32 Length=-1)
357 {
358 if (Length < 0)
359 {
361 }
362
363 static const uint32 Index = FieldMeta::Index & int32(EIndexPack::NumFieldsMask);
365 }
366
368 static void Impl(FLogScope*, const WIDECHAR* String, int32 Length=-1)
369 {
370 if (Length < 0)
371 {
372 Length = 0;
373 for (const WIDECHAR* c = String; *c; ++c, ++Length);
374 }
375
376 static const uint32 Index = FieldMeta::Index & int32(EIndexPack::NumFieldsMask);
378 }
379};
380
382template <typename FieldMeta>
383struct FLogScope::FFieldSet<FieldMeta, WideString>
384{
386 static void Impl(FLogScope*, const WIDECHAR* String, int32 Length=-1)
387 {
388 if (Length < 0)
389 {
390 Length = 0;
391 for (const WIDECHAR* c = String; *c; ++c, ++Length);
392 }
393
394 static const uint32 Index = FieldMeta::Index & int32(EIndexPack::NumFieldsMask);
396 }
397};
398
400template <typename FieldMeta, typename DefinitionType>
401struct FLogScope::FFieldSet<FieldMeta, TEventRef<DefinitionType>>
402{
404 static void Impl(FLogScope* Scope, const TEventRef<DefinitionType>& Reference)
405 {
406 FFieldSet<FieldMeta, DefinitionType>::Impl(Scope, Reference.Id);
407 }
408};
409
410} // namespace Private
411} // namespace Trace
412} // namespace UE
413
414#endif // TRACE_PRIVATE_MINIMAL_ENABLED
#define PLATFORM_BREAK()
Definition AndroidPlatformMisc.h:17
#define FORCENOINLINE
Definition AndroidPlatform.h:142
#define UE_AUTORTFM_ALWAYS_OPEN
Definition AutoRTFMDefines.h:114
FPlatformTypes::WIDECHAR WIDECHAR
A wide character. Normally a signed type.
Definition Platform.h:1133
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
#define UNLIKELY(x)
Definition Platform.h:857
FPlatformTypes::ANSICHAR ANSICHAR
An ANSI character. Normally a signed type.
Definition Platform.h:1131
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
@ Num
Definition MetalRHIPrivate.h:234
uint32 Size
Definition VulkanMemory.cpp:4034
memcpy(InputBufferBase, BinkBlocksData, BinkBlocksSize)
uint8_t uint8
Definition binka_ue_file_header.h:8
uint16_t uint16
Definition binka_ue_file_header.h:7
uint32_t uint32
Definition binka_ue_file_header.h:6
@ Trace
Definition NetTraceConfig.h:23
Type
Definition PawnAction_Move.h:11
Definition ExpressionParserTypes.h:21
Definition OverriddenPropertySet.cpp:45
void Serial(FArchive &Ar, T *Param)
Definition DirectLinkSerialMethods.h:100
void AtomicStoreRelease(Type volatile *Target, Type Value)
Definition Atomic.h:83
Type AtomicAddRelaxed(Type volatile *Target, Type Value)
Definition Atomic.h:131
@ Reference
Definition Protocol6.h:40
AnsiString
Definition Trace.h:52
WideString
Definition Trace.h:53
Definition AdvancedWidgetsModule.cpp:13
U16 Index
Definition radfft.cpp:71