Skip to content

Commit 0a56f44

Browse files
authored
fix: Add more detailed logging around RPC messages (#3994)
* fix: Add more detailed logging around RPC messages
1 parent 7c992c2 commit 0a56f44

18 files changed

Lines changed: 335 additions & 136 deletions

com.unity.netcode.gameobjects/Runtime/Logging/ContextualLogger.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public ContextualLogger(Object inspectorObject, [NotNull] NetworkManager network
6060
}
6161

6262
/// Used for the NetworkLog
63-
internal ContextualLogger(NetworkManager networkManager, bool useCompatibilityMode)
63+
internal ContextualLogger(NetworkManager networkManager, bool useCompatibilityMode = false)
6464
{
6565
m_UseCompatibilityMode = useCompatibilityMode;
6666
m_ManagerContext = new LogContextNetworkManager(networkManager);
@@ -89,7 +89,7 @@ internal DisposableContext AddDisposableInfo(string key, object value)
8989
[Conditional(k_CompilationCondition)]
9090
internal void RemoveInfo(string key)
9191
{
92-
m_LoggerContext.ClearInfo(key);
92+
m_LoggerContext.RemoveInfo(key);
9393
}
9494

9595
[HideInCallstack]
@@ -125,6 +125,19 @@ public void Exception(Exception exception)
125125
{
126126
Debug.unityLogger.LogException(exception, m_Object);
127127
}
128+
[HideInCallstack]
129+
public void Exception(Exception exception, Context context)
130+
{
131+
// Don't act if the LogLevel is higher than the level of this log
132+
if (m_ManagerContext.LogLevel > context.Level)
133+
{
134+
return;
135+
}
136+
137+
var message = BuildLog(context);
138+
Debug.unityLogger.LogException(new Exception(message, exception), context.RelevantObjectOverride ?? m_Object);
139+
}
140+
128141

129142
[HideInCallstack]
130143
private void Log(LogType logType, Context context)

com.unity.netcode.gameobjects/Runtime/Logging/LogBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public void AppendInfo(object key, object value)
3131
}
3232

3333
public void Append(string value) => m_Builder.Append(value);
34+
public void AppendLine(string value) => m_Builder.AppendLine(value);
3435

3536
public string Build() => m_Builder.ToString();
3637
}

com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs

Lines changed: 0 additions & 76 deletions
This file was deleted.

com.unity.netcode.gameobjects/Runtime/Logging/LogContext.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Collections.Generic;
2+
3+
namespace Unity.Netcode.Logging
4+
{
5+
internal delegate string LogCollectionBuilder<in TItem>(TItem item);
6+
internal readonly struct CollectionContext<TItem> : ILogContext
7+
{
8+
private readonly LogCollectionBuilder<TItem> m_Delegate;
9+
private readonly IEnumerable<TItem> m_Collection;
10+
11+
public CollectionContext(IEnumerable<TItem> collection, LogCollectionBuilder<TItem> builder)
12+
{
13+
m_Delegate = builder;
14+
m_Collection = collection;
15+
}
16+
17+
public void AppendTo(LogBuilder builder)
18+
{
19+
foreach (var item in m_Collection)
20+
{
21+
builder.AppendLine(m_Delegate(item));
22+
}
23+
}
24+
}
25+
}

