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

support enrichment closure and setAnonymousId #110

Merged
merged 4 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions Analytics-CSharp/Segment/Analytics/Analytics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,15 @@ public Analytics(Configuration configuration)
/// Process a raw event through the system. Useful when one needs to queue and replay events at a later time.
/// </summary>
/// <param name="incomingEvent">An event conforming to RawEvent to be processed in the timeline</param>
public void Process(RawEvent incomingEvent)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public void Process(RawEvent incomingEvent, Func<RawEvent, RawEvent> enrichment = default)
{
if (!Enable) return;

incomingEvent.ApplyRawEventData(_userInfo);
AnalyticsScope.Launch(AnalyticsDispatcher, () =>
{
Timeline.Process(incomingEvent);
Timeline.Process(incomingEvent, enrichment);
});
}

Expand All @@ -100,6 +101,19 @@ public void Process(RawEvent incomingEvent)
/// <returns>Anonymous Id</returns>
public virtual string AnonymousId() => _userInfo._anonymousId;

/// <summary>
/// Set the anonymousId.
/// </summary>
/// <param name="anonymousId">Anonymous Id</param>
public virtual void SetAnonymousId(string anonymousId)
{
_userInfo._anonymousId = anonymousId;
AnalyticsScope.Launch(AnalyticsDispatcher, async () =>
{
await Store.Dispatch<UserInfo.SetAnonymousIdAction, UserInfo>(new UserInfo.SetAnonymousIdAction(anonymousId));
});
}


/// <summary>
/// Retrieve the userId registered by a previous <see cref="Identify(string,JsonObject)"/> call
Expand Down
78 changes: 46 additions & 32 deletions Analytics-CSharp/Segment/Analytics/Events.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using global::System.Runtime.Serialization;
using Segment.Serialization;

Expand All @@ -12,15 +13,16 @@ public partial class Analytics
/// </summary>
/// <param name="name">Name of the action</param>
/// <param name="properties">Properties to describe the action</param>
public virtual void Track(string name, JsonObject properties = default)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Track(string name, JsonObject properties = default, Func<RawEvent, RawEvent> enrichment = default)
{
if (properties == null)
{
properties = new JsonObject();
}

var trackEvent = new TrackEvent(name, properties);
Process(trackEvent);
Process(trackEvent, enrichment);
}

/// <summary>
Expand All @@ -30,17 +32,18 @@ public virtual void Track(string name, JsonObject properties = default)
/// </summary>
/// <param name="name">Name of the action</param>
/// <param name="properties">Properties to describe the action</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Track<T>(string name, T properties = default) where T : ISerializable
public virtual void Track<T>(string name, T properties = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (properties == null)
{
Track(name);
Track(name, enrichment: enrichment);
}
else
{
string json = JsonUtility.ToJson(properties);
Track(name, JsonUtility.FromJson<JsonObject>(json));
Track(name, JsonUtility.FromJson<JsonObject>(json), enrichment);
}
}

Expand All @@ -59,7 +62,8 @@ public virtual void Track<T>(string name, T properties = default) where T : ISer
/// </summary>
/// <param name="userId">Unique identifier which you recognize a user by in your own database</param>
/// <param name="traits">Traits about the user</param>
public virtual void Identify(string userId, JsonObject traits = default)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Identify(string userId, JsonObject traits = default, Func<RawEvent, RawEvent> enrichment = default)
{
if (traits == null)
{
Expand All @@ -76,7 +80,7 @@ public virtual void Identify(string userId, JsonObject traits = default)
});

var identifyEvent = new IdentifyEvent(userId, traits);
Process(identifyEvent);
Process(identifyEvent, enrichment);
}

/// <summary>
Expand All @@ -93,7 +97,8 @@ public virtual void Identify(string userId, JsonObject traits = default)
/// info.
/// </summary>
/// <param name="traits">Traits about the user</param>
public virtual void Identify(JsonObject traits)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Identify(JsonObject traits, Func<RawEvent, RawEvent> enrichment = default)
{
if (traits == null)
{
Expand All @@ -109,7 +114,7 @@ public virtual void Identify(JsonObject traits)
});

var identifyEvent = new IdentifyEvent(_userInfo._userId, traits);
Process(identifyEvent);
Process(identifyEvent, enrichment);
}

/// <summary>
Expand All @@ -127,17 +132,18 @@ public virtual void Identify(JsonObject traits)
/// </summary>
/// <param name="userId">Unique identifier which you recognize a user by in your own database</param>
/// <param name="traits">Traits about the user</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Identify<T>(string userId, T traits = default) where T : ISerializable
public virtual void Identify<T>(string userId, T traits = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (traits == null)
{
Identify(userId);
Identify(userId, enrichment: enrichment);
}
else
{
string json = JsonUtility.ToJson(traits);
Identify(userId, JsonUtility.FromJson<JsonObject>(json));
Identify(userId, JsonUtility.FromJson<JsonObject>(json), enrichment);
}
}

Expand All @@ -155,17 +161,18 @@ public virtual void Identify<T>(string userId, T traits = default) where T : ISe
/// info.
/// </summary>
/// <param name="traits">Traits about the user</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Identify<T>(T traits) where T : ISerializable
public virtual void Identify<T>(T traits, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (traits == null)
{
Identify(new JsonObject());
Identify(new JsonObject(), enrichment);
}
else
{
string json = JsonUtility.ToJson(traits);
Identify(JsonUtility.FromJson<JsonObject>(json));
Identify(JsonUtility.FromJson<JsonObject>(json), enrichment);
}
}

Expand All @@ -177,14 +184,15 @@ public virtual void Identify<T>(T traits) where T : ISerializable
/// <param name="title">A name for the screen</param>
/// <param name="properties">Properties to add extra information to this call</param>
/// <param name="category">A category to describe the screen</param>
public virtual void Screen(string title, JsonObject properties = default, string category = "")
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Screen(string title, JsonObject properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default)
{
if (properties == null)
{
properties = new JsonObject();
}
var screenEvent = new ScreenEvent(category, title, properties);
Process(screenEvent);
Process(screenEvent, enrichment);
}

