check buffering events (#952)

* check buffering events
* use the claim permanent url for buffer events
* update request parameters
* hash user ids for buffer events
* update buffer event endpoint
This commit is contained in:
Akinwale Ariwodola 2020-07-21 19:30:45 +01:00 committed by GitHub
parent 481c50f465
commit c772cf2ead
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 0 deletions

View file

@ -0,0 +1,65 @@
package io.lbry.browser.tasks;
import android.os.AsyncTask;
import android.util.Log;
import org.json.JSONObject;
import java.util.concurrent.TimeUnit;
import io.lbry.browser.utils.Helper;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public class BufferEventTask extends AsyncTask<Void, Void, Void> {
private static final String TAG = "LbryBufferEvent";
private static final String ENDPOINT = "https://collector-service.api.lbry.tv/api/v1/events/video";
private String streamUrl;
private String userIdHash;
private long streamDuration;
private long streamPosition;
private long bufferDuration;
public BufferEventTask(String streamUrl, long streamDuration, long streamPosition, long bufferDuration, String userIdHash) {
this.streamUrl = streamUrl;
this.bufferDuration = bufferDuration;
this.streamDuration = streamDuration;
this.streamPosition = streamPosition;
this.userIdHash = userIdHash;
}
protected Void doInBackground(Void... params) {
JSONObject requestBody = new JSONObject();
JSONObject data = new JSONObject();
try {
data.put("url", streamUrl);
data.put("position", streamPosition);
data.put("stream_duration", streamDuration);
data.put("duration", bufferDuration);
requestBody.put("device", "android");
requestBody.put("type", "buffering");
requestBody.put("client", userIdHash);
requestBody.put("data", data);
RequestBody body = RequestBody.create(requestBody.toString(), Helper.JSON_MEDIA_TYPE);
Request request = new Request.Builder().url(ENDPOINT).post(body).build();
OkHttpClient client = new OkHttpClient.Builder().
writeTimeout(60, TimeUnit.SECONDS).
readTimeout(60, TimeUnit.SECONDS).
build();
Response response = client.newCall(request).execute();
String responseString = response.body().string();
Log.d(TAG, String.format("buffer event sent: %s", responseString));
} catch (Exception ex) {
// we don't want to fail if a buffer event fails to register
Log.d(TAG, String.format("buffer event log failed: %s", ex.getMessage()), ex);
}
return null;
}
}

View file

@ -120,6 +120,7 @@ import io.lbry.browser.model.UrlSuggestion;
import io.lbry.browser.model.WalletBalance;
import io.lbry.browser.model.lbryinc.Reward;
import io.lbry.browser.model.lbryinc.Subscription;
import io.lbry.browser.tasks.BufferEventTask;
import io.lbry.browser.tasks.CommentCreateWithTipTask;
import io.lbry.browser.tasks.CommentListHandler;
import io.lbry.browser.tasks.CommentListTask;
@ -165,6 +166,7 @@ public class FileViewFragment extends BaseFragment implements
WalletBalanceListener {
private static final int RELATED_CONTENT_SIZE = 16;
private static final String DEFAULT_PLAYBACK_SPEED = "1x";
private static final String CDN_PREFIX = "https://cdn.lbryplayer.xyz";
private PlayerControlView castControlView;
private Player currentPlayer;
@ -292,6 +294,27 @@ public class FileViewFragment extends BaseFragment implements
loadingNewClaim = false;
}
} else if (playbackState == Player.STATE_BUFFERING) {
if (MainActivity.appPlayer != null && MainActivity.appPlayer.getCurrentPosition() > 0) {
// we only want to log a buffer event after the media has already started playing
String mediaSourceUrl = getStreamingUrl();
long duration = MainActivity.appPlayer.getDuration();
long position = MainActivity.appPlayer.getCurrentPosition();
// TODO: Determine a hash for the userId
String userIdHash = Helper.SHA256(Lbryio.currentUser != null ? String.valueOf(Lbryio.currentUser.getId()) : "0");
if (mediaSourceUrl.startsWith(CDN_PREFIX)) {
BufferEventTask bufferEvent = new BufferEventTask(claim.getPermanentUrl(), duration, position, 1, userIdHash);
bufferEvent.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
} else {
// sdk stream buffer events should be handled differently
Bundle bundle = new Bundle();
bundle.putString("url", claim.getPermanentUrl());
bundle.putLong("stream_duration", duration);
bundle.putLong("stream_position", position);
bundle.putString("user_id_hash", userIdHash);
LbryAnalytics.logEvent(LbryAnalytics.EVENT_BUFFER, bundle);
}
}
showBuffering();
} else {
hideBuffering();

View file

@ -30,6 +30,8 @@ import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.google.android.gms.common.util.Hex;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@ -37,6 +39,9 @@ import org.json.JSONObject;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
@ -766,4 +771,14 @@ public final class Helper {
}
return id.toString();
}
public static String SHA256(String value) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hash = digest.digest(value.getBytes("UTF-8"));
return Hex.bytesToStringLowercase(hash);
} catch (NoSuchAlgorithmException | UnsupportedEncodingException ex) {
return null;
}
}
}

View file

@ -11,6 +11,7 @@ public class LbryAnalytics {
public static final String EVENT_APP_ERROR = "app_error";
public static final String EVENT_APP_LAUNCH = "app_launch";
public static final String EVENT_COMMENT_CREATE = "comment_create";
public static final String EVENT_BUFFER = "buffer";
public static final String EVENT_EMAIL_ADDED = "email_added";
public static final String EVENT_EMAIL_VERIFIED = "email_verified";
public static final String EVENT_FIRST_RUN_COMPLETED = "first_run_completed";