-
-
Notifications
You must be signed in to change notification settings - Fork 55
/
Copy pathViewHierarchyEventProcessor.cs
120 lines (102 loc) · 3.83 KB
/
ViewHierarchyEventProcessor.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Sentry.Extensibility;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace Sentry.Unity;
public class ViewHierarchyEventProcessor : ISentryEventProcessorWithHint
{
private readonly SentryUnityOptions _options;
public ViewHierarchyEventProcessor(SentryUnityOptions sentryOptions)
{
_options = sentryOptions;
}
public SentryEvent? Process(SentryEvent @event)
{
return @event;
}
public SentryEvent? Process(SentryEvent @event, SentryHint hint)
{
if (!MainThreadData.IsMainThread())
{
_options.DiagnosticLogger?.LogDebug("Can't capture view hierarchy on other than main (UI) thread.");
return @event;
}
if (_options.BeforeCaptureViewHierarchyInternal?.Invoke() is not false)
{
var viewHierarchy = CreateViewHierarchy(
_options.MaxViewHierarchyRootObjects,
_options.MaxViewHierarchyObjectChildCount,
_options.MaxViewHierarchyDepth);
if (_options.BeforeSendViewHierarchyInternal is not null)
{
viewHierarchy = _options.BeforeSendViewHierarchyInternal.Invoke(viewHierarchy);
if (viewHierarchy is null)
{
return @event;
}
}
using var stream = new MemoryStream();
using var writer = new Utf8JsonWriter(stream);
viewHierarchy.WriteTo(writer, _options.DiagnosticLogger);
writer.Flush();
hint.AddAttachment(stream.ToArray(), "view-hierarchy.json", AttachmentType.ViewHierarchy, "application/json");
}
else
{
_options.DiagnosticLogger?.LogInfo("View hierarchy attachment skipped by BeforeAttachViewHierarchy callback.");
}
return @event;
}
internal ViewHierarchy CreateViewHierarchy(int maxRootGameObjectCount, int maxChildCount, int maxDepth)
{
var rootGameObjects = new List<GameObject>();
var scene = SceneManager.GetActiveScene();
scene.GetRootGameObjects(rootGameObjects);
// Consider the root a 'scene'.
var root = new UnityViewHierarchyNode(scene.name);
var viewHierarchy = new ViewHierarchy("Unity");
viewHierarchy.Windows.Add(root);
var rootElementCount = Math.Min(rootGameObjects.Count, maxRootGameObjectCount);
for (var i = 0; i < rootElementCount; i++)
{
CreateNode(maxDepth, maxChildCount, root, rootGameObjects[i].transform);
}
return viewHierarchy;
}
internal void CreateNode(int remainingDepth, int maxChildCount, ViewHierarchyNode parentNode, Transform transform)
{
var components = new List<Component>();
transform.GetComponents(components);
var extras = new List<string>(components.Count);
foreach (var component in components)
{
if (component?.GetType().Name is { } componentName)
{
extras.Add(componentName);
}
}
var node = new UnityViewHierarchyNode(transform.name)
{
Tag = transform.tag,
Position = transform.position.ToString(),
Rotation = transform.rotation.eulerAngles.ToString(),
Scale = transform.localScale.ToString(),
Active = transform.gameObject.activeSelf,
Extras = extras,
};
parentNode.Children.Add(node);
remainingDepth--;
if (remainingDepth <= 0)
{
return;
}
var childCount = Math.Min(transform.childCount, maxChildCount);
for (var i = 0; i < childCount; i++)
{
CreateNode(remainingDepth, maxChildCount, node, transform.GetChild(i));
}
}
}