Record the age of accounts that send unsealed-sender messages.
This commit is contained in:
parent
8c9d871268
commit
06ca5f14fc
|
@ -402,7 +402,7 @@ public class WhisperServerService extends Application<WhisperServerConfiguration
|
|||
AttachmentControllerV2 attachmentControllerV2 = new AttachmentControllerV2(rateLimiters, config.getAwsAttachmentsConfiguration().getAccessKey(), config.getAwsAttachmentsConfiguration().getAccessSecret(), config.getAwsAttachmentsConfiguration().getRegion(), config.getAwsAttachmentsConfiguration().getBucket());
|
||||
AttachmentControllerV3 attachmentControllerV3 = new AttachmentControllerV3(rateLimiters, config.getGcpAttachmentsConfiguration().getDomain(), config.getGcpAttachmentsConfiguration().getEmail(), config.getGcpAttachmentsConfiguration().getMaxSizeInBytes(), config.getGcpAttachmentsConfiguration().getPathPrefix(), config.getGcpAttachmentsConfiguration().getRsaSigningKey());
|
||||
KeysController keysController = new KeysController(rateLimiters, keysDynamoDb, accountsManager, directoryQueue);
|
||||
MessageController messageController = new MessageController(rateLimiters, messageSender, receiptSender, accountsManager, messagesManager, apnFallbackManager, dynamicConfigurationManager);
|
||||
MessageController messageController = new MessageController(rateLimiters, messageSender, receiptSender, accountsManager, messagesManager, apnFallbackManager, dynamicConfigurationManager, metricsCluster);
|
||||
ProfileController profileController = new ProfileController(rateLimiters, accountsManager, profilesManager, usernamesManager, cdnS3Client, profileCdnPolicyGenerator, profileCdnPolicySigner, config.getCdnConfiguration().getBucket(), zkProfileOperations, isZkEnabled);
|
||||
StickerController stickerController = new StickerController(rateLimiters, config.getCdnConfiguration().getAccessKey(), config.getCdnConfiguration().getAccessSecret(), config.getCdnConfiguration().getRegion(), config.getCdnConfiguration().getBucket());
|
||||
RemoteConfigController remoteConfigController = new RemoteConfigController(remoteConfigsManager, config.getRemoteConfigConfiguration().getAuthorizedTokens(), config.getRemoteConfigConfiguration().getGlobalConfig());
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
|||
import com.google.protobuf.ByteString;
|
||||
import io.dropwizard.auth.Auth;
|
||||
import io.dropwizard.util.DataSize;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.core.instrument.Metrics;
|
||||
import io.micrometer.core.instrument.Tag;
|
||||
import java.io.IOException;
|
||||
|
@ -56,6 +57,7 @@ import org.whispersystems.textsecuregcm.push.ApnFallbackManager;
|
|||
import org.whispersystems.textsecuregcm.push.MessageSender;
|
||||
import org.whispersystems.textsecuregcm.push.NotPushRegisteredException;
|
||||
import org.whispersystems.textsecuregcm.push.ReceiptSender;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.redis.RedisOperation;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
|
@ -88,10 +90,12 @@ public class MessageController {
|
|||
private final MessagesManager messagesManager;
|
||||
private final ApnFallbackManager apnFallbackManager;
|
||||
private final DynamicConfigurationManager dynamicConfigurationManager;
|
||||
private final FaultTolerantRedisCluster metricsCluster;
|
||||
|
||||
private static final String SENT_MESSAGE_COUNTER_NAME = name(MessageController.class, "sentMessages");
|
||||
private static final String REJECT_UNSEALED_SENDER_COUNTER_NAME = name(MessageController.class, "rejectUnsealedSenderLimit");
|
||||
private static final String INTERNATIONAL_UNSEALED_SENDER_COUNTER_NAME = name(MessageController.class, "internationalUnsealedSender");
|
||||
private static final String UNSEALED_SENDER_ACCOUNT_AGE_DISTRIBUTION_NAME = name(MessageController.class, "unsealedSenderAccountAge");
|
||||
private static final String CONTENT_SIZE_DISTRIBUTION_NAME = name(MessageController.class, "messageContentSize");
|
||||
private static final String OUTGOING_MESSAGE_LIST_SIZE_BYTES_DISTRIBUTION_NAME = name(MessageController.class, "outgoingMessageListSizeBytes");
|
||||
|
||||
|
@ -101,13 +105,16 @@ public class MessageController {
|
|||
|
||||
private static final long MAX_MESSAGE_SIZE = DataSize.kibibytes(256).toBytes();
|
||||
|
||||
private static final String SENT_FIRST_UNSEALED_SENDER_MESSAGE_KEY = "sent_first_unsealed_sender_message";
|
||||
|
||||
public MessageController(RateLimiters rateLimiters,
|
||||
MessageSender messageSender,
|
||||
ReceiptSender receiptSender,
|
||||
AccountsManager accountsManager,
|
||||
MessagesManager messagesManager,
|
||||
ApnFallbackManager apnFallbackManager,
|
||||
DynamicConfigurationManager dynamicConfigurationManager)
|
||||
DynamicConfigurationManager dynamicConfigurationManager,
|
||||
FaultTolerantRedisCluster metricsCluster)
|
||||
{
|
||||
this.rateLimiters = rateLimiters;
|
||||
this.messageSender = messageSender;
|
||||
|
@ -116,6 +123,7 @@ public class MessageController {
|
|||
this.messagesManager = messagesManager;
|
||||
this.apnFallbackManager = apnFallbackManager;
|
||||
this.dynamicConfigurationManager = dynamicConfigurationManager;
|
||||
this.metricsCluster = metricsCluster;
|
||||
}
|
||||
|
||||
@Timed
|
||||
|
@ -135,6 +143,26 @@ public class MessageController {
|
|||
}
|
||||
|
||||
if (source.isPresent() && !source.get().isFor(destinationName)) {
|
||||
RedisOperation.unchecked(() -> {
|
||||
metricsCluster.useCluster(connection -> {
|
||||
if (connection.sync().pfadd(SENT_FIRST_UNSEALED_SENDER_MESSAGE_KEY, source.get().getUuid().toString()) == 1) {
|
||||
final List<Tag> tags = List.of(
|
||||
UserAgentTagUtil.getPlatformTag(userAgent),
|
||||
Tag.of(SENDER_COUNTRY_TAG_NAME, Util.getCountryCode(source.get().getNumber())));
|
||||
|
||||
assert source.get().getMasterDevice().isPresent();
|
||||
|
||||
final long accountAge = System.currentTimeMillis() - source.get().getMasterDevice().get().getCreated();
|
||||
|
||||
DistributionSummary.builder(UNSEALED_SENDER_ACCOUNT_AGE_DISTRIBUTION_NAME)
|
||||
.tags(tags)
|
||||
.publishPercentileHistogram()
|
||||
.register(Metrics.globalRegistry)
|
||||
.record(accountAge);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
try {
|
||||
rateLimiters.getUnsealedSenderLimiter().validate(source.get().getUuid().toString(), destinationName.toString());
|
||||
} catch (RateLimitExceededException e) {
|
||||
|
|
|
@ -29,7 +29,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import io.dropwizard.auth.PolymorphicAuthValueFactoryProvider;
|
||||
import io.dropwizard.testing.junit.ResourceTestRule;
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
@ -44,7 +43,6 @@ import junitparams.JUnitParamsRunner;
|
|||
import junitparams.Parameters;
|
||||
import org.glassfish.jersey.test.grizzly.GrizzlyWebTestContainerFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
@ -67,6 +65,7 @@ import org.whispersystems.textsecuregcm.limits.RateLimiters;
|
|||
import org.whispersystems.textsecuregcm.push.ApnFallbackManager;
|
||||
import org.whispersystems.textsecuregcm.push.MessageSender;
|
||||
import org.whispersystems.textsecuregcm.push.ReceiptSender;
|
||||
import org.whispersystems.textsecuregcm.redis.FaultTolerantRedisCluster;
|
||||
import org.whispersystems.textsecuregcm.storage.Account;
|
||||
import org.whispersystems.textsecuregcm.storage.AccountsManager;
|
||||
import org.whispersystems.textsecuregcm.storage.Device;
|
||||
|
@ -93,6 +92,7 @@ public class MessageControllerTest {
|
|||
private final CardinalityRateLimiter unsealedSenderLimiter = mock(CardinalityRateLimiter.class);
|
||||
private final ApnFallbackManager apnFallbackManager = mock(ApnFallbackManager.class);
|
||||
private final DynamicConfigurationManager dynamicConfigurationManager = mock(DynamicConfigurationManager.class);
|
||||
private final FaultTolerantRedisCluster metricsCluster = mock(FaultTolerantRedisCluster.class);
|
||||
|
||||
private final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class MessageControllerTest {
|
|||
.addProvider(new PolymorphicAuthValueFactoryProvider.Binder<>(ImmutableSet.of(Account.class, DisabledPermittedAccount.class)))
|
||||
.setTestContainerFactory(new GrizzlyWebTestContainerFactory())
|
||||
.addResource(new MessageController(rateLimiters, messageSender, receiptSender, accountsManager,
|
||||
messagesManager, apnFallbackManager, dynamicConfigurationManager))
|
||||
messagesManager, apnFallbackManager, dynamicConfigurationManager, metricsCluster))
|
||||
.build();
|
||||
|
||||
|
||||
|
|
|
@ -101,9 +101,13 @@ public class AuthHelper {
|
|||
when(UNDISCOVERABLE_DEVICE.isMaster()).thenReturn(true);
|
||||
|
||||
when(VALID_ACCOUNT.getDevice(1L)).thenReturn(Optional.of(VALID_DEVICE));
|
||||
when(VALID_ACCOUNT.getMasterDevice()).thenReturn(Optional.of(VALID_DEVICE));
|
||||
when(VALID_ACCOUNT_TWO.getDevice(eq(1L))).thenReturn(Optional.of(VALID_DEVICE_TWO));
|
||||
when(VALID_ACCOUNT_TWO.getMasterDevice()).thenReturn(Optional.of(VALID_DEVICE_TWO));
|
||||
when(DISABLED_ACCOUNT.getDevice(eq(1L))).thenReturn(Optional.of(DISABLED_DEVICE));
|
||||
when(DISABLED_ACCOUNT.getMasterDevice()).thenReturn(Optional.of(DISABLED_DEVICE));
|
||||
when(UNDISCOVERABLE_ACCOUNT.getDevice(eq(1L))).thenReturn(Optional.of(UNDISCOVERABLE_DEVICE));
|
||||
when(UNDISCOVERABLE_ACCOUNT.getMasterDevice()).thenReturn(Optional.of(UNDISCOVERABLE_DEVICE));
|
||||
|
||||
when(VALID_ACCOUNT_TWO.getEnabledDeviceCount()).thenReturn(6);
|
||||
|
||||
|
@ -211,6 +215,7 @@ public class AuthHelper {
|
|||
when(device.getId()).thenReturn(1L);
|
||||
when(device.isEnabled()).thenReturn(true);
|
||||
when(account.getDevice(1L)).thenReturn(Optional.of(device));
|
||||
when(account.getMasterDevice()).thenReturn(Optional.of(device));
|
||||
when(account.getNumber()).thenReturn(number);
|
||||
when(account.getUuid()).thenReturn(uuid);
|
||||
when(account.getAuthenticatedDevice()).thenReturn(Optional.of(device));
|
||||
|
|
Loading…
Reference in New Issue