mirror of https://github.com/tasks/tasks
Added service and invoker for reporting analytics data
parent
2a0200a715
commit
7f57679469
@ -0,0 +1,119 @@
|
|||||||
|
package com.todoroo.astrid.service.abtesting;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.data.DatabaseDao.ModelUpdateListener;
|
||||||
|
import com.todoroo.andlib.data.TodorooCursor;
|
||||||
|
import com.todoroo.andlib.service.Autowired;
|
||||||
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||||
|
import com.todoroo.andlib.sql.Query;
|
||||||
|
import com.todoroo.astrid.dao.ABTestEventDao;
|
||||||
|
import com.todoroo.astrid.data.ABTestEvent;
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public final class ABTestEventReportingService {
|
||||||
|
|
||||||
|
private static final String KEY_TEST = "test";
|
||||||
|
private static final String KEY_VARIANT = "variant";
|
||||||
|
private static final String KEY_NEW_USER = "new";
|
||||||
|
private static final String KEY_ACTIVE_USER = "activated";
|
||||||
|
private static final String KEY_DAYS = "days";
|
||||||
|
private static final String KEY_DATE = "date";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ABTestEventDao abTestEventDao;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ABTestReporter abTestReporter;
|
||||||
|
|
||||||
|
public ABTestEventReportingService() {
|
||||||
|
DependencyInjectionService.getInstance().inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
abTestEventDao.addListener(new ModelUpdateListener<ABTestEvent>() {
|
||||||
|
@Override
|
||||||
|
public void onModelUpdated(ABTestEvent model) {
|
||||||
|
if (model.getValue(ABTestEvent.REPORTED) == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pushABTestEvent(model);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushABTestEvent(final ABTestEvent model) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
JSONArray payload = new JSONArray().put(jsonFromABTestEvent(model));
|
||||||
|
abTestReporter.post(payload);
|
||||||
|
model.setValue(ABTestEvent.REPORTED, 1);
|
||||||
|
abTestEventDao.saveExisting(model);
|
||||||
|
} catch (JSONException e) {
|
||||||
|
handleException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
handleException(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushAllUnreportedABTestEvents() {
|
||||||
|
TodorooCursor<ABTestEvent> unreported = abTestEventDao.query(Query.select(ABTestEvent.PROPERTIES)
|
||||||
|
.where(ABTestEvent.REPORTED.eq(0)));
|
||||||
|
try {
|
||||||
|
if (unreported.getCount() > 0) {
|
||||||
|
JSONArray payload = jsonArrayFromABTestEvents(unreported);
|
||||||
|
abTestReporter.post(payload);
|
||||||
|
for (unreported.moveToFirst(); !unreported.isAfterLast(); unreported.moveToNext()) {
|
||||||
|
ABTestEvent model = new ABTestEvent(unreported);
|
||||||
|
model.setValue(ABTestEvent.REPORTED, 1);
|
||||||
|
abTestEventDao.saveExisting(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
handleException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
handleException(e);
|
||||||
|
} finally {
|
||||||
|
unreported.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(Exception e) {
|
||||||
|
Log.e("analytics", "analytics-error", e);
|
||||||
|
|
||||||
|
// TODO: Schedule retry
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONObject jsonFromABTestEvent(ABTestEvent model) throws JSONException {
|
||||||
|
JSONObject payload = new JSONObject();
|
||||||
|
payload.put(KEY_TEST, model.getValue(ABTestEvent.TEST_NAME));
|
||||||
|
payload.put(KEY_VARIANT, model.getValue(ABTestEvent.TEST_VARIANT));
|
||||||
|
payload.put(KEY_NEW_USER, model.getValue(ABTestEvent.NEW_USER) > 0 ? true : false);
|
||||||
|
payload.put(KEY_ACTIVE_USER, model.getValue(ABTestEvent.ACTIVATED_USER) > 0 ? true : false);
|
||||||
|
payload.put(KEY_DAYS, model.getValue(ABTestEvent.TIME_INTERVAL));
|
||||||
|
|
||||||
|
long date = model.getValue(ABTestEvent.DATE_RECORDED) / 1000L;
|
||||||
|
payload.put(KEY_DATE, date);
|
||||||
|
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JSONArray jsonArrayFromABTestEvents(TodorooCursor<ABTestEvent> events) throws JSONException {
|
||||||
|
JSONArray result = new JSONArray();
|
||||||
|
for (events.moveToFirst(); !events.isAfterLast(); events.moveToNext()) {
|
||||||
|
ABTestEvent model = new ABTestEvent(events);
|
||||||
|
result.put(jsonFromABTestEvent(model));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,81 @@
|
|||||||
|
package com.todoroo.astrid.service.abtesting;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.NameValuePair;
|
||||||
|
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||||
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
|
import org.apache.http.protocol.HTTP;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import com.todoroo.andlib.service.Autowired;
|
||||||
|
import com.todoroo.andlib.service.DependencyInjectionService;
|
||||||
|
import com.todoroo.andlib.service.RestClient;
|
||||||
|
|
||||||
|
@SuppressWarnings("nls")
|
||||||
|
public class ABTestReporter {
|
||||||
|
|
||||||
|
/** NOTE: these values are development values and will not work on production */
|
||||||
|
private static final String URL = "http://analytics.astrid.com/api/1/retention";
|
||||||
|
private static final String API_KEY = "ryyubd";
|
||||||
|
private static final String API_SECRET = "q9ef3i";
|
||||||
|
|
||||||
|
@Autowired private RestClient restClient;
|
||||||
|
|
||||||
|
public ABTestReporter() {
|
||||||
|
DependencyInjectionService.getInstance().inject(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JSONObject post(JSONArray payload) throws IOException {
|
||||||
|
try {
|
||||||
|
HttpEntity postData = createPostData(payload);
|
||||||
|
if (postData == null)
|
||||||
|
throw new IOException("Unsupported URL encoding");
|
||||||
|
String response = restClient.post(URL, postData);
|
||||||
|
JSONObject object = new JSONObject(response);
|
||||||
|
if (object.getString("status").equals("error")) {
|
||||||
|
throw new IOException("Error reporting ABTestEvent: " +
|
||||||
|
object.optString("message"));
|
||||||
|
}
|
||||||
|
return object;
|
||||||
|
} catch (JSONException e) {
|
||||||
|
throw new IOException(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private HttpEntity createPostData(JSONArray payload) {
|
||||||
|
List<NameValuePair> params = new ArrayList<NameValuePair>();
|
||||||
|
params.add(new BasicNameValuePair("apikey", API_KEY));
|
||||||
|
params.add(new BasicNameValuePair("payload", payload.toString()));
|
||||||
|
|
||||||
|
StringBuilder sigBuilder = new StringBuilder();
|
||||||
|
for(NameValuePair entry : params) {
|
||||||
|
if(entry.getValue() == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
String key = entry.getName();
|
||||||
|
String value = entry.getValue();
|
||||||
|
|
||||||
|
sigBuilder.append(key).append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
sigBuilder.append(API_SECRET);
|
||||||
|
String signature = DigestUtils.md5Hex(sigBuilder.toString());
|
||||||
|
params.add(new BasicNameValuePair("sig", signature));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new UrlEncodedFormEntity(params, HTTP.UTF_8);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue