Skip to content

Commit d081e1f

Browse files
Merge pull request #76 from PostHog/add-uuid-to-events
feat: add UUID generation for events to ensure idempotency
2 parents c9ea39b + 91b210d commit d081e1f

File tree

7 files changed

+53
-7
lines changed

7 files changed

+53
-7
lines changed

.sampo/changesets/heroic-bard-ilmarinen.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,6 @@
22
hex/posthog: minor
33
---
44

5-
Add LLMAnalytics (experimental)
5+
Add LLM Analytics
6+
7+
This release introduces a lightweight LLM analytics toolkit for instrumenting, recording, and analyzing large language model usage across applications that use this repository's SDK. It provides practical observability for teams running LLMs in production and during development.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
hex/posthog: minor
3+
---
4+
5+
Add `uuid` to events on every request to guarantee idempotency in the backend

lib/posthog.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ defmodule PostHog do
7373
event = %{
7474
event: event,
7575
distinct_id: distinct_id,
76+
uuid: UUIDv7.generate(),
7677
timestamp: DateTime.utc_now() |> DateTime.to_iso8601(),
7778
properties: properties
7879
}

test/integration_test.exs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ defmodule PostHog.IntegrationTest do
66

77
require Logger
88

9+
alias PostHog.Integrations.LLMAnalytics.Req, as: LLMReq
910
alias PostHog.LLMAnalytics
1011

1112
@moduletag integration: true
@@ -102,7 +103,7 @@ defmodule PostHog.IntegrationTest do
102103

