From 9e0199aa1444f74853024b3e3c8083dbbbf3a576 Mon Sep 17 00:00:00 2001 From: Eugene Ivanov <93479789+evgeek@users.noreply.github.com> Date: Fri, 23 Aug 2024 02:25:32 +0300 Subject: [PATCH] Ability to specify uuid when capturing events (#68) * specify uuid * tidy * fix * rename package * rollback * rollback all * init * fix changelog * review fixes --------- Co-authored-by: evgeny.iva --- README.md | 12 +++++++++++ capture.go | 6 +++++- cmd/cli/main.go | 2 +- config.go | 19 ----------------- fixtures/test-enqueue-capture-with-uuid.json | 22 ++++++++++++++++++++ fixtures/test-enqueue-capture.json | 3 ++- fixtures/test-interval-capture.json | 3 ++- fixtures/test-many-capture.json | 9 +++++--- fixtures/test-merge-capture.json | 3 ++- fixtures/test-timestamp-capture.json | 3 ++- go.mod | 5 +---- go.sum | 4 +--- posthog_test.go | 17 +++++---------- 13 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 fixtures/test-enqueue-capture-with-uuid.json diff --git a/README.md b/README.md index 4a263a8..97ece82 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,18 @@ func main() { Properties: posthog.NewProperties(). Set("$current_url", "https://example.com"), }) + + // Capture event with calculated uuid to deduplicate repeated events. + // The library github.com/google/uuid is used + key := myEvent.Id + myEvent.Project + uid := uuid.NewSHA1(uuid.NameSpaceX500, []byte(key)).String() + client.Enqueue(posthog.Capture{ + Uuid: uid, + DistinctId: "test-user", + Event: "$pageview", + Properties: posthog.NewProperties(). + Set("$current_url", "https://example.com"), + }) // Check if a feature flag is enabled isMyFlagEnabled, err := client.IsFeatureEnabled( diff --git a/capture.go b/capture.go index b54acde..31db77d 100644 --- a/capture.go +++ b/capture.go @@ -9,7 +9,9 @@ type Capture struct { // This field is exported for serialization purposes and shouldn't be set by // the application, its value is always overwritten by the library. Type string - + // You don't usually need to specify this field - Posthog will generate it automatically. + // Use it only when necessary - for example, to prevent duplicate events. + Uuid string DistinctId string Event string Timestamp time.Time @@ -44,6 +46,7 @@ func (msg Capture) Validate() error { type CaptureInApi struct { Type string `json:"type"` + Uuid string `json:"uuid"` Library string `json:"library"` LibraryVersion string `json:"library_version"` Timestamp time.Time `json:"timestamp"` @@ -72,6 +75,7 @@ func (msg Capture) APIfy() APIMessage { apified := CaptureInApi{ Type: msg.Type, + Uuid: msg.Uuid, Library: library, LibraryVersion: libraryVersion, Timestamp: msg.Timestamp, diff --git a/cmd/cli/main.go b/cmd/cli/main.go index c58317d..da30b09 100644 --- a/cmd/cli/main.go +++ b/cmd/cli/main.go @@ -91,7 +91,7 @@ func main() { os.Exit(1) } - return nil + return nil } err := app.Run(os.Args) diff --git a/config.go b/config.go index 51ff05d..8e120a1 100644 --- a/config.go +++ b/config.go @@ -3,8 +3,6 @@ package posthog import ( "net/http" "time" - - "github.com/google/uuid" ) // Instances of this type carry the different configuration options that may @@ -79,12 +77,6 @@ type Config struct { // If not set the client will fallback to use a default retry policy. RetryAfter func(int) time.Duration - // A function called by the client to generate unique message identifiers. - // The client uses a UUID generator if none is provided. - // This field is not exported and only exposed internally to let unit tests - // mock the id generation. - uid func() string - // A function called by the client to get the current time, `time.Now` is // used by default. // This field is not exported and only exposed internally to let unit tests @@ -173,10 +165,6 @@ func makeConfig(c Config) Config { c.RetryAfter = DefaultBacko().Duration } - if c.uid == nil { - c.uid = uid - } - if c.now == nil { c.now = time.Now } @@ -187,10 +175,3 @@ func makeConfig(c Config) Config { return c } - -// This function returns a string representation of a UUID, it's the default -// function used for generating unique IDs. -func uid() string { - new_uuid, _ := uuid.NewRandom() - return new_uuid.String() -} diff --git a/fixtures/test-enqueue-capture-with-uuid.json b/fixtures/test-enqueue-capture-with-uuid.json new file mode 100644 index 0000000..fcd5fe7 --- /dev/null +++ b/fixtures/test-enqueue-capture-with-uuid.json @@ -0,0 +1,22 @@ +{ + "api_key": "Csyjlnlun3OzyNJAafdlv", + "batch": [ + { + "distinct_id": "123456", + "event": "Download", + "library": "posthog-go", + "library_version": "1.0.0", + "properties": { + "$lib": "posthog-go", + "$lib_version": "1.0.0", + "application": "PostHog Go", + "platform": "macos", + "version": "1.0.0" + }, + "send_feature_flags": false, + "timestamp": "2009-11-10T23:00:00Z", + "type": "capture", + "uuid": "11111111-1111-1111-1111-111111111111" + } + ] +} diff --git a/fixtures/test-enqueue-capture.json b/fixtures/test-enqueue-capture.json index 0b96c42..2120bfd 100644 --- a/fixtures/test-enqueue-capture.json +++ b/fixtures/test-enqueue-capture.json @@ -15,7 +15,8 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" } ] } diff --git a/fixtures/test-interval-capture.json b/fixtures/test-interval-capture.json index 0b96c42..2120bfd 100644 --- a/fixtures/test-interval-capture.json +++ b/fixtures/test-interval-capture.json @@ -15,7 +15,8 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" } ] } diff --git a/fixtures/test-many-capture.json b/fixtures/test-many-capture.json index 7fbd131..87d52b2 100644 --- a/fixtures/test-many-capture.json +++ b/fixtures/test-many-capture.json @@ -14,7 +14,8 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" }, { "distinct_id": "123456", @@ -29,7 +30,8 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" }, { "distinct_id": "123456", @@ -44,7 +46,8 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" } ] } diff --git a/fixtures/test-merge-capture.json b/fixtures/test-merge-capture.json index d754fdd..e5d7a07 100644 --- a/fixtures/test-merge-capture.json +++ b/fixtures/test-merge-capture.json @@ -16,7 +16,8 @@ }, "send_feature_flags": false, "timestamp": "2015-07-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" } ] } diff --git a/fixtures/test-timestamp-capture.json b/fixtures/test-timestamp-capture.json index 94d6e36..f863e41 100644 --- a/fixtures/test-timestamp-capture.json +++ b/fixtures/test-timestamp-capture.json @@ -15,7 +15,8 @@ }, "send_feature_flags": false, "timestamp": "2015-07-10T23:00:00Z", - "type": "capture" + "type": "capture", + "uuid": "" } ] } diff --git a/go.mod b/go.mod index 036d7d3..043d70d 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,7 @@ module github.com/posthog/posthog-go go 1.18 -require ( - github.com/google/uuid v1.3.0 - github.com/urfave/cli v1.22.5 -) +require github.com/urfave/cli v1.22.5 require ( github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect diff --git a/go.sum b/go.sum index 03d0eb7..74dc48f 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= @@ -12,4 +10,4 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= \ No newline at end of file +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/posthog_test.go b/posthog_test.go index b8d4c89..e36e619 100644 --- a/posthog_test.go +++ b/posthog_test.go @@ -152,8 +152,6 @@ func fixture(name string) string { return string(b) } -func mockId() string { return "I'm unique" } - func mockTime() time.Time { // time.Unix(0, 0) fails on Circle return time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC) @@ -191,11 +189,11 @@ func ExampleCapture() { Endpoint: server.URL, BatchSize: 1, now: mockTime, - uid: mockId, }) defer client.Close() client.Enqueue(Capture{ + Uuid: "00000000-0000-0000-0000-000000000000", Event: "Download", DistinctId: "123456", Properties: Properties{ @@ -225,7 +223,8 @@ func ExampleCapture() { // }, // "send_feature_flags": false, // "timestamp": "2009-11-10T23:00:00Z", - // "type": "capture" + // "type": "capture", + // "uuid": "00000000-0000-0000-0000-000000000000" // } // ] // } @@ -246,7 +245,6 @@ func TestCaptureNoProperties(t *testing.T) { Endpoint: server.URL, BatchSize: 1, now: mockTime, - uid: mockId, DefaultEventProperties: NewProperties().Set("service", "api"), }) defer client.Close() @@ -323,8 +321,9 @@ func TestEnqueue(t *testing.T) { }, "*capture": { - strings.TrimSpace(fixture("test-enqueue-capture.json")), + strings.TrimSpace(fixture("test-enqueue-capture-with-uuid.json")), &Capture{ + Uuid: "11111111-1111-1111-1111-111111111111", Event: "Download", DistinctId: "123456", Properties: Properties{ @@ -346,7 +345,6 @@ func TestEnqueue(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, - uid: mockId, }) defer client.Close() @@ -404,7 +402,6 @@ func TestCaptureWithInterval(t *testing.T) { Verbose: true, Logger: t, now: mockTime, - uid: mockId, }) defer client.Close() @@ -441,7 +438,6 @@ func TestCaptureWithTimestamp(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, - uid: mockId, }) defer client.Close() @@ -475,7 +471,6 @@ func TestCaptureWithDefaultProperties(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, - uid: mockId, }) defer client.Close() @@ -508,7 +503,6 @@ func TestCaptureMany(t *testing.T) { Logger: t, BatchSize: 3, now: mockTime, - uid: mockId, }) defer client.Close() @@ -1711,7 +1705,6 @@ func TestCaptureSendFlags(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, - uid: mockId, PersonalApiKey: "some very secret key", })