/// <summary>
Expand All @@ -195,17 +203,18 @@ public virtual void Screen(string title, JsonObject properties = default, string
/// <param name="title">A name for the screen</param>
/// <param name="properties">Properties to add extra information to this call</param>
/// <param name="category">A category to describe the screen</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Screen<T>(string title, T properties = default, string category = "") where T : ISerializable
public virtual void Screen<T>(string title, T properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (properties == null)
{
Screen(title, category: category);
Screen(title, category: category, enrichment: enrichment);
}
else
{
string json = JsonUtility.ToJson(properties);
Screen(title, JsonUtility.FromJson<JsonObject>(json), category);
Screen(title, JsonUtility.FromJson<JsonObject>(json), category, enrichment);
}
}

Expand All @@ -218,14 +227,15 @@ public virtual void Screen<T>(string title, T properties = default, string categ
/// <param name="title">A name for the page</param>
/// <param name="properties">Properties to add extra information to this call</param>
/// <param name="category">A category to describe the page</param>
public virtual void Page(string title, JsonObject properties = default, string category = "")
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Page(string title, JsonObject properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default)
{
if (properties == null)
{
properties = new JsonObject();
}
var pageEvent = new PageEvent(category, title, properties);
Process(pageEvent);
Process(pageEvent, enrichment);
}

/// <summary>
Expand All @@ -236,17 +246,18 @@ public virtual void Page(string title, JsonObject properties = default, string c
/// <param name="title">A name for the page</param>
/// <param name="properties">Properties to add extra information to this call</param>
/// <param name="category">A category to describe the page</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Page<T>(string title, T properties = default, string category = "") where T : ISerializable
public virtual void Page<T>(string title, T properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (properties == null)
{
Page(title, category: category);
Page(title, category: category, enrichment: enrichment);
}
else
{
string json = JsonUtility.ToJson(properties);
Page(title, JsonUtility.FromJson<JsonObject>(json), category);
Page(title, JsonUtility.FromJson<JsonObject>(json), category, enrichment);
}
}

Expand All @@ -259,14 +270,15 @@ public virtual void Page<T>(string title, T properties = default, string categor
/// </summary>
/// <param name="groupId">Unique identifier which you recognize a group by in your own database</param>
/// <param name="traits">Traits about the group</param>
public virtual void Group(string groupId, JsonObject traits = default)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Group(string groupId, JsonObject traits = default, Func<RawEvent, RawEvent> enrichment = default)
{
if (traits == null)
{
traits = new JsonObject();
}
var groupEvent = new GroupEvent(groupId, traits);
Process(groupEvent);
Process(groupEvent, enrichment);
}

/// <summary>
Expand All @@ -278,17 +290,18 @@ public virtual void Group(string groupId, JsonObject traits = default)
/// </summary>
/// <param name="groupId">Unique identifier which you recognize a group by in your own database</param>
/// <param name="traits">Traits about the group</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
public virtual void Group<T>(string groupId, T traits = default) where T : ISerializable
public virtual void Group<T>(string groupId, T traits = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
{
if (traits == null)
{
Group(groupId);
Group(groupId, enrichment: enrichment);
}
else
{
string json = JsonUtility.ToJson(traits);
Group(groupId, JsonUtility.FromJson<JsonObject>(json));
Group(groupId, JsonUtility.FromJson<JsonObject>(json), enrichment);
}
}

Expand All @@ -301,7 +314,8 @@ public virtual void Group<T>(string groupId, T traits = default) where T : ISeri
/// <param name="newId">The new ID you want to alias the existing ID to. The existing ID will be either
/// the previousId if you have called identify, or the anonymous ID.
/// </param>
public virtual void Alias(string newId)
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
public virtual void Alias(string newId, Func<RawEvent, RawEvent> enrichment = default)
{
var aliasEvent = new AliasEvent(newId, _userInfo._userId ?? _userInfo._anonymousId);

Expand All @@ -312,7 +326,7 @@ public virtual void Alias(string newId)
await Store.Dispatch<UserInfo.SetUserIdAction, UserInfo>(new UserInfo.SetUserIdAction(newId));
});

Process(aliasEvent);
Process(aliasEvent, enrichment);
}
}
}
7 changes: 6 additions & 1 deletion Analytics-CSharp/Segment/Analytics/Timeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,18 @@ public class Timeline
/// initiate the event's lifecycle
/// </summary>
/// <param name="incomingEvent">event to be processed</param>
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
/// <returns>event after processing</returns>
internal RawEvent Process(RawEvent incomingEvent)
internal RawEvent Process(RawEvent incomingEvent, Func<RawEvent, RawEvent> enrichment = default)
{
// Apply before and enrichment types first to start the timeline processing.
RawEvent beforeResult = ApplyPlugins(PluginType.Before, incomingEvent);
// Enrichment is like middleware, a chance to update the event across the board before going to destinations.
RawEvent enrichmentResult = ApplyPlugins(PluginType.Enrichment, beforeResult);
if (enrichment != null)
{
enrichmentResult = enrichment(enrichmentResult);
}

// Make sure not to update the events during this next cycle. Since each destination may want different
// data than other destinations we don't want them conflicting and changing what a real result should be
Expand Down
13 changes: 13 additions & 0 deletions Tests/AnalyticsTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,19 @@ public void TestAnonymousId()
Assert.NotNull(id);
}

[Fact]
public void TestSetAnonymousId()
{
string expected = "foo";
_storage.Setup(o => o.WritePrefs(StorageConstants.AnonymousId, expected)).Verifiable();
string anonIdOld = _analytics.AnonymousId();
_analytics.SetAnonymousId(expected);

string anonIdNew = _analytics.AnonymousId();
Assert.NotEqual(anonIdOld, anonIdNew);
Assert.Equal(expected, anonIdNew);
}

[Fact]
public void TestUserId()
{
Expand Down
Loading
Loading