103104
test "OpenAI Responses", %{wait_fun: wait} do
104105
Req.new()
105-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
106+
|> LLMReq.attach()
106107
|> Req.post!(
107108
url: "https://api.openai.com/v1/responses",
108109
auth: {:bearer, Application.get_env(:posthog, :openai_key)},
@@ -117,7 +118,7 @@ defmodule PostHog.IntegrationTest do
117118

118119
test "OpenAI Chat Completions", %{wait_fun: wait} do
119120
Req.new()
120-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
121+
|> LLMReq.attach()
121122
|> Req.post!(
122123
url: "https://api.openai.com/v1/chat/completions",
123124
auth: {:bearer, Application.get_env(:posthog, :openai_key)},
@@ -137,7 +138,7 @@ defmodule PostHog.IntegrationTest do
137138

138139
test "OpenAI Responses with tool", %{wait_fun: wait} do
139140
Req.new()
140-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
141+
|> LLMReq.attach()
141142
|> Req.post!(
142143
url: "https://api.openai.com/v1/responses",
143144
auth: {:bearer, Application.get_env(:posthog, :openai_key)},
@@ -173,7 +174,7 @@ defmodule PostHog.IntegrationTest do
173174

174175
test "OpenAI Chat Completions with tool", %{wait_fun: wait} do
175176
Req.new()
176-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
177+
|> LLMReq.attach()
177178
|> Req.post!(
178179
url: "https://api.openai.com/v1/chat/completions",
179180
auth: {:bearer, Application.get_env(:posthog, :openai_key)},
@@ -211,7 +212,7 @@ defmodule PostHog.IntegrationTest do
211212

212213
test "Gemini", %{wait_fun: wait} do
213214
Req.new()
214-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
215+
|> LLMReq.attach()
215216
|> Req.post!(
216217
url: "https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent",
217218
headers: [{"x-goog-api-key", Application.get_env(:posthog, :gemini_key)}],
@@ -231,7 +232,7 @@ defmodule PostHog.IntegrationTest do
231232

232233
test "Gemini with tool", %{wait_fun: wait} do
233234
Req.new()
234-
|> PostHog.Integrations.LLMAnalytics.Req.attach()
235+
|> LLMReq.attach()
235236
|> Req.post!(
236237
url: "https://generativelanguage.googleapis.com/v1beta/models/{model}:generateContent",
237238
headers: [{"x-goog-api-key", Application.get_env(:posthog, :gemini_key)}],

test/posthog/handler_test.exs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ defmodule PostHog.HandlerTest do
2020

2121
assert %{
2222
event: "$exception",
23+
uuid: _,
2324
distinct_id: "foo",
2425
properties: %{
2526
"$exception_list": [
@@ -45,6 +46,7 @@ defmodule PostHog.HandlerTest do
4546

4647
assert %{
4748
event: "$exception",
49+
uuid: _,
4850
properties: %{
4951
"$lib": "posthog-elixir",
5052
"$lib_version": _,
@@ -83,6 +85,7 @@ defmodule PostHog.HandlerTest do
8385

8486
assert %{
8587
event: "$exception",
88+
uuid: _,
8689
properties: %{
8790
"$exception_list": [
8891
%{
@@ -103,6 +106,7 @@ defmodule PostHog.HandlerTest do
103106

104107
assert %{
105108
event: "$exception",
109+
uuid: _,
106110
properties: %{
107111
"$exception_list": [
108112
%{
@@ -123,6 +127,7 @@ defmodule PostHog.HandlerTest do
123127

124128
assert %{
125129
event: "$exception",
130+
uuid: _,
126131
properties: %{
127132
"$exception_list": [
128133
%{
@@ -143,6 +148,7 @@ defmodule PostHog.HandlerTest do
143148

144149
assert %{
145150
event: "$exception",
151+
uuid: _,
146152
properties: %{
147153
"$exception_list": [
148154
%{
@@ -189,6 +195,7 @@ defmodule PostHog.HandlerTest do
189195

190196
assert %{
191197
event: "$exception",
198+
uuid: _,
192199
properties: %{
193200
"$exception_list": [
194201
%{
@@ -209,6 +216,7 @@ defmodule PostHog.HandlerTest do
209216

210217
assert %{
211218
event: "$exception",
219+
uuid: _,
212220
properties: %{
213221
"$exception_list": [
214222
%{
@@ -229,6 +237,7 @@ defmodule PostHog.HandlerTest do
229237

230238
assert %{
231239
event: "$exception",
240+
uuid: _,
232241
properties: %{
233242
"$exception_list": [
234243
%{
@@ -249,6 +258,7 @@ defmodule PostHog.HandlerTest do
249258

250259
assert %{
251260
event: "$exception",
261+
uuid: _,
252262
properties: %{
253263
"$exception_list": [
254264
%{

test/posthog/integrations/plug_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ defmodule PostHog.Integrations.PlugTest do
4949

5050
assert %{
5151
event: "$exception",
52+
uuid: _,
5253
properties: properties
5354
} = event
5455

@@ -79,6 +80,7 @@ defmodule PostHog.Integrations.PlugTest do
7980

8081
assert %{
8182
event: "$exception",
83+
uuid: _,
8284
properties: properties
8385
} = event
8486

@@ -109,6 +111,7 @@ defmodule PostHog.Integrations.PlugTest do
109111

110112
assert %{
111113
event: "$exception",
114+
uuid: _,
112115
properties: properties
113116
} = event
114117

@@ -139,6 +142,7 @@ defmodule PostHog.Integrations.PlugTest do
139142

140143
assert %{
141144
event: "$exception",
145+
uuid: _,
142146
properties: properties
143147
} = event
144148

@@ -168,6 +172,7 @@ defmodule PostHog.Integrations.PlugTest do
168172

169173
assert %{
170174
event: "$exception",
175+
uuid: _,
171176
properties: properties
172177
} = event
173178

@@ -197,6 +202,7 @@ defmodule PostHog.Integrations.PlugTest do
197202

198203
assert %{
199204
event: "$exception",
205+
uuid: _,
200206
properties: properties
201207
} = event
202208

test/posthog_test.exs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ defmodule PostHogTest do
2929

3030
assert %{
3131
event: "case tested",
32+
uuid: _,
3233
distinct_id: "distinct_id",
3334
properties: %{},
3435
timestamp: _
@@ -42,6 +43,7 @@ defmodule PostHogTest do
4243

4344
assert %{
4445
event: "case tested",
46+
uuid: _,
4547
distinct_id: "distinct_id",
4648
properties: %{foo: "bar"},
4749
timestamp: _
@@ -59,6 +61,7 @@ defmodule PostHogTest do
5961

6062
assert %{
6163
event: "case tested",
64+
uuid: _,
6265
distinct_id: "distinct_id",
6366
properties: %{
6467
egg: "spam",
@@ -80,6 +83,7 @@ defmodule PostHogTest do
8083

8184
assert %{
8285
event: "case tested",
86+
uuid: _,
8387
distinct_id: "distinct_id",
8488
properties: %{},
8589
timestamp: _
@@ -94,6 +98,7 @@ defmodule PostHogTest do
9498

9599
assert %{
96100
event: "case tested",
101+
uuid: _,
97102
distinct_id: "distinct_id",
98103
properties: %{foo: "bar"},
99104
timestamp: _
@@ -120,13 +125,27 @@ defmodule PostHogTest do
120125

121126
assert %{
122127
event: "case tested",
128+
uuid: _,
123129
distinct_id: "distinct_id",
124130
properties: %{struct: %{hello: nil}, ref: _} = properties,
125131
timestamp: _
126132
} = event
127133

128134
Jason.encode!(properties)
129135
end
136+
137+
test "uuid is valid v7" do
138+
PostHog.bare_capture("uuid test", "distinct_id")
139+
140+
assert [event] = all_captured()
141+
142+
assert is_binary(event.uuid)
143+
144+
assert Regex.match?(
145+
~r/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i,
146+
event.uuid
147+
)
148+
end
130149
end
131150

132151
describe "capture/4" do
@@ -137,6 +156,7 @@ defmodule PostHogTest do
137156

138157
assert %{
139158
event: "case tested",
159+
uuid: _,
140160
distinct_id: "distinct_id",
141161
properties: %{},
142162
timestamp: _
@@ -154,6 +174,7 @@ defmodule PostHogTest do
154174

155175
assert %{
156176
event: "case tested",
177+
uuid: _,
157178
distinct_id: "distinct_id",
158179
properties: %{foo: "bar"},
159180
timestamp: _

0 commit comments

Comments
 (0)