Skip to content

Commit cf8ccc2

Browse files
committed
Squashed commit of the following:
commit 0fc1aa6 Author: Samy Al Bahra <sbahra@repnop.org> Date: Sun Oct 18 14:58:19 2020 -0400 doc: fix typo in README. commit 5853df4 Author: jasoncdavis0 <jason.davis@enterprisedb.com> Date: Thu Oct 15 11:53:40 2020 -0400 Update CHANGELOG.md commit 3a348bb Author: Konrad Dysput <konrad.dysput@gmail.com> Date: Thu Oct 15 17:47:19 2020 +0200 Version 3.1.2 - PII changes - `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 0fb3f4b commit cf8ccc2

File tree

5 files changed

+198
-61
lines changed

5 files changed

+198
-61
lines changed

CHANGELOG.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,24 @@
33
## Version 3.2.0-release candidate
44
This release adds the ability to capture native iOS crashes from Unity games deployed to iOS. The Backtrace Configuration now exposes a setting for games being prepared for iOS to choose `Capture native crashes`. When enabled, the backtrace-unity client will capture and submit native iOS crashes to the configured Backtrace instance. To generate human readable callstacks, game programmers will need to generate and upload appropriate debug symbols.
55

6+
## Version 3.1.2
7+
- `BacktraceData` allows to edit list of environment variables collected by `BacktraceAnnotations`
8+
- `SourceCode` object description for PII purpose
9+
- `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.
10+
11+
```csharp
12+
Annotations.EnvironmentVariablesCache["USERNAME"] = "%USERNAME%";
13+
```
14+
15+
Also you can still use BeforeSend event to edit collected diagnostic data:
16+
```csharp
17+
client.BeforeSend = (BacktraceData data) =>
18+
{
19+
data.Annotation.EnvironmentVariables["USERNAME"] = "%USERNAME%";
20+
return data;
21+
}
22+
```
23+
624
## Version 3.1.1
725
- Prevent erroneously extending backtraceClient attributes with backtraceReport attributes.
826
- Removed randomly generated path to assembly from callstacks.

Runtime/Model/BacktraceData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)