com.unity.netcode.gameobjects/Runtime/Logging/LogContext/CollectionContext.cs.meta

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs renamed to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,20 @@ namespace Unity.Netcode.Logging
55
{
66
internal readonly struct GenericContext : ILogContext, IDisposable
77
{
8-
private readonly List<string> m_Contexts;
8+
private readonly List<string> m_Tags;
99
private readonly Dictionary<object, object> m_Info;
1010

11-
private GenericContext(List<string> contexts, Dictionary<object, object> info)
11+
private GenericContext(List<string> tags, Dictionary<object, object> info)
1212
{
13-
m_Contexts = contexts;
13+
m_Tags = tags;
1414
m_Info = info;
1515
}
1616

1717
public void AppendTo(LogBuilder builder)
1818
{
19-
if (m_Contexts != null)
19+
if (m_Tags != null)
2020
{
21-
foreach (var ctx in m_Contexts)
21+
foreach (var ctx in m_Tags)
2222
{
2323
builder.AppendTag(ctx);
2424
}
@@ -33,21 +33,26 @@ public void AppendTo(LogBuilder builder)
3333
}
3434
}
3535

36-
public void StoreTag(string msg)
36+
public void StoreTag(string tag)
3737
{
38-
m_Contexts.Add(msg);
38+
m_Tags.Add(tag);
3939
}
4040

4141
public void StoreInfo(object key, object value)
4242
{
4343
m_Info.Add(key, value);
4444
}
4545

46-
public void ClearInfo(object key)
46+
public void RemoveInfo(object key)
4747
{
4848
m_Info?.Remove(key);
4949
}
5050

51+
public void RemoveTag(string tag)
52+
{
53+
m_Tags?.Remove(tag);
54+
}
55+
5156
public void Dispose()
5257
{
5358
PreallocatedStore.Free(this);
@@ -76,7 +81,7 @@ internal static GenericContext GetPreallocated()
7681

7782
internal static void Free(GenericContext ctx)
7883
{
79-
ctx.m_Contexts.Clear();
84+
ctx.m_Tags.Clear();
8085
ctx.m_Info.Clear();
8186
k_Preallocated.Enqueue(ctx);
8287
}

com.unity.netcode.gameobjects/Runtime/Logging/GenericContext.cs.meta renamed to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/GenericContext.cs.meta

File renamed without changes.
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.CompilerServices;
4+
using Object = UnityEngine.Object;
5+
6+
namespace Unity.Netcode.Logging
7+
{
8+
internal interface ILogContext
9+
{
10+
public void AppendTo(LogBuilder builder);
11+
}
12+
13+
internal struct Context : ILogContext, IDisposable
14+
{
15+
public readonly LogLevel Level;
16+
private readonly string m_CallingFunction;
17+
internal readonly string Message;
18+
internal Object RelevantObjectOverride;
19+
20+
private readonly GenericContext m_Other;
21+
private List<ILogContext> m_Prepend;
22+
private List<ILogContext> m_Postpend;
23+
24+
public Context(LogLevel level, string msg, [CallerMemberName] string memberName = "")
25+
{
26+
Level = level;
27+
Message = msg;
28+
m_CallingFunction = memberName;
29+
30+
m_Other = GenericContext.Create();
31+
RelevantObjectOverride = null;
32+
m_Prepend = null;
33+
m_Postpend = null;
34+
}
35+
36+
internal Context(LogLevel level, string msg, bool noCaller)
37+
{
38+
Level = level;
39+
Message = msg;
40+
m_CallingFunction = null;
41+
42+
m_Other = GenericContext.Create();
43+
RelevantObjectOverride = null;
44+
m_Prepend = null;
45+
m_Postpend = null;
46+
}
47+
48+
public void AppendTo(LogBuilder builder)
49+
{
50+
// [CallingFunction]
51+
if (!string.IsNullOrEmpty(m_CallingFunction))
52+
{
53+
builder.AppendTag(m_CallingFunction);
54+
}
55+
56+
57+
// [SomeContext][SomeName:SomeValue]
58+
m_Other.AppendTo(builder);
59+
60+
if (m_Prepend != null)
61+
{
62+
foreach (var context in m_Prepend)
63+
{
64+
context.AppendTo(builder);
65+
}
66+
}
67+
68+
// Human-readable log message
69+
builder.Append(" ");
70+
builder.Append(Message);
71+
72+
if (m_Postpend != null)
73+
{
74+
foreach (var context in m_Postpend)
75+
{
76+
context.AppendTo(builder);
77+
}
78+
}
79+
}
80+
81+
public Context AddInfo(object key, object value)
82+
{
83+
m_Other.StoreInfo(key, value);
84+
return this;
85+
}
86+
87+
public Context AddTag(string msg)
88+
{
89+
m_Other.StoreTag(msg);
90+
return this;
91+
}
92+
93+
public Context AddObject(Object obj)
94+
{
95+
RelevantObjectOverride = obj;
96+
return this;
97+
}
98+
99+
public Context AddNetworkObject(NetworkObject networkObject)
100+
{
101+
AddPrepend(new LogContextNetworkObject(networkObject));
102+
RelevantObjectOverride = networkObject;
103+
return this;
104+
}
105+
106+
public Context AddNetworkBehaviour(NetworkBehaviour networkBehaviour)
107+
{
108+
AddPrepend(new LogContextNetworkBehaviour(networkBehaviour));
109+
RelevantObjectOverride = networkBehaviour;
110+
return this;
111+
}
112+
113+
public Context AddCollection<TItem>(IEnumerable<TItem> collection, LogCollectionBuilder<TItem> builder)
114+
{
115+
AddPostpend(new CollectionContext<TItem>(collection, builder));
116+
return this;
117+
}
118+
119+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
120+
private void AddPrepend(ILogContext prepend)
121+
{
122+
if (m_Prepend == null)
123+
{
124+
m_Prepend = PreallocatedStore.GetPreallocated();
125+
}
126+
m_Prepend.Add(prepend);
127+
}
128+
129+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
130+
private void AddPostpend(ILogContext postpend)
131+
{
132+
if (m_Postpend == null)
133+
{
134+
m_Postpend = PreallocatedStore.GetPreallocated();
135+
}
136+
m_Postpend.Add(postpend);
137+
}
138+
139+
public void Dispose()
140+
{
141+
m_Other.Dispose();
142+
PreallocatedStore.Free(m_Prepend);
143+
PreallocatedStore.Free(m_Postpend);
144+
m_Prepend = null;
145+
m_Postpend = null;
146+
}
147+
148+
private static class PreallocatedStore
149+
{
150+
private static readonly Queue<List<ILogContext>> k_Preallocated = new();
151+
152+
internal static List<ILogContext> GetPreallocated()
153+
{
154+
if (k_Preallocated.Count > 0)
155+
{
156+
k_Preallocated.Dequeue();
157+
}
158+
159+
return new List<ILogContext>();
160+
}
161+
162+
internal static void Free(List<ILogContext> collection)
163+
{
164+
collection.Clear();
165+
k_Preallocated.Enqueue(collection);
166+
}
167+
}
168+
}
169+
}

com.unity.netcode.gameobjects/Runtime/Logging/LogContext.cs.meta renamed to com.unity.netcode.gameobjects/Runtime/Logging/LogContext/LogContext.cs.meta

File renamed without changes.

0 commit comments

Comments
 (0)