Skip to content

Commit 25aa513

Browse files
committed
adding method overrides and tests
1 parent 26daeab commit 25aa513

File tree

4 files changed

+492
-9
lines changed

4 files changed

+492
-9
lines changed

src/PostHog/Capture/CaptureExtensions.cs

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,148 @@ public static bool Capture(
6666
groups: null,
6767
sendFeatureFlags: false);
6868

69+
/// <summary>
70+
/// Captures an event with a custom timestamp.
71+
/// </summary>
72+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
73+
/// <param name="distinctId">The identifier you use for the user.</param>
74+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
75+
/// <param name="timestamp">The timestamp when the event occurred.</param>
76+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
77+
public static bool Capture(
78+
this IPostHogClient client,
79+
string distinctId,
80+
string eventName,
81+
DateTimeOffset timestamp)
82+
=> NotNull(client).Capture(
83+
distinctId,
84+
eventName,
85+
properties: null,
86+
groups: null,
87+
sendFeatureFlags: false,
88+
timestamp: timestamp);
89+
90+
/// <summary>
91+
/// Captures an event with a custom timestamp and additional properties.
92+
/// </summary>
93+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
94+
/// <param name="distinctId">The identifier you use for the user.</param>
95+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
96+
/// <param name="timestamp">The timestamp when the event occurred.</param>
97+
/// <param name="properties">Optional: The properties to send along with the event.</param>
98+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
99+
public static bool Capture(
100+
this IPostHogClient client,
101+
string distinctId,
102+
string eventName,
103+
DateTimeOffset timestamp,
104+
Dictionary<string, object>? properties)
105+
=> NotNull(client).Capture(
106+
distinctId,
107+
eventName,
108+
properties: properties,
109+
groups: null,
110+
sendFeatureFlags: false,
111+
timestamp: timestamp);
112+
113+
/// <summary>
114+
/// Captures an event with a custom timestamp and groups.
115+
/// </summary>
116+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
117+
/// <param name="distinctId">The identifier you use for the user.</param>
118+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
119+
/// <param name="timestamp">The timestamp when the event occurred.</param>
120+
/// <param name="groups">A set of groups to send with the event. The groups are identified by their group_type and group_key.</param>
121+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
122+
public static bool Capture(
123+
this IPostHogClient client,
124+
string distinctId,
125+
string eventName,
126+
DateTimeOffset timestamp,
127+
GroupCollection groups)
128+
=> NotNull(client).Capture(
129+
distinctId,
130+
eventName,
131+
properties: null,
132+
groups: groups,
133+
sendFeatureFlags: false,
134+
timestamp: timestamp);
135+
136+
/// <summary>
137+
/// Captures an event with a custom timestamp, properties, and groups.
138+
/// </summary>
139+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
140+
/// <param name="distinctId">The identifier you use for the user.</param>
141+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
142+
/// <param name="timestamp">The timestamp when the event occurred.</param>
143+
/// <param name="properties">Optional: The properties to send along with the event.</param>
144+
/// <param name="groups">Optional: Context of what groups are related to this event, example: { ["company"] = "id:5" }. Can be used to analyze companies instead of users.</param>
145+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
146+
public static bool Capture(
147+
this IPostHogClient client,
148+
string distinctId,
149+
string eventName,
150+
DateTimeOffset timestamp,
151+
Dictionary<string, object>? properties,
152+
GroupCollection? groups)
153+
=> NotNull(client).Capture(
154+
distinctId,
155+
eventName,
156+
properties: properties,
157+
groups: groups,
158+
sendFeatureFlags: false,
159+
timestamp: timestamp);
160+
161+
/// <summary>
162+
/// Captures an event with a custom timestamp and feature flags.
163+
/// </summary>
164+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
165+
/// <param name="distinctId">The identifier you use for the user.</param>
166+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
167+
/// <param name="timestamp">The timestamp when the event occurred.</param>
168+
/// <param name="sendFeatureFlags">If <c>true</c>, feature flags are sent with the captured event.</param>
169+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
170+
public static bool Capture(
171+
this IPostHogClient client,
172+
string distinctId,
173+
string eventName,
174+
DateTimeOffset timestamp,
175+
bool sendFeatureFlags)
176+
=> NotNull(client).Capture(
177+
distinctId,
178+
eventName,
179+
properties: null,
180+
groups: null,
181+
sendFeatureFlags: sendFeatureFlags,
182+
timestamp: timestamp);
183+
184+
/// <summary>
185+
/// Captures an event with a custom timestamp, properties, groups, and feature flags.
186+
/// </summary>
187+
/// <param name="client">The <see cref="IPostHogClient"/>.</param>
188+
/// <param name="distinctId">The identifier you use for the user.</param>
189+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
190+
/// <param name="timestamp">The timestamp when the event occurred.</param>
191+
/// <param name="properties">Optional: The properties to send along with the event.</param>
192+
/// <param name="groups">Optional: Context of what groups are related to this event, example: { ["company"] = "id:5" }. Can be used to analyze companies instead of users.</param>
193+
/// <param name="sendFeatureFlags">Default: <c>false</c>. If <c>true</c>, feature flags are sent with the captured event.</param>
194+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
195+
public static bool Capture(
196+
this IPostHogClient client,
197+
string distinctId,
198+
string eventName,
199+
DateTimeOffset timestamp,
200+
Dictionary<string, object>? properties,
201+
GroupCollection? groups,
202+
bool sendFeatureFlags)
203+
=> NotNull(client).Capture(
204+
distinctId,
205+
eventName,
206+
properties: properties,
207+
groups: groups,
208+
sendFeatureFlags: sendFeatureFlags,
209+
timestamp: timestamp);
210+
69211
/// <summary>
70212
/// Captures an event with properties to set on the user.
71213
/// </summary>
@@ -359,6 +501,11 @@ public static bool CaptureSurveyDismissed(
359501
eventPropertyValue: surveyId,
360502
properties);
361503

