Skip to content

Commit

Permalink
Locally track message send time.
Browse files Browse the repository at this point in the history
  • Loading branch information
greyson-signal authored and alex-signal committed Aug 5, 2021
1 parent 37ae740 commit 784c373
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Projection;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat;
import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat;
Expand Down Expand Up @@ -64,6 +65,8 @@ public class ConversationItemFooter extends ConstraintLayout {
private final Rect speedToggleHitRect = new Rect();
private final int touchTargetSize = ViewUtil.dpToPx(48);

private long previousMessageId;

public ConversationItemFooter(Context context) {
super(context);
init(null);
Expand Down Expand Up @@ -368,6 +371,19 @@ private void presentInsecureIndicator(@NonNull MessageRecord messageRecord) {
}

private void presentDeliveryStatus(@NonNull MessageRecord messageRecord) {
long newMessageId = buildMessageId(messageRecord);

if (previousMessageId == newMessageId && deliveryStatusView.isPending() && !messageRecord.isPending()) {
if (messageRecord.getRecipient().isGroup()) {
SignalLocalMetrics.GroupMessageSend.onUiUpdated(messageRecord.getId());
} else {
SignalLocalMetrics.IndividualMessageSend.onUiUpdated(messageRecord.getId());
}
}

previousMessageId = newMessageId;


if (messageRecord.isFailed() || messageRecord.isPendingInsecureSmsFallback()) {
deliveryStatusView.setNone();
return;
Expand Down Expand Up @@ -426,6 +442,10 @@ private void hideAudioDurationViews() {
playbackSpeedToggleTextView.setVisibility(View.GONE);
}

private long buildMessageId(@NonNull MessageRecord record) {
return record.isMms() ? -record.getId() : record.getId();
}

public interface OnTouchDelegateChangedListener {
void onTouchDelegateChanged(@NonNull Rect delegateRect, @NonNull View delegateView);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ public void setNone() {
this.setVisibility(View.GONE);
}

public boolean isPending() {
return pendingIndicator.getVisibility() == View.VISIBLE;
}

public void setPending() {
this.setVisibility(View.VISIBLE);
pendingIndicator.setVisibility(View.VISIBLE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.GroupUtil;
import org.thoughtcrime.securesms.util.RecipientAccessList;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.whispersystems.libsignal.util.Pair;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.crypto.ContentHint;
Expand Down Expand Up @@ -147,6 +148,8 @@ public void onAdded() {
public void onPushSend()
throws IOException, MmsException, NoSuchMessageException, RetryLaterException
{
SignalLocalMetrics.GroupMessageSend.onJobStarted(messageId);

MessageDatabase database = DatabaseFactory.getMmsDatabase(context);
OutgoingMediaMessage message = database.getOutgoingMessage(messageId);
long threadId = database.getMessageRecord(messageId).getThreadId();
Expand Down Expand Up @@ -186,6 +189,7 @@ public void onPushSend()
RecipientAccessList accessList = new RecipientAccessList(target);

List<SendMessageResult> results = deliver(message, groupRecipient, target);
SignalLocalMetrics.GroupMessageSend.onNetworkFinished(messageId);
Log.i(TAG, JobLogger.format(this, "Finished send."));

List<NetworkFailure> networkFailures = Stream.of(results).filter(SendMessageResult::isNetworkFailure).map(result -> new NetworkFailure(accessList.requireIdByAddress(result.getAddress()))).toList();
Expand Down Expand Up @@ -258,6 +262,8 @@ public void onPushSend()
database.markAsSentFailed(messageId);
notifyMediaMessageDeliveryFailed(context, messageId);
}

SignalLocalMetrics.GroupMessageSend.onJobFinished(messageId);
}

@Override
Expand Down Expand Up @@ -303,6 +309,7 @@ private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull R
.withExpiration(groupRecipient.getExpiresInSeconds())
.asGroupMessage(group)
.build();
SignalLocalMetrics.GroupMessageSend.onNetworkStarted(messageId);
return GroupSendUtil.sendResendableDataMessage(context, groupRecipient.requireGroupId().requireV2(), destinations, isRecipientUpdate, ContentHint.IMPLICIT, new MessageId(messageId, true), groupDataMessage);
} else {
throw new UndeliverableMessageException("Messages can no longer be sent to V1 groups!");
Expand All @@ -328,6 +335,7 @@ private List<SendMessageResult> deliver(OutgoingMediaMessage message, @NonNull R

Log.i(TAG, JobLogger.format(this, "Beginning message send."));

SignalLocalMetrics.GroupMessageSend.onNetworkStarted(messageId);
return GroupSendUtil.sendResendableDataMessage(context,
groupRecipient.getGroupId().transform(GroupId::requireV2).orNull(),
destinations,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
import org.thoughtcrime.securesms.transport.RetryLaterException;
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
Expand Down Expand Up @@ -74,6 +75,8 @@ public void onAdded() {

@Override
public void onPushSend() throws IOException, NoSuchMessageException, UndeliverableMessageException, RetryLaterException {
SignalLocalMetrics.IndividualMessageSend.onJobStarted(messageId);

ExpiringMessageManager expirationManager = ApplicationDependencies.getExpiringMessageManager();
MessageDatabase database = DatabaseFactory.getSmsDatabase(context);
SmsMessageRecord record = database.getSmsMessage(messageId);
Expand Down Expand Up @@ -136,6 +139,8 @@ public void onPushSend() throws IOException, NoSuchMessageException, Undeliverab
} catch (ProofRequiredException e) {
handleProofRequiredException(e, record.getRecipient(), record.getThreadId(), messageId, false);
}

SignalLocalMetrics.IndividualMessageSend.onJobFinished(messageId);
}

@Override
Expand Down Expand Up @@ -176,11 +181,17 @@ private boolean deliver(SmsMessageRecord message)
Optional<UnidentifiedAccessPair> syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);

SignalLocalMetrics.IndividualMessageSend.onNetworkStarted(messageId);
SendMessageResult result = messageSender.sendSyncMessage(syncMessage, syncAccess);
SignalLocalMetrics.IndividualMessageSend.onNetworkFinished(messageId);

DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return syncAccess.isPresent();
} else {
SignalLocalMetrics.IndividualMessageSend.onNetworkStarted(messageId);
SendMessageResult result = messageSender.sendDataMessage(address, unidentifiedAccess, ContentHint.RESENDABLE, textSecureMessage);
SignalLocalMetrics.IndividualMessageSend.onNetworkFinished(messageId);

DatabaseFactory.getMessageLogDatabase(context).insertIfPossible(messageRecipient.getId(), message.getDateSent(), result, ContentHint.RESENDABLE, new MessageId(messageId, false));
return result.getSuccess().isUnidentified();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.ParcelUtil;
import org.thoughtcrime.securesms.util.SignalLocalMetrics;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.libsignal.util.guava.Preconditions;
Expand Down Expand Up @@ -114,6 +115,8 @@ public static long send(final Context context,
System.currentTimeMillis(),
insertListener);

SignalLocalMetrics.IndividualMessageSend.start(messageId);

sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
onMessageSent();

Expand All @@ -135,6 +138,10 @@ public static long send(final Context context,
Recipient recipient = message.getRecipient();
long messageId = database.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, forceSms, insertListener);

if (message.getRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
SignalLocalMetrics.GroupMessageSend.start(messageId);
}

sendMediaMessage(context, recipient, forceSms, messageId, Collections.emptyList());
onMessageSent();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import java.util.concurrent.Executor
object LocalMetrics {
private val TAG: String = Log.tag(LocalMetrics::class.java)

private val eventsById: MutableMap<String, LocalMetricsEvent> = mutableMapOf()
private val lastSplitTimeById: MutableMap<String, Long> = mutableMapOf()
private val eventsById: MutableMap<String, LocalMetricsEvent> = LRUCache(200)
private val lastSplitTimeById: MutableMap<String, Long> = LRUCache(200)

private val executor: Executor = SignalExecutors.newCachedSingleThreadExecutor("signal-LocalMetrics")
private val db: LocalMetricsDatabase by lazy { LocalMetricsDatabase.getInstance(ApplicationDependencies.getApplication()) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ public static final class ColdStart {

@MainThread
public static void start() {
conversationListId = NAME_CONVERSATION_LIST + System.currentTimeMillis();
otherId = NAME_OTHER + System.currentTimeMillis();
conversationListId = NAME_CONVERSATION_LIST + "-" + System.currentTimeMillis();
otherId = NAME_OTHER + "-" + System.currentTimeMillis();

LocalMetrics.getInstance().start(conversationListId, NAME_CONVERSATION_LIST);
LocalMetrics.getInstance().start(otherId, NAME_OTHER);
Expand Down Expand Up @@ -63,4 +63,82 @@ public static void onRenderFinished() {
}
}
}

public static final class IndividualMessageSend {
private static final String NAME = "individual-message-send";

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";

public static void start(long messageId) {
LocalMetrics.getInstance().start(buildId(messageId), NAME);
}

public static void onJobStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_ENQUEUE);
}

public static void onNetworkStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_PRE_NETWORK);
}

public static void onNetworkFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_NETWORK);
}

public static void onJobFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_POST_NETWORK);
}

public static void onUiUpdated(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(buildId(messageId));
}

private static String buildId(long messageId) {
return NAME + "-" + messageId;
}
}

public static final class GroupMessageSend {
private static final String NAME = "group-message-send";

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";

public static void start(long messageId) {
LocalMetrics.getInstance().start(buildId(messageId), NAME);
}

public static void onJobStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_ENQUEUE);
}

public static void onNetworkStarted(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_PRE_NETWORK);
}

public static void onNetworkFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_NETWORK);
}

public static void onJobFinished(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_JOB_POST_NETWORK);
}

public static void onUiUpdated(long messageId) {
LocalMetrics.getInstance().split(buildId(messageId), SPLIT_UI_UPDATE);
LocalMetrics.getInstance().end(buildId(messageId));
}

private static String buildId(long messageId) {
return NAME + "-" + messageId;
}
}
}

0 comments on commit 784c373

Please sign in to comment.