Skip to content

Commit 964ddc5

Browse files
authored
support enrichment closure and setAnonymousId (#110)
* implement enrichment closure * add unit tests * fix unit test * add new API SetAnonymousId --------- Co-authored-by: Wenxi Zeng <[email protected]>
1 parent 7354013 commit 964ddc5

File tree

5 files changed

+248
-36
lines changed

5 files changed

+248
-36
lines changed

Analytics-CSharp/Segment/Analytics/Analytics.cs

+16-2
Original file line numberDiff line numberDiff line change
@@ -81,14 +81,15 @@ public Analytics(Configuration configuration)
8181
/// Process a raw event through the system. Useful when one needs to queue and replay events at a later time.
8282
/// </summary>
8383
/// <param name="incomingEvent">An event conforming to RawEvent to be processed in the timeline</param>
84-
public void Process(RawEvent incomingEvent)
84+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
85+
public void Process(RawEvent incomingEvent, Func<RawEvent, RawEvent> enrichment = default)
8586
{
8687
if (!Enable) return;
8788

8889
incomingEvent.ApplyRawEventData(_userInfo);
8990
AnalyticsScope.Launch(AnalyticsDispatcher, () =>
9091
{
91-
Timeline.Process(incomingEvent);
92+
Timeline.Process(incomingEvent, enrichment);
9293
});
9394
}
9495

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

104+
/// <summary>
105+
/// Set the anonymousId.
106+
/// </summary>
107+
/// <param name="anonymousId">Anonymous Id</param>
108+
public virtual void SetAnonymousId(string anonymousId)
109+
{
110+
_userInfo._anonymousId = anonymousId;
111+
AnalyticsScope.Launch(AnalyticsDispatcher, async () =>
112+
{
113+
await Store.Dispatch<UserInfo.SetAnonymousIdAction, UserInfo>(new UserInfo.SetAnonymousIdAction(anonymousId));
114+
});
115+
}
116+
103117

104118
/// <summary>
105119
/// Retrieve the userId registered by a previous <see cref="Identify(string,JsonObject)"/> call

Analytics-CSharp/Segment/Analytics/Events.cs

+46-32
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using global::System.Runtime.Serialization;
23
using Segment.Serialization;
34

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

2224
var trackEvent = new TrackEvent(name, properties);
23-
Process(trackEvent);
25+
Process(trackEvent, enrichment);
2426
}
2527

2628
/// <summary>
@@ -30,17 +32,18 @@ public virtual void Track(string name, JsonObject properties = default)
3032
/// </summary>
3133
/// <param name="name">Name of the action</param>
3234
/// <param name="properties">Properties to describe the action</param>
35+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
3336
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
34-
public virtual void Track<T>(string name, T properties = default) where T : ISerializable
37+
public virtual void Track<T>(string name, T properties = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
3538
{
3639
if (properties == null)
3740
{
38-
Track(name);
41+
Track(name, enrichment: enrichment);
3942
}
4043
else
4144
{
4245
string json = JsonUtility.ToJson(properties);
43-
Track(name, JsonUtility.FromJson<JsonObject>(json));
46+
Track(name, JsonUtility.FromJson<JsonObject>(json), enrichment);
4447
}
4548
}
4649

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

7882
var identifyEvent = new IdentifyEvent(userId, traits);
79-
Process(identifyEvent);
83+
Process(identifyEvent, enrichment);
8084
}
8185

8286
/// <summary>
@@ -93,7 +97,8 @@ public virtual void Identify(string userId, JsonObject traits = default)
9397
/// info.
9498
/// </summary>
9599
/// <param name="traits">Traits about the user</param>
96-
public virtual void Identify(JsonObject traits)
100+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
101+
public virtual void Identify(JsonObject traits, Func<RawEvent, RawEvent> enrichment = default)
97102
{
98103
if (traits == null)
99104
{
@@ -109,7 +114,7 @@ public virtual void Identify(JsonObject traits)
109114
});
110115

111116
var identifyEvent = new IdentifyEvent(_userInfo._userId, traits);
112-
Process(identifyEvent);
117+
Process(identifyEvent, enrichment);
113118
}
114119

