Skip to content
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

Adding some smarter defaults for persistence of data #25

Merged
merged 7 commits into from
Mar 1, 2023
28 changes: 23 additions & 5 deletions Analytics-CSharp/Segment/Analytics/Configuration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@

using System;
using System.IO;
using Segment.Analytics.Utilities;
using Segment.Concurrent;

Expand Down Expand Up @@ -33,11 +35,12 @@ public class Configuration
/// </summary>
/// <param name="writeKey">the Segment writeKey</param>
/// <param name="persistentDataPath">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to remove this comment block too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

/// path where analytics stores data. for example:
/// path where analytics stores data when using a storage provider that writes to disk. for example:
/// <list type="bullet">
/// <item><description>Xamarin: <c>Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)</c></description></item>
/// <item><description>Unity: <c>Application.persistentDataPath</c></description></item>
/// </list>
/// defaults to Local Application Data
/// </param>
/// <param name="flushAt">count of events at which we flush events, defaults to <c>20</c></param>
/// <param name="flushInterval">interval in seconds at which we flush events, defaults to <c>30 seconds</c></param>
Expand All @@ -49,12 +52,13 @@ public class Configuration
/// <param name="exceptionHandler">set an exception handler to handle errors happened in async methods within the analytics scope</param>
/// <param name="storageProvider">set a storage provide to tell the analytics where to store your data:
/// <list type="bullet">
/// <item><description><see cref="InMemoryStorageProvider"/> stores data only in memory</description></item>
/// <item><description><see cref="InMemoryStorageProvider"/> stores data only in memory and ignores the persistentDataPath</description></item>
/// <item><description><see cref="DefaultStorageProvider"/> persists data in local disk. This is used by default</description></item>
/// </list>
/// defaults to DefaultStorageProvider on Unity (Mono) and Xamarin, or to InMemoryStorageProvider on .Net Core
/// </param>
public Configuration(string writeKey,
string persistentDataPath,
string persistentDataPath = null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now that we have a way to provide StorageProvider, I think we can move this parameter to where we create a storage provider. since these two things are related, it makes sense to put them at one place.

int flushAt = 20,
int flushInterval = 30,
Settings defaultSettings = new Settings(),
Expand All @@ -65,8 +69,10 @@ public Configuration(string writeKey,
ICoroutineExceptionHandler exceptionHandler = null,
IStorageProvider storageProvider = default)
{
var platform = SystemInfo.getPlatform();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like this variable is unused?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, thanks.


this.writeKey = writeKey;
this.persistentDataPath = persistentDataPath;
this.persistentDataPath = persistentDataPath ?? SystemInfo.getAppFolder();
this.flushAt = flushAt;
this.flushInterval = flushInterval;
this.defaultSettings = defaultSettings;
Expand All @@ -75,7 +81,19 @@ public Configuration(string writeKey,
this.apiHost = apiHost;
this.cdnHost = cdnHost;
this.exceptionHandler = exceptionHandler;
this.storageProvider = storageProvider ?? new DefaultStorageProvider();

if (storageProvider != null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the more I think the more I feel we probably only need to smart default persist data path. we should always to default to use storage unless the user specifies to use in memory. what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm in favor. More consistent behavior, fewer assumptions and surprises.

{
this.storageProvider = storageProvider;
}
else if (platform.Contains("Mono") || platform.Contains("Xamarin"))
{
this.storageProvider = new DefaultStorageProvider();
}
else
{
this.storageProvider = new InMemoryStorageProvider();
}
}
}

Expand Down
9 changes: 8 additions & 1 deletion Analytics-CSharp/Segment/Analytics/Plugins/ContextPlugin.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Segment.Serialization;
using Segment.Analytics.Utilities;

namespace Segment.Analytics.Plugins
{
Expand All @@ -18,6 +19,10 @@ public class ContextPlugin : Plugin

private const string LibraryVersionKey = "version";

private const string OSKey = "os";

private const string PlatformKey = "platform";

public override void Configure(Analytics analytics)
{
base.Configure(analytics);
Expand All @@ -32,7 +37,9 @@ private void ApplyContextData(RawEvent @event)
{
var context = new JsonObject(@event.context?.Content)
{
[LibraryKey] = _library
[LibraryKey] = _library,
[OSKey] = SystemInfo.getOS(),
[PlatformKey] = SystemInfo.getPlatform()
};

@event.context = context;
Expand Down
80 changes: 80 additions & 0 deletions Analytics-CSharp/Segment/Analytics/Utilities/SystemInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.Runtime.InteropServices;

namespace Segment.Analytics.Utilities
{
public class SystemInfo
{
public static string getAppFolder()
{
var type = Type.GetType("UnityEngine.Application, UnityEngine");
string unityPath = type?.GetProperty("persistentDataPath").GetValue(null,null).ToString();
if(unityPath != null)
{
return unityPath;
}

return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}

public static string getPlatform()
{
var type = "";

if (Type.GetType("Xamarin.Forms.Device") != null)
{
type = "Xamarin";
}
else if (Type.GetType("UnityEngine.Device.SystemInfo, UnityEngine") != null)
{
type = "Unity";
}
else
{
var descr = RuntimeInformation.FrameworkDescription;
var platf = descr.Substring(0, descr.LastIndexOf(' '));

type = platf;
}
return type;
}

public static string getOS()
{
OperatingSystem os = Environment.OSVersion;
var vs = os.Version;

string operatingSystem = "";

switch (os.Platform)
{

case PlatformID.Win32S:
operatingSystem = "Win32S";
break;
case PlatformID.Win32Windows:
operatingSystem = "Win32Windows";
break;
case PlatformID.Win32NT:
operatingSystem = "Win32NT";
break;
case PlatformID.WinCE:
operatingSystem = "WinCE";
break;
case PlatformID.Unix:
operatingSystem = "Unix";
break;
case PlatformID.Xbox:
operatingSystem = "Xbox";
break;
case PlatformID.MacOSX:
operatingSystem = "MacOSX";
break;
default:
break;
}
return operatingSystem + " - " + vs.Major + "." + vs.Minor;
}
}
}

35 changes: 35 additions & 0 deletions Tests/Utilities/SystemInfoTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using Segment.Analytics.Utilities;
using Xunit;

namespace Tests.Utilities
{
public class SystemInfoTest
{

[Fact]
public void GetPlatformTest()
{
var sysinfo = SystemInfo.getPlatform();

Assert.NotNull(sysinfo);
Assert.Contains(".NET", sysinfo);
}

[Fact]
public void GetOSTest()
{
var sysinfo = SystemInfo.getOS();

Assert.NotNull(sysinfo);
}

[Fact]
public void GetAppFolderTest()
{
var path = SystemInfo.getAppFolder();

Assert.Equal(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), path);
}
}
}