Clients call amplitude.Client.Track() to send an event.
The event is added to storages.inMemoryEventStorage (by destination.amplitudePlugin)
Then, destination.amplitudePlugin pulls the events from the store asynchronously and sends them to the Amplitude (server) via internal.AmplitudeHTTPClient.Send()
After, destination.amplitudePlugin waits for the http response and calls internal.AmplitudeResponseProcessor.Process() to transform the response from AmplitudeResponse to AmplitudeProcessorResult
And finally, AmplitudeProcessorResult is used to create types.ExecuteResult and call the client's callback
AmplitudeResponse has 2 status codes and 2 errors:
type AmplitudeResponse struct {
Status int `json:"-"` // An HTTP Response Code
Err error `json:"-"` // An HTTP Response Err
Code int `json:"code"` // Code from the Response Body json
Error string `json:"error"`. // Error from the Response Body json
...
}
Code field is populated from the json response body.
For example:
Two.
Customers get Code=0 via the callback.
When this happens the customers don't know how to handle it.
Does it mean we should retry or drop the message?
This leads to a potential data loss.
A few examples of errors:
Event reached max retry times 1: code=0, events=...
HTTP request failed: Post "https://api2.amplitude.com/batch": unexpected EOF: code=0, events=...
In this change we make internal.AmplitudeResponseProcessor to assign Code from StatusCode (effectively http response status code) if Code=0 (if request failed or json parsing failed).
This will tell the customer the real reason of a failure and the customer will be able to decide what to do with the message.
Testing
new unit tests
Checklist
[x] Does your PR title have the correct title format?
Summary
The Amplitude client is set up like the following:
The flow works like the following:
amplitude.Client.Track()
to send an event.storages.inMemoryEventStorage
(bydestination.amplitudePlugin
)destination.amplitudePlugin
pulls the events from the store asynchronously and sends them to the Amplitude (server) viainternal.AmplitudeHTTPClient.Send()
destination.amplitudePlugin
waits for the http response and callsinternal.AmplitudeResponseProcessor.Process()
to transform the response fromAmplitudeResponse
toAmplitudeProcessorResult
AmplitudeProcessorResult
is used to createtypes.ExecuteResult
and call the client's callbackAmplitudeResponse
has 2 status codes and 2 errors:Code
field is populated from the json response body. For example:See: https://amplitude.com/docs/apis/analytics/batch-event-upload#successsummary
Q: What happens if an http request fails, there's no response body or the body is not json?
The
Code
field will be 0.This leads to many issues:
One. https://github.com/amplitude/analytics-go/pull/64 - a fix, which only takes care of 413
Two. Customers get
Code=0
via the callback. When this happens the customers don't know how to handle it. Does it mean we should retry or drop the message? This leads to a potential data loss.A few examples of errors:
Event reached max retry times 1: code=0, events=...
HTTP request failed: Post "https://api2.amplitude.com/batch": unexpected EOF: code=0, events=...
In this change we make
internal.AmplitudeResponseProcessor
to assignCode
fromStatusCode
(effectively http response status code) ifCode=0
(if request failed or json parsing failed).This will tell the customer the real reason of a failure and the customer will be able to decide what to do with the message.
Testing
Checklist