-
Notifications
You must be signed in to change notification settings - Fork 38
Improper errors/exceptions message #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Im fully agree! |
Just bumped into this today. This is wild. First off, if you add Here's some sample code you can copy-paste that puts this info into the exceptions: MyMixPanelApiimport com.mixpanel.mixpanelapi.ClientDelivery;
import com.mixpanel.mixpanelapi.MixpanelMessageException;
import com.mixpanel.mixpanelapi.MixpanelServerException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
public class MyMixpanelAPI {
private static final int BUFFER_SIZE = 256;
private static final int CONNECT_TIMEOUT_MILLIS = 2000;
private static final int READ_TIMEOUT_MILLIS = 10000;
private static final int BATCH_SIZE = 50;
protected final String mEventsEndpoint;
protected final String mPeopleEndpoint;
protected final String mGroupsEndpoint;
public MyMixpanelAPI() {
this("https://api.mixpanel.com/track", "https://api.mixpanel.com/engage", "https://api.mixpanel.com/groups");
}
public MyMixpanelAPI(String eventsEndpoint, String peopleEndpoint) {
this(eventsEndpoint, peopleEndpoint, "https://api.mixpanel.com/groups");
}
public MyMixpanelAPI(String eventsEndpoint, String peopleEndpoint, String groupsEndpoint) {
if (eventsEndpoint == null || peopleEndpoint == null || groupsEndpoint == null) {
throw new IllegalArgumentException("Endpoints cannot be null");
}
this.mEventsEndpoint = eventsEndpoint;
this.mPeopleEndpoint = peopleEndpoint;
this.mGroupsEndpoint = groupsEndpoint;
}
public void sendMessage(JSONObject message) throws MixpanelMessageException, IOException, InvocationTargetException, IllegalAccessException {
if (message == null) {
throw new IOException("Message cannot be null");
}
ClientDelivery delivery = new ClientDelivery();
delivery.addMessage(message);
this.deliver(delivery);
}
public void deliver(ClientDelivery toSend) throws IOException, InvocationTargetException, IllegalAccessException {
deliver(toSend, false);
}
public void deliver(ClientDelivery toSend, boolean useIpAddress) throws IOException, InvocationTargetException, IllegalAccessException {
if (toSend == null) {
throw new IllegalArgumentException("ClientDelivery cannot be null");
}
String ipParameter = "ip=0&verbose=1";
try {
// Process events
String eventsUrl = this.mEventsEndpoint + "?" + ipParameter;
Method getEventsMessagesMethod = toSend.getClass().getDeclaredMethod("getEventsMessages");
getEventsMessagesMethod.setAccessible(true);
@SuppressWarnings("unchecked")
List<JSONObject> events = (List<JSONObject>) getEventsMessagesMethod.invoke(toSend);
sendMessages(events, eventsUrl);
// Process people
String peopleUrl = this.mPeopleEndpoint + "?" + ipParameter;
Method getPeopleMessagesMethod = toSend.getClass().getDeclaredMethod("getPeopleMessages");
getPeopleMessagesMethod.setAccessible(true);
@SuppressWarnings("unchecked")
List<JSONObject> people = (List<JSONObject>) getPeopleMessagesMethod.invoke(toSend);
sendMessages(people, peopleUrl);
// Process groups
String groupsUrl = this.mGroupsEndpoint + "?" + ipParameter;
Method getGroupMessagesMethod = toSend.getClass().getDeclaredMethod("getGroupMessages");
getGroupMessagesMethod.setAccessible(true);
List<JSONObject> groupMessages = (List<JSONObject>) getGroupMessagesMethod.invoke(toSend);
sendMessages(groupMessages, groupsUrl);
} catch (IOException | NoSuchMethodException e) {
throw new IOException("Failed to deliver messages to Mixpanel", e);
}
}
protected String encodeDataString(String dataString) throws UnsupportedEncodingException {
if (dataString == null) {
throw new IllegalArgumentException("Data string cannot be null");
}
try {
byte[] utf8data = dataString.getBytes(StandardCharsets.UTF_8);
String base64data = new String(Base64Coder.encode(utf8data));
return URLEncoder.encode(base64data, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
throw new UnsupportedEncodingException("Failed to encode data string: " + e.getMessage());
}
}
protected boolean sendData(String dataString, String endpointUrl) throws IOException {
if (dataString == null || endpointUrl == null) {
throw new IllegalArgumentException("Data string and endpoint URL cannot be null");
}
HttpURLConnection conn = null;
OutputStream postStream = null;
InputStream responseStream = null;
InputStream errorStream = null;
try {
URL endpoint = new URL(endpointUrl);
conn = (HttpURLConnection) endpoint.openConnection();
conn.setReadTimeout(READ_TIMEOUT_MILLIS);
conn.setConnectTimeout(CONNECT_TIMEOUT_MILLIS);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf8");
String encodedData = encodeDataString(dataString);
String encodedQuery = "data=" + encodedData;
// Send data
postStream = conn.getOutputStream();
postStream.write(encodedQuery.getBytes(StandardCharsets.UTF_8));
postStream.flush();
// Read response
try {
responseStream = conn.getInputStream();
String response = slurp(responseStream);
if (!response.contains("\"status\":1")) {
throw new IOException("Server response: " + response + "\n\ndataString: " + dataString);
}
return true;
} catch (IOException e) {
// Try to read error stream if available
errorStream = conn.getErrorStream();
if (errorStream != null) {
String errorResponse = slurp(errorStream);
throw new IOException("Failed to send data to Mixpanel. Server response: " + errorResponse, e);
}
throw e;
}
} catch (SocketTimeoutException e) {
throw new IOException("Connection timed out while sending data to Mixpanel", e);
} catch (IOException e) {
throw new IOException("Failed to send data to Mixpanel", e);
} finally {
// Close streams in reverse order of creation
closeQuietly(errorStream);
closeQuietly(responseStream);
closeQuietly(postStream);
if (conn != null) {
conn.disconnect();
}
}
}
private void sendMessages(List<JSONObject> messages, String endpointUrl) throws IOException {
if (messages == null || endpointUrl == null) {
throw new IllegalArgumentException("Messages list and endpoint URL cannot be null");
}
for (int i = 0; i < messages.size(); i += BATCH_SIZE) {
int endIndex = Math.min(i + BATCH_SIZE, messages.size());
List<JSONObject> batch = messages.subList(i, endIndex);
if (!batch.isEmpty()) {
try {
String messagesString = dataString(batch);
boolean accepted = sendData(messagesString, endpointUrl);
if (!accepted) {
throw new MixpanelServerException("Server refused to accept messages, they may be malformed.", batch);
}
} catch (IOException e) {
throw new IOException("Failed to send batch " + (i / BATCH_SIZE + 1), e);
}
}
}
}
private String dataString(List<JSONObject> messages) {
if (messages == null) {
throw new IllegalArgumentException("Messages list cannot be null");
}
JSONArray array = new JSONArray();
for (JSONObject message : messages) {
if (message != null) {
array.put(message);
}
}
return array.toString();
}
private String slurp(InputStream in) throws IOException {
if (in == null) {
throw new IllegalArgumentException("InputStream cannot be null");
}
StringBuilder out = new StringBuilder();
try (InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8)) {
char[] readBuffer = new char[BUFFER_SIZE];
int readCount;
while ((readCount = reader.read(readBuffer)) != -1) {
out.append(readBuffer, 0, readCount);
}
}
return out.toString();
}
private void closeQuietly(AutoCloseable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (Exception e) {
System.err.println("Failed to close resource: " + e.getMessage());
}
}
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
When you don't supply the token or the token value is given null the SDK throws exception with message mix panel Server refused to accept messages, they may be malformed which i think is very confusing. I have found (on the internet) that it also throws the same error due to some other errors as well.
It would be good and helpful to have more proper and meaningful errors for such scenarios.
I think the sendData() method could be modified to return something more diverse and meaningful.
The text was updated successfully, but these errors were encountered: