Skip to content

Commit 3a348bb

Browse files
authored
Version 3.1.2 - PII changes
## Version 3.1.2 - `BacktraceData` allows to edit list of environment variables collected by `BacktraceAnnotations` - `SourceCode` object description for PII purpose ` `Annotations` class exposes EnvironmentVariableCache dictionary - dictionary that stores environment variables collected by library. For example - to replace `USERNAME` environment variable collected by Backtrace library with random string you can easily edit annotations environment varaible and Backtrace-Untiy will reuse them on report creation. * public environment variables + pii tests * Version update * Updated description for BacktraceData SourceCode integration * Allow user to edit source code integration text * more unit tests + better changelog description
1 parent 1eea055 commit 3a348bb

File tree

6 files changed

+200
-63
lines changed

6 files changed

+200
-63
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
# Backtrace Unity Release Notes
22

3+
## Version 3.1.2
4+
- `BacktraceData` allows to edit list of environment variables collected by `BacktraceAnnotations`
5+
- `SourceCode` object description for PII purpose
6+
` `Annotations` class exposes EnvironmentVariableCache dictionary - dictionary that stores environment variables collected by library. For example - to replace `USERNAME` environment variable collected by Backtrace library with random string you can easily edit annotations environment varaible and Backtrace-Untiy will reuse them on report creation.
7+
8+
```csharp
9+
Annotations.EnvironmentVariablesCache["USERNAME"] = "%USERNAME%";
10+
```
11+
12+
Also you can still use BeforeSend event to edit collected diagnostic data:
13+
```csharp
14+
client.BeforeSend = (BacktraceData data) =>
15+
{
16+
data.Annotation.EnvironmentVariables["USERNAME"] = "%USERNAME%";
17+
return data;
18+
}
19+
```
20+
321
## Version 3.1.1
422
- Prevent erroneously extending backtraceClient attributes with backtraceReport attributes.
523
- Removed randomly generated path to assembly from callstacks.

Runtime/Model/BacktraceData.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ public class BacktraceData
4545
/// <summary>
4646
/// Version of the C# library
4747
/// </summary>
48-
public const string AgentVersion = "3.1.1";
48+
public const string AgentVersion = "3.1.2";
4949

5050
/// <summary>
5151
/// Application thread details
@@ -63,7 +63,7 @@ public class BacktraceData
6363
public string[] Classifier;
6464

6565
/// <summary>
66-
/// Source code information - right now we support source code only for BacktraceUnhandledException exceptions.
66+
/// Source code information.
6767
/// </summary>
6868
public BacktraceSourceCode SourceCode;
6969

Runtime/Model/BacktraceSourceCode.cs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,39 @@
33

44
namespace Backtrace.Unity.Model
55
{
6+
/// <summary>
7+
/// Source code panel - in Unity integration, Backtrace-Unity stores unity Engine
8+
/// logs in the Source Code integration.
9+
/// </summary>
610
public class BacktraceSourceCode
711
{
8-
public string Id = Guid.NewGuid().ToString();
12+
/// <summary>
13+
/// Source code id - integration uses id to assign source code to first stack frame
14+
/// </summary>
15+
public readonly string Id = Guid.NewGuid().ToString();
16+
/// <summary>
17+
/// Default source code type
18+
/// </summary>
919
public readonly string Type = "Text";
20+
/// <summary>
21+
/// Default source code title
22+
/// </summary>
1023
public readonly string Title = "Log File";
1124

12-
public bool HighlightLine = false;
13-
public string Text { get; set; }
25+
/// <summary>
26+
/// Required source code option - we don't want to hightlight any line
27+
/// </summary>
28+
public readonly bool HighlightLine = false;
1429

15-
public BacktraceSourceCode()
16-
{
17-
Type = "Text";
18-
Title = "Log File";
19-
}
30+
/// <summary>
31+
/// Unity engine text
32+
/// </summary>
33+
public string Text { get; set; }
2034

35+
/// <summary>
36+
/// Convert Source code integration into JSON object
37+
/// </summary>
38+
/// <returns>Source code BacktraceJObject</returns>
2139
internal BacktraceJObject ToJson()
2240
{
2341
var json = new BacktraceJObject();

Runtime/Model/JsonData/Annotations.cs

Lines changed: 25 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,23 @@
55
using System.Text.RegularExpressions;
66
using UnityEngine;
77
using UnityEngine.SceneManagement;
8-
98
namespace Backtrace.Unity.Model.JsonData
109
{
1110
/// <summary>
1211
/// Get report annotations - environment variables
1312
/// </summary>
1413
public class Annotations
1514
{
16-
17-
private static Dictionary<string, string> _variables;
18-
19-
/// <summary>
20-
/// System environment values dictionary
21-
/// </summary>
22-
internal static Dictionary<string, string> Variables
23-
{
24-
get
25-
{
26-
if (_variables == null)
27-
{
28-
_variables = new Dictionary<string, string>();
29-
foreach (DictionaryEntry variable in Environment.GetEnvironmentVariables())
30-
{
31-
_variables.Add(variable.Key.ToString(), Regex.Escape(variable.Value.ToString() ?? "NULL"));
32-
}
33-
}
34-
35-
return _variables;
36-
}
37-
}
38-
15+
public static Dictionary<string, string> EnvironmentVariablesCache { get; set; } = SetEnvironmentVariables();
16+
public Dictionary<string, string> EnvironmentVariables { get; set; } = EnvironmentVariablesCache;
3917
/// <summary>
4018
/// Set maximum number of game objects in Backtrace report
4119
/// </summary>
4220
private readonly int _gameObjectDepth;
43-
4421
/// <summary>
4522
/// Exception object
4623
/// </summary>
47-
private Exception _exception { get; set; }
48-
24+
public Exception Exception { get; set; }
4925
public Annotations()
5026
{
5127
}
@@ -57,37 +33,43 @@ public Annotations()
5733
public Annotations(Exception exception, int gameObjectDepth)
5834
{
5935
_gameObjectDepth = gameObjectDepth;
60-
_exception = exception;
36+
Exception = exception;
37+
}
38+
private static Dictionary<string, string> SetEnvironmentVariables()
39+
{
40+
var environmentVariables = new Dictionary<string, string>();
41+
foreach (DictionaryEntry variable in Environment.GetEnvironmentVariables())
42+
{
43+
environmentVariables.Add(variable.Key.ToString(), Regex.Escape(variable.Value.ToString() ?? "NULL"));
44+
}
45+
return environmentVariables;
6146
}
62-
6347
public BacktraceJObject ToJson()
6448
{
6549
var annotations = new BacktraceJObject();
6650
var envVariables = new BacktraceJObject();
67-
68-
foreach (var envVariable in Variables)
51+
if (EnvironmentVariables != null)
6952
{
70-
envVariables[envVariable.Key] = envVariable.Value;
53+
foreach (var envVariable in EnvironmentVariables)
54+
{
55+
envVariables[envVariable.Key] = envVariable.Value;
56+
}
57+
annotations["Environment Variables"] = envVariables;
7158
}
72-
annotations["Environment Variables"] = envVariables;
73-
74-
if (_exception != null)
59+
if (Exception != null)
7560
{
7661
annotations["Exception properties"] = new BacktraceJObject()
7762
{
78-
["message"] = _exception.Message,
79-
["stackTrace"] = _exception.StackTrace,
80-
["type"] = _exception.GetType().FullName,
81-
["source"] = _exception.Source
63+
["message"] = Exception.Message,
64+
["stackTrace"] = Exception.StackTrace,
65+
["type"] = Exception.GetType().FullName,
66+
["source"] = Exception.Source
8267
};
8368
}
84-
8569
if (_gameObjectDepth > -1)
8670
{
8771
var activeScene = SceneManager.GetActiveScene();
88-
8972
var gameObjects = new List<BacktraceJObject>();
90-
9173
var rootObjects = new List<GameObject>();
9274
activeScene.GetRootGameObjects(rootObjects);
9375
foreach (var gameObject in rootObjects)
@@ -96,11 +78,8 @@ public BacktraceJObject ToJson()
9678
}
9779
annotations["Game objects"] = gameObjects;
9880
}
99-
100-
10181
return annotations;
10282
}
103-
10483
private BacktraceJObject ConvertGameObject(GameObject gameObject, int depth = 0)
10584
{
10685
if (gameObject == null)
@@ -109,7 +88,6 @@ private BacktraceJObject ConvertGameObject(GameObject gameObject, int depth = 0)
10988
}
11089
var jGameObject = GetJObject(gameObject);
11190
var innerObjects = new List<BacktraceJObject>();
112-
11391
foreach (var childObject in gameObject.transform)
11492
{
11593
var transformChildObject = childObject as Component;
@@ -122,7 +100,6 @@ private BacktraceJObject ConvertGameObject(GameObject gameObject, int depth = 0)
122100
jGameObject["children"] = innerObjects;
123101
return jGameObject;
124102
}
125-
126103
private BacktraceJObject ConvertGameObject(Component gameObject, string parentName, int depth)
127104
{
128105
if (_gameObjectDepth > 0 && depth > _gameObjectDepth)
@@ -135,8 +112,6 @@ private BacktraceJObject ConvertGameObject(Component gameObject, string parentNa
135112
return result;
136113
}
137114
var innerObjects = new List<BacktraceJObject>();
138-
139-
140115
foreach (var childObject in gameObject.transform)
141116
{
142117
var transformChildObject = childObject as Component;
@@ -149,7 +124,6 @@ private BacktraceJObject ConvertGameObject(Component gameObject, string parentNa
149124
result["children"] = innerObjects;
150125
return result;
151126
}
152-
153127
private BacktraceJObject GetJObject(GameObject gameObject, string parentName = "")
154128
{
155129
var o = new BacktraceJObject();
@@ -166,7 +140,6 @@ private BacktraceJObject GetJObject(GameObject gameObject, string parentName = "
166140
o["parnetName"] = string.IsNullOrEmpty(parentName) ? "root object" : parentName;
167141
return o;
168142
}
169-
170143
private BacktraceJObject GetJObject(Component gameObject, string parentName = "")
171144
{
172145
var o = new BacktraceJObject();
@@ -180,4 +153,4 @@ private BacktraceJObject GetJObject(Component gameObject, string parentName = ""
180153
return o;
181154
}
182155
}
183-
}
156+
}

Tests/Runtime/ClientSendTests.cs

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Backtrace.Unity.Model;
2+
using Backtrace.Unity.Model.JsonData;
23
using NUnit.Framework;
34
using System;
45
using System.Collections;
@@ -71,5 +72,132 @@ public IEnumerator SendReport_MessageReport_ValidSend()
7172
Assert.IsTrue(trigger);
7273
yield return null;
7374
}
75+
76+
[UnityTest]
77+
public IEnumerator PiiTests_ShouldRemoveEnvironmentVariables_AnnotationsShouldntBeAvailable()
78+
{
79+
var trigger = false;
80+
var exception = new Exception("custom exception message");
81+
client.BeforeSend = (BacktraceData data) =>
82+
{
83+
Assert.IsNotNull(data.Annotation.EnvironmentVariables);
84+
data.Annotation.EnvironmentVariables = null;
85+
return data;
86+
};
87+
88+
client.RequestHandler = (string url, BacktraceData data) =>
89+
{
90+
trigger = true;
91+
Assert.IsNull(data.Annotation.EnvironmentVariables);
92+
return new BacktraceResult();
93+
};
94+
client.Send(exception);
95+
96+
yield return new WaitForEndOfFrame();
97+
Assert.IsTrue(trigger);
98+
yield return null;
99+
}
100+
101+
[UnityTest]
102+
public IEnumerator PiiTests_ShouldChangeApplicationDataPath_ApplicationDataPathDoesntHaveUserNameAnymore()
103+
{
104+
var trigger = false;
105+
var exception = new Exception("custom exception message");
106+
var expectedDataPath = "/some/path";
107+
client.BeforeSend = (BacktraceData data) =>
108+
{
109+
Assert.IsNotNull(data.Attributes.Attributes["application.data_path"]);
110+
data.Attributes.Attributes["application.data_path"] = expectedDataPath;
111+
return data;
112+
};
113+
client.RequestHandler = (string url, BacktraceData data) =>
114+
{
115+
trigger = true;
116+
Assert.AreEqual(expectedDataPath, data.Attributes.Attributes["application.data_path"]);
117+
return new BacktraceResult();
118+
};
119+
client.Send(exception);
120+
121+
yield return new WaitForEndOfFrame();
122+
Assert.IsTrue(trigger);
123+
yield return null;
124+
}
125+
126+
[UnityTest]
127+
public IEnumerator PiiTests_ShouldChangeSourceCodeIntegration_SourceCodeTextDoesntHaveUserNameAnymore()
128+
{
129+
var trigger = false;
130+
var exception = new Exception("custom exception message");
131+
var sourceCodeTestString = "source-code-test-string";
132+
client.BeforeSend = (BacktraceData data) =>
133+
{
134+
Assert.IsNotNull(data.SourceCode);
135+
Assert.IsNotEmpty(data.SourceCode.Text);
136+
data.SourceCode.Text = sourceCodeTestString;
137+
return data;
138+
};
139+
client.RequestHandler = (string url, BacktraceData data) =>
140+
{
141+
trigger = true;
142+
Assert.AreEqual(sourceCodeTestString, data.SourceCode.Text);
143+
return new BacktraceResult();
144+
};
145+
client.Send(exception);
146+
147+
yield return new WaitForEndOfFrame();
148+
Assert.IsTrue(trigger);
149+
yield return null;
150+
}
151+
152+
[UnityTest]
153+
public IEnumerator PiiTests_ShouldModifyEnvironmentVariable_IntegrationShouldUseModifiedEnvironmentVariables()
154+
{
155+
var trigger = false;
156+
var exception = new Exception("custom exception message");
157+
158+
var environmentVariableKey = "foo";
159+
var expectedValue = "bar";
160+
Annotations.EnvironmentVariablesCache[environmentVariableKey] = expectedValue;
161+
162+
client.BeforeSend = (BacktraceData data) =>
163+
{
164+
var actualValue = data.Annotation.EnvironmentVariables[environmentVariableKey];
165+
Assert.AreEqual(expectedValue, actualValue);
166+
trigger = true;
167+
return data;
168+
};
169+
client.Send(exception);
170+
171+
yield return new WaitForEndOfFrame();
172+
Assert.IsTrue(trigger);
173+
yield return null;
174+
}
175+
176+
177+
[UnityTest]
178+
public IEnumerator PiiTests_ShouldRemoveEnvironmentVariableValue_IntegrationShouldUseModifiedEnvironmentVariables()
179+
{
180+
var trigger = false;
181+
var exception = new Exception("custom exception message");
182+
183+
var environmentVariableKey = "USERNAME";
184+
var expectedValue = "%USERNAME%";
185+
var defaultUserName = Annotations.EnvironmentVariablesCache[environmentVariableKey];
186+
Annotations.EnvironmentVariablesCache[environmentVariableKey] = expectedValue;
187+
188+
client.BeforeSend = (BacktraceData data) =>
189+
{
190+
var actualValue = data.Annotation.EnvironmentVariables[environmentVariableKey];
191+
Assert.AreEqual(expectedValue, actualValue);
192+
Assert.AreNotEqual(defaultUserName, actualValue);
193+
trigger = true;
194+
return data;
195+
};
196+
client.Send(exception);
197+
198+
yield return new WaitForEndOfFrame();
199+
Assert.IsTrue(trigger);
200+
yield return null;
201+
}
74202
}
75203
}

0 commit comments

Comments
 (0)