Add measurements, improve MSL insert.

This commit is contained in:
Greyson Parrelli
2021-08-30 15:07:03 -04:00
parent 1241f4c0e9
commit bca2205945
10 changed files with 430 additions and 52 deletions

View File

@@ -178,12 +178,18 @@ public final class SignalLocalMetrics {
public static final class GroupMessageSend {
private static final String NAME = "group-message-send";
private static final String SPLIT_DB_INSERT = "db-insert";
private static final String SPLIT_JOB_ENQUEUE = "job-enqueue";
private static final String SPLIT_JOB_PRE_NETWORK = "job-pre-network";
private static final String SPLIT_NETWORK = "network";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update";
private static final String SPLIT_DB_INSERT = "db-insert";
private static final String SPLIT_JOB_ENQUEUE = "job-enqueue";
private static final String SPLIT_JOB_PRE_NETWORK = "job-pre-network";
private static final String SPLIT_SENDER_KEY_SHARED = "sk-shared";
private static final String SPLIT_ENCRYPTION = "encryption";
private static final String SPLIT_NETWORK_SENDER_KEY = "network-sk";
private static final String SPLIT_NETWORK_SENDER_KEY_SYNC = "network-sk-sync";
private static final String SPLIT_MSL_SENDER_KEY = "msl-sk";
private static final String SPLIT_NETWORK_LEGACY = "network-legacy";
private static final String SPLIT_NETWORK_LEGACY_SYNC = "network-legacy-sync";
private static final String SPLIT_JOB_POST_NETWORK = "job-post-network";
private static final String SPLIT_UI_UPDATE = "ui-update";
private static final Map<Long, String> ID_MAP = new HashMap<>();
@@ -205,14 +211,44 @@ public final class SignalLocalMetrics {
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_ENQUEUE);
}
public static void onNetworkStarted(long messageId) {
public static void onSenderKeyStarted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_JOB_PRE_NETWORK);
}
public static void onNetworkFinished(long messageId) {
public static void onSenderKeyShared(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK);
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_SENDER_KEY_SHARED);
}
public static void onSenderKeyEncrypted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_ENCRYPTION);
}
public static void onSenderKeyMessageSent(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_SENDER_KEY);
}
public static void onSenderKeySyncSent(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_SENDER_KEY_SYNC);
}
public static void onSenderKeyMslInserted(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_MSL_SENDER_KEY);
}
public static void onLegacyMessageSent(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_LEGACY);
}
public static void onLegacySyncFinished(long messageId) {
if (!ID_MAP.containsKey(messageId)) return;
LocalMetrics.getInstance().split(requireId(messageId), SPLIT_NETWORK_LEGACY_SYNC);
}
public static void onJobFinished(long messageId) {

View File

@@ -4,6 +4,7 @@ import android.content.ContentValues;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.annimon.stream.Stream;
@@ -19,9 +20,13 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public final class SqlUtil {
/** The maximum number of arguments (i.e. question marks) allowed in a SQL statement. */
private static final int MAX_QUERY_ARGS = 999;
private SqlUtil() {}
public static boolean tableExists(@NonNull SQLiteDatabase db, @NonNull String table) {
@@ -155,6 +160,41 @@ public final class SqlUtil {
return new Query(column + " IN (" + query.toString() + ")", buildArgs(args));
}
public static @NonNull List<Query> buildCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList) {
return buildCustomCollectionQuery(query, argList, MAX_QUERY_ARGS);
}
@VisibleForTesting
static @NonNull List<Query> buildCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList, int maxQueryArgs) {
int batchSize = maxQueryArgs / argList.get(0).length;
return Util.chunk(argList, batchSize)
.stream()
.map(argBatch -> buildSingleCustomCollectionQuery(query, argBatch))
.collect(Collectors.toList());
}
private static @NonNull Query buildSingleCustomCollectionQuery(@NonNull String query, @NonNull List<String[]> argList) {
StringBuilder outputQuery = new StringBuilder();
String[] outputArgs = new String[argList.get(0).length * argList.size()];
int argPosition = 0;
for (int i = 0, len = argList.size(); i < len; i++) {
outputQuery.append("(").append(query).append(")");
if (i < len - 1) {
outputQuery.append(" OR ");
}
String[] args = argList.get(i);
for (String arg : args) {
outputArgs[argPosition] = arg;
argPosition++;
}
}
return new Query(outputQuery.toString(), outputArgs);
}
public static @NonNull Query buildQuery(@NonNull String where, @NonNull Object... args) {
return new SqlUtil.Query(where, SqlUtil.buildArgs(args));
}
@@ -168,6 +208,68 @@ public final class SqlUtil {
return output;
}
public static List<Query> buildBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues) {
return buildBulkInsert(tableName, columns, contentValues, MAX_QUERY_ARGS);
}
@VisibleForTesting
static List<Query> buildBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues, int maxQueryArgs) {
int batchSize = maxQueryArgs / columns.length;
return Util.chunk(contentValues, batchSize)
.stream()
.map(batch -> buildSingleBulkInsert(tableName, columns, batch))
.collect(Collectors.toList());
}
private static Query buildSingleBulkInsert(@NonNull String tableName, @NonNull String[] columns, List<ContentValues> contentValues) {
StringBuilder builder = new StringBuilder();
builder.append("INSERT INTO ").append(tableName).append(" (");
for (int i = 0; i < columns.length; i++) {
builder.append(columns[i]);
if (i < columns.length - 1) {
builder.append(", ");
}
}
builder.append(") VALUES ");
StringBuilder placeholder = new StringBuilder();
placeholder.append("(");
for (int i = 0; i < columns.length; i++) {
placeholder.append("?");
if (i < columns.length - 1) {
placeholder.append(", ");
}
}
placeholder.append(")");
for (int i = 0, len = contentValues.size(); i < len; i++) {
builder.append(placeholder);
if (i < len - 1) {
builder.append(", ");
}
}
String query = builder.toString();
String[] args = new String[columns.length * contentValues.size()];
int i = 0;
for (ContentValues values : contentValues) {
for (String column : columns) {
Object value = values.get(column);
args[i] = value != null ? values.get(column).toString() : "null";
i++;
}
}
return new Query(query, args);
}
public static class Query {
private final String where;
private final String[] whereArgs;