115120
/// <summary>
@@ -127,17 +132,18 @@ public virtual void Identify(JsonObject traits)
127132
/// </summary>
128133
/// <param name="userId">Unique identifier which you recognize a user by in your own database</param>
129134
/// <param name="traits">Traits about the user</param>
135+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
130136
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
131-
public virtual void Identify<T>(string userId, T traits = default) where T : ISerializable
137+
public virtual void Identify<T>(string userId, T traits = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
132138
{
133139
if (traits == null)
134140
{
135-
Identify(userId);
141+
Identify(userId, enrichment: enrichment);
136142
}
137143
else
138144
{
139145
string json = JsonUtility.ToJson(traits);
140-
Identify(userId, JsonUtility.FromJson<JsonObject>(json));
146+
Identify(userId, JsonUtility.FromJson<JsonObject>(json), enrichment);
141147
}
142148
}
143149

@@ -155,17 +161,18 @@ public virtual void Identify<T>(string userId, T traits = default) where T : ISe
155161
/// info.
156162
/// </summary>
157163
/// <param name="traits">Traits about the user</param>
164+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
158165
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
159-
public virtual void Identify<T>(T traits) where T : ISerializable
166+
public virtual void Identify<T>(T traits, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
160167
{
161168
if (traits == null)
162169
{
163-
Identify(new JsonObject());
170+
Identify(new JsonObject(), enrichment);
164171
}
165172
else
166173
{
167174
string json = JsonUtility.ToJson(traits);
168-
Identify(JsonUtility.FromJson<JsonObject>(json));
175+
Identify(JsonUtility.FromJson<JsonObject>(json), enrichment);
169176
}
170177
}
171178

@@ -177,14 +184,15 @@ public virtual void Identify<T>(T traits) where T : ISerializable
177184
/// <param name="title">A name for the screen</param>
178185
/// <param name="properties">Properties to add extra information to this call</param>
179186
/// <param name="category">A category to describe the screen</param>
180-
public virtual void Screen(string title, JsonObject properties = default, string category = "")
187+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
188+
public virtual void Screen(string title, JsonObject properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default)
181189
{
182190
if (properties == null)
183191
{
184192
properties = new JsonObject();
185193
}
186194
var screenEvent = new ScreenEvent(category, title, properties);
187-
Process(screenEvent);
195+
Process(screenEvent, enrichment);
188196
}
189197

190198
/// <summary>
@@ -195,17 +203,18 @@ public virtual void Screen(string title, JsonObject properties = default, string
195203
/// <param name="title">A name for the screen</param>
196204
/// <param name="properties">Properties to add extra information to this call</param>
197205
/// <param name="category">A category to describe the screen</param>
206+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
198207
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
199-
public virtual void Screen<T>(string title, T properties = default, string category = "") where T : ISerializable
208+
public virtual void Screen<T>(string title, T properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
200209
{
201210
if (properties == null)
202211
{
203-
Screen(title, category: category);
212+
Screen(title, category: category, enrichment: enrichment);
204213
}
205214
else
206215
{
207216
string json = JsonUtility.ToJson(properties);
208-
Screen(title, JsonUtility.FromJson<JsonObject>(json), category);
217+
Screen(title, JsonUtility.FromJson<JsonObject>(json), category, enrichment);
209218
}
210219
}
211220

@@ -218,14 +227,15 @@ public virtual void Screen<T>(string title, T properties = default, string categ
218227
/// <param name="title">A name for the page</param>
219228
/// <param name="properties">Properties to add extra information to this call</param>
220229
/// <param name="category">A category to describe the page</param>
221-
public virtual void Page(string title, JsonObject properties = default, string category = "")
230+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
231+
public virtual void Page(string title, JsonObject properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default)
222232
{
223233
if (properties == null)
224234
{
225235
properties = new JsonObject();
226236
}
227237
var pageEvent = new PageEvent(category, title, properties);
228-
Process(pageEvent);
238+
Process(pageEvent, enrichment);
229239
}
230240

231241
/// <summary>
@@ -236,17 +246,18 @@ public virtual void Page(string title, JsonObject properties = default, string c
236246
/// <param name="title">A name for the page</param>
237247
/// <param name="properties">Properties to add extra information to this call</param>
238248
/// <param name="category">A category to describe the page</param>
249+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
239250
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
240-
public virtual void Page<T>(string title, T properties = default, string category = "") where T : ISerializable
251+
public virtual void Page<T>(string title, T properties = default, string category = "", Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
241252
{
242253
if (properties == null)
243254
{
244-
Page(title, category: category);
255+
Page(title, category: category, enrichment: enrichment);
245256
}
246257
else
247258
{
248259
string json = JsonUtility.ToJson(properties);
249-
Page(title, JsonUtility.FromJson<JsonObject>(json), category);
260+
Page(title, JsonUtility.FromJson<JsonObject>(json), category, enrichment);
250261
}
251262
}
252263

@@ -259,14 +270,15 @@ public virtual void Page<T>(string title, T properties = default, string categor
259270
/// </summary>
260271
/// <param name="groupId">Unique identifier which you recognize a group by in your own database</param>
261272
/// <param name="traits">Traits about the group</param>
262-
public virtual void Group(string groupId, JsonObject traits = default)
273+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
274+
public virtual void Group(string groupId, JsonObject traits = default, Func<RawEvent, RawEvent> enrichment = default)
263275
{
264276
if (traits == null)
265277
{
266278
traits = new JsonObject();
267279
}
268280
var groupEvent = new GroupEvent(groupId, traits);
269-
Process(groupEvent);
281+
Process(groupEvent, enrichment);
270282
}
271283

272284
/// <summary>
@@ -278,17 +290,18 @@ public virtual void Group(string groupId, JsonObject traits = default)
278290
/// </summary>
279291
/// <param name="groupId">Unique identifier which you recognize a group by in your own database</param>
280292
/// <param name="traits">Traits about the group</param>
293+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
281294
/// <typeparam name="T">Type that implements <see cref="ISerializable"/></typeparam>
282-
public virtual void Group<T>(string groupId, T traits = default) where T : ISerializable
295+
public virtual void Group<T>(string groupId, T traits = default, Func<RawEvent, RawEvent> enrichment = default) where T : ISerializable
283296
{
284297
if (traits == null)
285298
{
286-
Group(groupId);
299+
Group(groupId, enrichment: enrichment);
287300
}
288301
else
289302
{
290303
string json = JsonUtility.ToJson(traits);
291-
Group(groupId, JsonUtility.FromJson<JsonObject>(json));
304+
Group(groupId, JsonUtility.FromJson<JsonObject>(json), enrichment);
292305
}
293306
}
294307

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

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

315-
Process(aliasEvent);
329+
Process(aliasEvent, enrichment);
316330
}
317331
}
318332
}

Analytics-CSharp/Segment/Analytics/Timeline.cs

+6-1
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,18 @@ public class Timeline
2828
/// initiate the event's lifecycle
2929
/// </summary>
3030
/// <param name="incomingEvent">event to be processed</param>
31+
/// <param name="enrichment">a closure that enables enrichment on the generated event</param>
3132
/// <returns>event after processing</returns>
32-
internal RawEvent Process(RawEvent incomingEvent)
33+
internal RawEvent Process(RawEvent incomingEvent, Func<RawEvent, RawEvent> enrichment = default)
3334
{
3435
// Apply before and enrichment types first to start the timeline processing.
3536
RawEvent beforeResult = ApplyPlugins(PluginType.Before, incomingEvent);
3637
// Enrichment is like middleware, a chance to update the event across the board before going to destinations.
3738
RawEvent enrichmentResult = ApplyPlugins(PluginType.Enrichment, beforeResult);
39+
if (enrichment != null)
40+
{
41+
enrichmentResult = enrichment(enrichmentResult);
42+
}
3843

3944
// Make sure not to update the events during this next cycle. Since each destination may want different
4045
// data than other destinations we don't want them conflicting and changing what a real result should be

Tests/AnalyticsTest.cs

+13
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ public void TestAnonymousId()
6565
Assert.NotNull(id);
6666
}
6767

68+
[Fact]
69+
public void TestSetAnonymousId()
70+
{
71+
string expected = "foo";
72+
_storage.Setup(o => o.WritePrefs(StorageConstants.AnonymousId, expected)).Verifiable();
73+
string anonIdOld = _analytics.AnonymousId();
74+
_analytics.SetAnonymousId(expected);
75+
76+
string anonIdNew = _analytics.AnonymousId();
77+
Assert.NotEqual(anonIdOld, anonIdNew);
78+
Assert.Equal(expected, anonIdNew);
79+
}
80+
6881
[Fact]
6982
public void TestUserId()
7083
{

0 commit comments

Comments
 (0)