504+
505+
506+
507+
508+
362509
static bool CaptureSpecialEvent(
363510
this IPostHogClient client,
364511
string distinctId,

src/PostHog/IPostHogClient.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,24 @@ bool Capture(
8484
GroupCollection? groups,
8585
bool sendFeatureFlags);
8686

87+
/// <summary>
88+
/// Captures an event with a custom timestamp.
89+
/// </summary>
90+
/// <param name="distinctId">The identifier you use for the user.</param>
91+
/// <param name="eventName">Human friendly name of the event. Recommended format [object] [verb] such as "Project created" or "User signed up".</param>
92+
/// <param name="properties">Optional: The properties to send along with the event.</param>
93+
/// <param name="groups">Optional: Context of what groups are related to this event, example: { ["company"] = "id:5" }. Can be used to analyze companies instead of users.</param>
94+
/// <param name="sendFeatureFlags">Default: <c>false</c>. If <c>true</c>, feature flags are sent with the captured event.</param>
95+
/// <param name="timestamp">The timestamp when the event occurred.</param>
96+
/// <returns><c>true</c> if the event was successfully enqueued. Otherwise <c>false</c>.</returns>
97+
bool Capture(
98+
string distinctId,
99+
string eventName,
100+
Dictionary<string, object>? properties,
101+
GroupCollection? groups,
102+
bool sendFeatureFlags,
103+
DateTimeOffset timestamp);
104+
87105
/// <summary>
88106
/// Determines whether a feature is enabled for the specified user.
89107
/// </summary>

src/PostHog/PostHogClient.cs

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -131,19 +131,11 @@ public bool Capture(
131131
GroupCollection? groups,
132132
bool sendFeatureFlags)
133133
{
134-
// Check for custom timestamp in properties
135-
var timestamp = properties?.TryGetValue("timestamp", out var timestampValue) == true &&
136-
(timestampValue is DateTimeOffset customTimestampOffset || timestampValue is DateTime customTimestamp)
137-
? timestampValue is DateTimeOffset dtOffset
138-
? dtOffset
139-
: new DateTimeOffset((DateTime)timestampValue)
140-
: _timeProvider.GetUtcNow();
141-
142134
var capturedEvent = new CapturedEvent(
143135
eventName,
144136
distinctId,
145137
properties,
146-
timestamp: timestamp);
138+
timestamp: _timeProvider.GetUtcNow());
147139

148140
if (groups is { Count: > 0 })
149141
{
@@ -170,6 +162,8 @@ Task<CapturedEvent> BatchTask(CapturedEventBatchContext context) =>
170162
: Task.FromResult(capturedEvent);
171163
}
172164

165+
166+
173167
async Task<CapturedEvent> AddFreshFeatureFlagDataAsync(
174168
IFeatureFlagCache featureFlagCache,
175169
string distinctId,
@@ -581,6 +575,56 @@ public async ValueTask DisposeAsync()
581575
_featureFlagCalledEventCache.Dispose();
582576
_featureFlagsLoader.Dispose();
583577
}
578+
579+
/// <inheritdoc/>
580+
public bool Capture(
581+
string distinctId,
582+
string eventName,
583+
Dictionary<string, object>? properties,
584+
GroupCollection? groups,
585+
bool sendFeatureFlags,
586+
DateTimeOffset timestamp)
587+
{
588+
// Add timestamp to properties as well
589+
properties = AddTimestampToProperties(properties, timestamp);
590+
591+
var capturedEvent = new CapturedEvent(
592+
eventName,
593+
distinctId,
594+
properties,
595+
timestamp: timestamp);
596+
597+
if (groups is { Count: > 0 })
598+
{
599+
capturedEvent.Properties["$groups"] = groups.ToDictionary(g => g.GroupType, g => g.GroupKey);
600+
}
601+
602+
capturedEvent.Properties.Merge(_options.Value.SuperProperties);
603+
604+
var batchItem = new BatchItem<CapturedEvent, CapturedEventBatchContext>(BatchTask);
605+
606+
if (_asyncBatchHandler.Enqueue(batchItem))
607+
{
608+
_logger.LogTraceCaptureCalled(eventName, capturedEvent.Properties.Count, _asyncBatchHandler.Count);
609+
return true;
610+
}
611+
_logger.LogWarnCaptureFailed(eventName, capturedEvent.Properties.Count, _asyncBatchHandler.Count);
612+
return false;
613+
614+
Task<CapturedEvent> BatchTask(CapturedEventBatchContext context) =>
615+
sendFeatureFlags
616+
? AddFreshFeatureFlagDataAsync(context.FeatureFlagCache, distinctId, groups, capturedEvent)
617+
: _featureFlagsLoader.IsLoaded && eventName != "$feature_flag_called"
618+
? AddLocalFeatureFlagDataAsync(distinctId, groups, capturedEvent)
619+
: Task.FromResult(capturedEvent);
620+
}
621+
622+
static Dictionary<string, object>? AddTimestampToProperties(Dictionary<string, object>? properties, DateTimeOffset timestamp)
623+
{
624+
properties ??= new Dictionary<string, object>();
625+
properties["timestamp"] = timestamp;
626+
return properties;
627+
}
584628
}
585629

586630
internal static partial class PostHogClientLoggerExtensions

0 commit comments

Comments
 (0)