usagestats: use Amplitude HTTP API endpoint
Created by: attfarhan
Currently, we use Amplitude for product analytics on Sourcegraph Cloud. Our current system uses event logs that are stored in our BigQuery data warehouse, and transforms these events for use in Amplitude, and then sends batches of events to the Amplitude Batch API using a python script.
We want to move to sending events to Amplitude directly from our application. This is the recommended way to instrument went using Amplitude, either through the SDK (client side) or HTTP API (server side). We opted to implement using the HTTP API. For more info see the RFC.
This PR implements sending events to Amplitude via the HTTP API. The main changes are summarized below.
logEvent
mutation
GraphQL API: In the logEvent mutation, we now send a few new fields:
- userProperties: user properties that we get from localStorage. For example, 'isSourcegraphTeammate' or 'hasAddedRepos'.
- deviceID: required for Amplitude. A random ID assigned to the user's device.
- eventID: used for deduplicating
- insertID: used for deduplicating
Frontend event logger
Added getters for device ID, event ID, insert ID.
Webapp
In the SourcegraphWebApp component, we populate the user's localStorage with the latest user properties. We already have requests in the component to query the user's repositories, external services, and current authenticated user. This information is currently enough to get all the user properties we want. I'm wondering how this will scale if we ever need more info, so open to alternatives here.
usagestats
package
Go We add a new codepath in the LogEvent function, where we call publishAmplitudeEvent
if we're on Sourcegraph.com. publishAmplitudeEvent
will get the Amplitude API key, and collect the arguments passed in with the event to create a JSON payload ready to send to Amplitude. This involves pulling different data to populate the userProperties
field completely.
amplitude
package
Then, we call the amplitude.Publish
function. This function simply sends a POST request to the Amplitude HTTP API endpoint with the event.
This is the part I would like the most help on. I have some error handling and retry logic in there that could use some review. Also, is this simple implementation sufficient? I know a lot of Go client libraries for other tools get more complicated with concurrency, channels, etc, etc., but I haven't looked at that stuff for a long time and unsure if it's actually necessary.
Todo before merge:
-
Upload Amplitude API key.