-
Notifications
You must be signed in to change notification settings - Fork 1
feat: Analytics (MAPCO-8806) #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 14 commits
fce85cf
82862ff
450d2e0
92458a9
25b49d2
031670d
0274a6d
032e3eb
1c14373
9f1cfc5
e28780e
e594de7
ad6226e
2360dff
4a53689
82db891
a9d39c4
ced26e0
b048c25
5230e8d
289ef0e
192d7b4
c4ff8e5
c09b76f
60adf88
6f53c0b
5d2ca6b
d7999bc
6879708
9a70d23
0026cb8
bbeaa3a
096bd7f
6ff1eef
df20daf
75938ed
4960089
09cc0b6
6066de3
b31d549
100c16c
66a9938
42d4e31
210d9e0
412bd81
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| using System.IO; | ||
| using System.Threading.Tasks; | ||
| using com.mapcolonies.core.Services.Analytics.Enums; | ||
| using com.mapcolonies.core.Services.Analytics.Managers; | ||
| using com.mapcolonies.core.Services.Analytics.Model; | ||
| using NUnit.Framework; | ||
| using UnityEngine; | ||
|
|
||
| namespace EditorTests.Analytics | ||
| { | ||
| public class AnalyticsManagerFileWriteTests | ||
| { | ||
| private AnalyticsManager _manager; | ||
| private string _logDirPath; | ||
| private string _logFilePath; | ||
|
|
||
| [SetUp] | ||
| public void Setup() | ||
| { | ||
| _manager = new AnalyticsManager(); | ||
| _manager.Initialize(); | ||
|
|
||
| _logDirPath = Path.Combine(Application.persistentDataPath, "AnalyticsLogs"); | ||
| _logFilePath = Path.Combine(_logDirPath, $"session-{AnalyticsManager.SessionId}.log"); | ||
|
|
||
| if (File.Exists(_logFilePath)) | ||
| { | ||
| File.Delete(_logFilePath); | ||
| } | ||
| } | ||
|
|
||
| [TearDown] | ||
| public void Teardown() | ||
| { | ||
| if (File.Exists(_logFilePath)) File.Delete(_logFilePath); | ||
| if (Directory.Exists(_logDirPath) && Directory.GetFiles(_logDirPath).Length == 0) Directory.Delete(_logDirPath, true); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task Publish_Writes_JSON_Line_To_Session_Log_File() | ||
asafMasa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| LayerData msgParams = LayerData.Create("imagery", "layer-abc"); | ||
| LogObject log = LogObject.Create(LogType.Log, | ||
| AnalyticsMessageTypes.LayerUseStarted.ToString(), | ||
| msgParams, | ||
| "General", | ||
| AnalyticsMessageTypes.LayerUseStarted); | ||
|
|
||
| await AnalyticsManager.Publish(log); | ||
|
|
||
| Assert.IsTrue(File.Exists(_logFilePath), $"Log file was not created at {_logFilePath}"); | ||
|
|
||
| string content = await File.ReadAllTextAsync(_logFilePath); | ||
| StringAssert.Contains("\"LayerDomain\":\"imagery\"", content); | ||
| StringAssert.Contains("\"UniqueLayerId\":\"layer-abc\"", content); | ||
| StringAssert.Contains("\"MessageType\":" + (int)AnalyticsMessageTypes.LayerUseStarted, content); | ||
| StringAssert.Contains("\"Severity\":\"Log\"", content); | ||
| } | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| using System; | ||
| using com.mapcolonies.core.Services.Analytics.Enums; | ||
| using com.mapcolonies.core.Services.Analytics.Managers; | ||
| using com.mapcolonies.core.Services.Analytics.Model; | ||
| using NUnit.Framework; | ||
| using UnityEngine; | ||
|
|
||
| namespace EditorTests.Analytics | ||
| { | ||
| public class LogObjectTests | ||
| { | ||
| [Test] | ||
| public void Create_Sets_All_Fields() | ||
| { | ||
| long fakeSession = 123456789L; | ||
asafMasa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| AnalyticsManager.SessionId = fakeSession; | ||
| LogType severity = LogType.Warning; | ||
| string message = "LayerUseStarted"; | ||
| LayerData parameters = LayerData.Create("imagery", "layer-001"); | ||
| string component = "General"; | ||
| AnalyticsMessageTypes type = AnalyticsMessageTypes.LayerUseStarted; | ||
| LogObject log = LogObject.Create(severity, message, parameters, component, type); | ||
|
|
||
| Assert.AreEqual(fakeSession, log.SessionID); | ||
| Assert.AreEqual(severity.ToString(), log.Severity); | ||
| Assert.AreEqual(message, log.Message); | ||
| Assert.AreSame(parameters, log.MessageParameters); | ||
| Assert.AreEqual(component, log.Component); | ||
| Assert.AreEqual(type, log.MessageType); | ||
| Assert.That(log.TimeStamp, Is.InRange(DateTime.UtcNow.AddMinutes(-1), DateTime.UtcNow.AddMinutes(1))); | ||
| } | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| using System; | ||
| using System.Runtime.Serialization; | ||
| using com.mapcolonies.core.Services.Analytics.Model; | ||
| using NUnit.Framework; | ||
| using UnityEngine; | ||
|
|
||
| namespace EditorTests.Analytics | ||
| { | ||
| public class ModelSerializationTests | ||
| { | ||
| [Test] | ||
| public void LayerData_Serializes_Expected_Fields() | ||
| { | ||
| LayerData data = LayerData.Create("elevation", "lyr-42"); | ||
asafMasa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| SerializationInfo info = new SerializationInfo(typeof(LayerData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual("elevation", info.GetString(nameof(LayerData.LayerDomain))); | ||
| Assert.AreEqual("lyr-42", info.GetString(nameof(LayerData.UniqueLayerId))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void LocationData_Serializes_Expected_Fields() | ||
| { | ||
| LocationData data = LocationData.Create(34.5, 31.7); | ||
| SerializationInfo info = new SerializationInfo(typeof(LocationData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual(34.5, info.GetDouble(nameof(LocationData.Longitude))); | ||
| Assert.AreEqual(31.7, info.GetDouble(nameof(LocationData.Latitude))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ApplicationData_Serializes_Expected_Fields() | ||
| { | ||
| ApplicationData data = ApplicationData.Create("Yahalom", "1.2.3"); | ||
| SerializationInfo info = new SerializationInfo(typeof(ApplicationData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual("Yahalom", info.GetString(nameof(ApplicationData.ApplicationName))); | ||
| Assert.AreEqual("1.2.3", info.GetString(nameof(ApplicationData.ApplicationVersion))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void GameModeData_Serializes_Expected_Fields() | ||
| { | ||
| GameModeData data = GameModeData.Create("MissionPlanning", "TopDown"); | ||
| SerializationInfo info = new SerializationInfo(typeof(GameModeData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual("MissionPlanning", info.GetString(nameof(GameModeData.Mode))); | ||
| Assert.AreEqual("TopDown", info.GetString(nameof(GameModeData.ViewMode))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void PerformanceData_Serializes_Expected_Fields() | ||
| { | ||
| PerformanceData data = PerformanceData.Create(58.9f, 1024.5, 23.3); | ||
| SerializationInfo info = new SerializationInfo(typeof(PerformanceData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual(58.9f, info.GetSingle(nameof(PerformanceData.Fps))); | ||
| Assert.AreEqual(1024.5, info.GetDouble(nameof(PerformanceData.AllocatedMemoryInMB))); | ||
| Assert.AreEqual(23.3, info.GetDouble(nameof(PerformanceData.CpuUsagePercentage))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void UserInputDevices_Serializes_Expected_Fields() | ||
| { | ||
| UserInputDevicesData devs = UserInputDevicesData.Create(new[] {"Keyboard", "Mouse"}); | ||
| SerializationInfo info = new SerializationInfo(typeof(UserInputDevicesData), new FormatterConverter()); | ||
| devs.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| string[] stored = (string[])info.GetValue(nameof(UserInputDevicesData.InputDevices), typeof(string[])); | ||
| CollectionAssert.AreEqual(new[] {"Keyboard", "Mouse"}, stored); | ||
| } | ||
|
|
||
| [Test] | ||
| public void UserDetails_Serializes_Expected_Fields() | ||
| { | ||
| UserDetailsData detailsData = UserDetailsData.Create("username", "MAPCO", "DEVPC01"); | ||
| SerializationInfo info = new SerializationInfo(typeof(UserDetailsData), new FormatterConverter()); | ||
| detailsData.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual("username", info.GetString(nameof(UserDetailsData.UserName))); | ||
| Assert.AreEqual("MAPCO", info.GetString(nameof(UserDetailsData.UserDomainName))); | ||
| Assert.AreEqual("DEVPC01", info.GetString(nameof(UserDetailsData.MachineName))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void UserPlatformData_Serializes_Expected_Fields() | ||
| { | ||
| Resolution res = new Resolution { width = 1920, height = 1080, refreshRate = 60 }; | ||
| UserPlatformData data = UserPlatformData.Create("Windows 11", "Intel", "Direct3D11", 32768, | ||
| "RTX 3080", "555.12", 10240, res, "CustomPC"); | ||
| SerializationInfo info = new SerializationInfo(typeof(UserPlatformData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
|
|
||
| Assert.AreEqual("Windows 11", info.GetString(nameof(UserPlatformData.OperatingSystem))); | ||
| Assert.AreEqual("Intel", info.GetString(nameof(UserPlatformData.ProcessorType))); | ||
| Assert.AreEqual("Direct3D11", info.GetString(nameof(UserPlatformData.GraphicsDeviceType))); | ||
| Assert.AreEqual(32768, info.GetInt32(nameof(UserPlatformData.Ram))); | ||
| Assert.AreEqual("RTX 3080", info.GetString(nameof(UserPlatformData.GraphicsDeviceName))); | ||
| Assert.AreEqual("555.12", info.GetString(nameof(UserPlatformData.GraphicsDeviceVersion))); | ||
| Assert.AreEqual("CustomPC", info.GetString(nameof(UserPlatformData.DeviceModel))); | ||
| // Unity's Resolution struct is serialized as a whole; existence is enough. | ||
| Assert.DoesNotThrow(() => info.GetValue(nameof(UserPlatformData.ScreenResolution), typeof(Resolution))); | ||
| } | ||
|
|
||
| [Test] | ||
| public void ApplicationUsageData_Serializes_Expected_Fields() | ||
| { | ||
| TimeSpan timeSpan = TimeSpan.FromSeconds(123.45); | ||
| ApplicationUsageData data = ApplicationUsageData.Create(timeSpan); | ||
| SerializationInfo info = new SerializationInfo(typeof(ApplicationUsageData), new FormatterConverter()); | ||
| data.GetObjectData(info, new StreamingContext()); | ||
| TimeSpan storedTimeSpan = (TimeSpan)info.GetValue(nameof(ApplicationUsageData.Time), typeof(TimeSpan)); | ||
| Assert.AreEqual(123.45, storedTimeSpan.TotalSeconds, 0.0001); | ||
| } | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| using System; | ||
| using com.mapcolonies.core.Utilities; | ||
| using NUnit.Framework; | ||
|
|
||
| namespace EditorTests.Analytics | ||
| { | ||
| public class TimeUtilitiesTests | ||
| { | ||
| [Test] | ||
| public void SecondsToMilliseconds_Works() | ||
asafMasa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| { | ||
| double seconds = 1.5d; | ||
| double expectedMilliseconds = TimeSpan.FromSeconds(seconds).TotalMilliseconds; | ||
|
|
||
| var timeSpan = TimeSpan.FromSeconds(seconds); | ||
| double result = timeSpan.TotalMilliseconds; | ||
|
|
||
| Assert.AreEqual(expectedMilliseconds, result); | ||
| Assert.AreEqual(0d, TimeSpan.FromSeconds(0d).TotalMilliseconds); | ||
| } | ||
|
|
||
| [Test] | ||
| public void MillisecondsToSeconds_Works() | ||
| { | ||
| double milliseconds = 2500d; | ||
| double expectedSeconds = 2.5d; | ||
|
|
||
| var timeSpan = TimeSpan.FromMilliseconds(milliseconds); | ||
| double result = timeSpan.TotalSeconds; | ||
|
|
||
| Assert.AreEqual(expectedSeconds, result); | ||
| Assert.AreEqual(0d, TimeSpan.FromMilliseconds(0d).TotalSeconds); | ||
| } | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| using System; | ||
| using System.IO; | ||
| using System.Reflection; | ||
| using System.Threading.Tasks; | ||
| using com.mapcolonies.core.Services.Analytics.Managers; | ||
| using NUnit.Framework; | ||
| using UnityEngine; | ||
| using com.mapcolonies.core.Utilities; | ||
|
|
||
| namespace EditorTests.Analytics | ||
| { | ||
| public class UsageAnalyticsManagerReflectionTests | ||
asafMasa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| { | ||
| private string _logPath; | ||
|
|
||
| [SetUp] | ||
| public void Setup() | ||
| { | ||
| AnalyticsManager am = new AnalyticsManager(); | ||
asafMasa marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| am.Initialize(); | ||
|
|
||
| string dir = Path.Combine(Application.persistentDataPath, "AnalyticsLogs"); | ||
| _logPath = Path.Combine(dir, $"session-{AnalyticsManager.SessionId}.log"); | ||
| if (File.Exists(_logPath)) File.Delete(_logPath); | ||
| } | ||
|
|
||
| [Test] | ||
| public async Task PublishApplicationPerformance_Writes_Performance_Log() | ||
| { | ||
| Type type = typeof(UsageAnalyticsManager); | ||
asafMasa marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| var helper = new PlatformUsageHelper(); | ||
| object instance = System.Activator.CreateInstance(type, new object[] { helper }); | ||
|
|
||
| MethodInfo mi = type.GetMethod("PublishApplicationPerformance", BindingFlags.Instance | BindingFlags.NonPublic); | ||
| Assert.NotNull(mi, "Expected private method PublishApplicationPerformance"); | ||
|
|
||
| mi.Invoke(instance, new object[] { 30f, 123.0d, 45.6d }); | ||
|
|
||
| await Task.Delay(100); | ||
|
|
||
| Assert.IsTrue(File.Exists(_logPath), "Log file should exist"); | ||
| string content = await File.ReadAllTextAsync(_logPath); | ||
| StringAssert.Contains("\"Fps\":30", content); | ||
| StringAssert.Contains("\"AllocatedMemoryInMB\":123", content); | ||
| StringAssert.Contains("\"CpuUsagePercentage\":45.6", content); | ||
| } | ||
| } | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,5 +5,6 @@ | |
| ], | ||
| "includePlatforms": [ | ||
| "Editor" | ||
| ] | ||
| ], | ||
| "references":[ "GUID:def32eb86cfc4b07a6aa2ac71470d4af" ] | ||
| } | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.