diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f4a33d..e2ae27b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,3 @@ -# Changelog - -## 1.3.0 - 2024-08-14 - -1. Added the ability to explicitly specify the uuid for capturing events. If uuid is not specified, Posthog will calculate it automatically (suitable for most cases). -2. Removed unused config function `uid()`. - ## 1.2.16 * [Full Changelog](https://github.com/PostHog/posthog-go/compare/v1.2.15...v1.2.16) @@ -61,6 +54,8 @@ * [Full Changelog](https://github.com/PostHog/posthog-go/compare/v...v1.2.3) +# Changelog + ## 1.2.2 - 2024-08-08 1. Adds logging to error responses from the PostHog API so that users can see how a call failed (e.g. rate limiting) from the SDK itself. diff --git a/README.md b/README.md index 97ece82..4a263a8 100644 --- a/README.md +++ b/README.md @@ -62,18 +62,6 @@ 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 31db77d..b54acde 100644 --- a/capture.go +++ b/capture.go @@ -9,9 +9,7 @@ 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 @@ -46,7 +44,6 @@ 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"` @@ -75,7 +72,6 @@ func (msg Capture) APIfy() APIMessage { apified := CaptureInApi{ Type: msg.Type, - Uuid: msg.Uuid, Library: library, LibraryVersion: libraryVersion, Timestamp: msg.Timestamp, diff --git a/config.go b/config.go index 8e120a1..51ff05d 100644 --- a/config.go +++ b/config.go @@ -3,6 +3,8 @@ package posthog import ( "net/http" "time" + + "github.com/google/uuid" ) // Instances of this type carry the different configuration options that may @@ -77,6 +79,12 @@ 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 @@ -165,6 +173,10 @@ func makeConfig(c Config) Config { c.RetryAfter = DefaultBacko().Duration } + if c.uid == nil { + c.uid = uid + } + if c.now == nil { c.now = time.Now } @@ -175,3 +187,10 @@ 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 deleted file mode 100644 index fcd5fe7..0000000 --- a/fixtures/test-enqueue-capture-with-uuid.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "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 2120bfd..0b96c42 100644 --- a/fixtures/test-enqueue-capture.json +++ b/fixtures/test-enqueue-capture.json @@ -15,8 +15,7 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" } ] } diff --git a/fixtures/test-interval-capture.json b/fixtures/test-interval-capture.json index 2120bfd..0b96c42 100644 --- a/fixtures/test-interval-capture.json +++ b/fixtures/test-interval-capture.json @@ -15,8 +15,7 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" } ] } diff --git a/fixtures/test-many-capture.json b/fixtures/test-many-capture.json index 87d52b2..7fbd131 100644 --- a/fixtures/test-many-capture.json +++ b/fixtures/test-many-capture.json @@ -14,8 +14,7 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" }, { "distinct_id": "123456", @@ -30,8 +29,7 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" }, { "distinct_id": "123456", @@ -46,8 +44,7 @@ }, "send_feature_flags": false, "timestamp": "2009-11-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" } ] } diff --git a/fixtures/test-merge-capture.json b/fixtures/test-merge-capture.json index e5d7a07..d754fdd 100644 --- a/fixtures/test-merge-capture.json +++ b/fixtures/test-merge-capture.json @@ -16,8 +16,7 @@ }, "send_feature_flags": false, "timestamp": "2015-07-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" } ] } diff --git a/fixtures/test-timestamp-capture.json b/fixtures/test-timestamp-capture.json index f863e41..94d6e36 100644 --- a/fixtures/test-timestamp-capture.json +++ b/fixtures/test-timestamp-capture.json @@ -15,8 +15,7 @@ }, "send_feature_flags": false, "timestamp": "2015-07-10T23:00:00Z", - "type": "capture", - "uuid": "" + "type": "capture" } ] } diff --git a/go.mod b/go.mod index 043d70d..036d7d3 100644 --- a/go.mod +++ b/go.mod @@ -2,7 +2,10 @@ module github.com/posthog/posthog-go go 1.18 -require github.com/urfave/cli v1.22.5 +require ( + github.com/google/uuid v1.3.0 + 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 74dc48f..03d0eb7 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,8 @@ 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= @@ -10,4 +12,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= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= \ No newline at end of file diff --git a/posthog_test.go b/posthog_test.go index 85ffbcf..2daf1c6 100644 --- a/posthog_test.go +++ b/posthog_test.go @@ -152,6 +152,8 @@ 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) @@ -189,11 +191,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{ @@ -223,8 +225,7 @@ func ExampleCapture() { // }, // "send_feature_flags": false, // "timestamp": "2009-11-10T23:00:00Z", - // "type": "capture", - // "uuid": "00000000-0000-0000-0000-000000000000" + // "type": "capture" // } // ] // } @@ -296,9 +297,8 @@ func TestEnqueue(t *testing.T) { }, "*capture": { - strings.TrimSpace(fixture("test-enqueue-capture-with-uuid.json")), + strings.TrimSpace(fixture("test-enqueue-capture.json")), &Capture{ - Uuid: "11111111-1111-1111-1111-111111111111", Event: "Download", DistinctId: "123456", Properties: Properties{ @@ -320,6 +320,7 @@ func TestEnqueue(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, + uid: mockId, }) defer client.Close() @@ -377,6 +378,7 @@ func TestCaptureWithInterval(t *testing.T) { Verbose: true, Logger: t, now: mockTime, + uid: mockId, }) defer client.Close() @@ -413,6 +415,7 @@ func TestCaptureWithTimestamp(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, + uid: mockId, }) defer client.Close() @@ -446,6 +449,7 @@ func TestCaptureWithDefaultProperties(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, + uid: mockId, }) defer client.Close() @@ -478,6 +482,7 @@ func TestCaptureMany(t *testing.T) { Logger: t, BatchSize: 3, now: mockTime, + uid: mockId, }) defer client.Close() @@ -1680,6 +1685,7 @@ func TestCaptureSendFlags(t *testing.T) { Logger: t, BatchSize: 1, now: mockTime, + uid: mockId, PersonalApiKey: "some very secret key", })