Locally track message send time.
This commit is contained in:
parent
37ae740138
commit
784c373a0e
7 changed files with 132 additions and 4 deletions
|
@ -36,6 +36,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
|||
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;
|
||||
|
@ -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);
|
||||
|
@ -368,6 +371,19 @@ public class ConversationItemFooter extends ConstraintLayout {
|
|||
}
|
||||
|
||||
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;
|
||||
|
@ -426,6 +442,10 @@ public class ConversationItemFooter extends ConstraintLayout {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,10 @@ public class DeliveryStatusView extends FrameLayout {
|
|||
this.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return pendingIndicator.getVisibility() == View.VISIBLE;
|
||||
}
|
||||
|
||||
public void setPending() {
|
||||
this.setVisibility(View.VISIBLE);
|
||||
pendingIndicator.setVisibility(View.VISIBLE);
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.transport.RetryLaterException;
|
|||
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;
|
||||
|
@ -147,6 +148,8 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
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();
|
||||
|
@ -186,6 +189,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
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();
|
||||
|
@ -258,6 +262,8 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
database.markAsSentFailed(messageId);
|
||||
notifyMediaMessageDeliveryFailed(context, messageId);
|
||||
}
|
||||
|
||||
SignalLocalMetrics.GroupMessageSend.onJobFinished(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -303,6 +309,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
.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!");
|
||||
|
@ -328,6 +335,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
|
||||
Log.i(TAG, JobLogger.format(this, "Beginning message send."));
|
||||
|
||||
SignalLocalMetrics.GroupMessageSend.onNetworkStarted(messageId);
|
||||
return GroupSendUtil.sendResendableDataMessage(context,
|
||||
groupRecipient.getGroupId().transform(GroupId::requireV2).orNull(),
|
||||
destinations,
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
|||
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;
|
||||
|
@ -74,6 +75,8 @@ public class PushTextSendJob extends PushSendJob {
|
|||
|
||||
@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);
|
||||
|
@ -136,6 +139,8 @@ public class PushTextSendJob extends PushSendJob {
|
|||
} catch (ProofRequiredException e) {
|
||||
handleProofRequiredException(e, record.getRecipient(), record.getThreadId(), messageId, false);
|
||||
}
|
||||
|
||||
SignalLocalMetrics.IndividualMessageSend.onJobFinished(messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -176,11 +181,17 @@ public class PushTextSendJob extends PushSendJob {
|
|||
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();
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId;
|
|||
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;
|
||||
|
@ -114,6 +115,8 @@ public class MessageSender {
|
|||
System.currentTimeMillis(),
|
||||
insertListener);
|
||||
|
||||
SignalLocalMetrics.IndividualMessageSend.start(messageId);
|
||||
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
|
||||
onMessageSent();
|
||||
|
||||
|
@ -135,6 +138,10 @@ public class MessageSender {
|
|||
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();
|
||||
|
||||
|
|
|
@ -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()) }
|
||||
|
|
|
@ -25,8 +25,8 @@ public final class SignalLocalMetrics {
|
|||
|
||||
@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);
|
||||
|
@ -63,4 +63,82 @@ public final class SignalLocalMetrics {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue