Skip to content
This repository has been archived by the owner on Nov 14, 2024. It is now read-only.

[Named min timestamp leases] Metric tracking fresh ts shortfall #7402

Open
wants to merge 1 commit into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import com.palantir.lock.client.RequestBatchersFactory;
import com.palantir.lock.client.TimeLockClient;
import com.palantir.lock.client.TimestampCorroboratingTimelockService;
import com.palantir.lock.client.TimestampLeaseMetrics;
import com.palantir.lock.client.metrics.TimeLockFeedbackBackgroundTask;
import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetter;
import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl;
Expand Down Expand Up @@ -369,7 +370,8 @@ private static LockAndTimestampServices getLockAndTimestampServices(
namespacedConjureTimelockService,
multiClientTimelockServiceSupplier,
namespacedTimelockRpcClient,
timeLockHelperServices.requestBatchersFactory());
timeLockHelperServices.requestBatchersFactory(),
metricsManager);

TimestampManagementService timestampManagementService = new RemoteTimestampManagementAdapter(
serviceProvider.getTimestampManagementRpcClient(), timelockNamespace);
Expand All @@ -391,7 +393,8 @@ private static RemoteTimelockServiceAdapter createRemoteTimelockServiceAdapter(
NamespacedConjureTimelockService namespacedConjureTimelockService,
Supplier<InternalMultiClientConjureTimelockService> multiClientTimelockServiceSupplier,
NamespacedTimelockRpcClient namespacedTimelockRpcClient,
RequestBatchersFactory batchersFactory) {
RequestBatchersFactory batchersFactory,
MetricsManager metricsManager) {
LockTokenUnlocker unlocker = getTimeLockUnlocker(
timelockNamespace,
timelockRequestBatcherProviders,
Expand All @@ -401,8 +404,8 @@ private static RemoteTimelockServiceAdapter createRemoteTimelockServiceAdapter(
NamespacedTimestampLeaseService timestampLeaseService = new NamespacedTimestampLeaseServiceImpl(
Namespace.of(timelockNamespace), multiClientTimelockServiceSupplier.get());

TimestampLeaseAcquirer timestampLeaseAcquirer =
TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker);
TimestampLeaseAcquirer timestampLeaseAcquirer = TimestampLeaseAcquirerImpl.create(
timestampLeaseService, unlocker, TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry()));

MinLeasedTimestampGetter minLeasedTimestampGetter = new MinLeasedTimestampGetterImpl(timestampLeaseService);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.palantir.lock.client.NamespacedConjureTimelockServiceImpl;
import com.palantir.lock.client.RemoteTimelockServiceAdapter;
import com.palantir.lock.client.RequestBatchersFactory;
import com.palantir.lock.client.TimestampLeaseMetrics;
import com.palantir.lock.client.TransactionStarter;
import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl;
import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseService;
Expand Down Expand Up @@ -90,6 +91,7 @@ public abstract class AbstractInMemoryTimelockExtension implements TimeLockServi
private NamespacedConjureTimelockServiceImpl namespacedConjureTimelockService;
private NamespacedTimestampLeaseService timestampLeaseService;
private LockTokenUnlocker unlocker;
private final MetricsManager metricsManager = MetricsManagers.createForTests();

public AbstractInMemoryTimelockExtension() {
this("client");
Expand Down Expand Up @@ -129,8 +131,6 @@ public void setup() {
.clusterSnapshot(clusterConfig)
.build();

MetricsManager metricsManager = MetricsManagers.createForTests();

timeLockAgent = TimeLockAgent.create(
metricsManager,
install,
Expand All @@ -146,7 +146,7 @@ public void setup() {
() -> System.exit(0));

delegate = timeLockAgent.createInvalidatingTimeLockServices(client);
createHelperServices(metricsManager);
createHelperServices();

// Wait for leadership
Awaitility.await()
Expand All @@ -156,7 +156,7 @@ public void setup() {
.until(() -> delegate.getTimestampService().getFreshTimestamp() > 0);
}

private void createHelperServices(MetricsManager metricsManager) {
private void createHelperServices() {
helperServices = TimeLockHelperServices.create(
client,
metricsManager,
Expand Down Expand Up @@ -248,7 +248,8 @@ public TimelockService getLegacyTimelockService() {
lockLeaseService,
transactionStarter,
commitTimestampGetter,
TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker),
TimestampLeaseAcquirerImpl.create(
timestampLeaseService, unlocker, TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())),
new MinLeasedTimestampGetterImpl(timestampLeaseService));
}

Expand Down
1 change: 1 addition & 0 deletions lock-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ apply plugin: 'com.palantir.metric-schema'
license {
exclude '**/TimestampCorrectnessMetrics.java'
exclude '**/TopologyMetrics.java'
exclude '**/TimestampLeaseMetrics.java'
}

libsDirName = file('build/artifacts')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.palantir.lock.client.timestampleases;

import com.codahale.metrics.Counter;
import com.github.rholder.retry.Attempt;
import com.github.rholder.retry.RetryException;
import com.github.rholder.retry.Retryer;
Expand All @@ -39,6 +40,7 @@
import com.palantir.lock.LimitingLongSupplier;
import com.palantir.lock.client.LeasedLockToken;
import com.palantir.lock.client.LockTokenUnlocker;
import com.palantir.lock.client.TimestampLeaseMetrics;
import com.palantir.lock.v2.TimestampLeaseResult;
import com.palantir.lock.v2.TimestampLeaseResults;
import com.palantir.logsafe.Preconditions;
Expand All @@ -62,28 +64,38 @@ public final class TimestampLeaseAcquirerImpl implements TimestampLeaseAcquirer
private final NamespacedTimestampLeaseService delegate;
private final Unlocker unlocker;
private final Supplier<UUID> uuidSupplier;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should have asked on earlier review, but what is the purpose of the UUID supplier? We know from the type that it is a UUID supplier 😅

private final Counter notEnoughFreshTimestampsCounter;

private final Retryer<Optional<TimestampLeaseResponses>> retryer =
RetryerBuilder.<Optional<TimestampLeaseResponses>>newBuilder()
.retryIfResult(Optional::isEmpty)
.withStopStrategy(StopStrategies.stopAfterAttempt(3))
.build();

@VisibleForTesting
TimestampLeaseAcquirerImpl(
NamespacedTimestampLeaseService delegate, Unlocker unlocker, Supplier<UUID> uuidSupplier) {
private TimestampLeaseAcquirerImpl(
NamespacedTimestampLeaseService delegate,
Unlocker unlocker,
Supplier<UUID> uuidSupplier,
Counter notEnoughFreshTimestampsCounter) {
this.delegate = delegate;
this.unlocker = unlocker;
this.uuidSupplier = uuidSupplier;
this.notEnoughFreshTimestampsCounter = notEnoughFreshTimestampsCounter;
}

private TimestampLeaseAcquirerImpl(NamespacedTimestampLeaseService delegate, Unlocker unlocker) {
this(delegate, unlocker, UniqueIds::pseudoRandomUuidV4);
@VisibleForTesting
TimestampLeaseAcquirerImpl(
NamespacedTimestampLeaseService delegate, Unlocker unlocker, Supplier<UUID> uuidSupplier) {
this(delegate, unlocker, uuidSupplier, new Counter());
}

public static TimestampLeaseAcquirer create(
NamespacedTimestampLeaseService timestampLeaseService, LockTokenUnlocker unlocker) {
return new TimestampLeaseAcquirerImpl(timestampLeaseService, identifier -> unlock(unlocker, identifier));
NamespacedTimestampLeaseService delegate, LockTokenUnlocker unlocker, TimestampLeaseMetrics metrics) {
return new TimestampLeaseAcquirerImpl(
delegate,
identifier -> unlock(unlocker, identifier),
UniqueIds::pseudoRandomUuidV4,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally in the rest of the code we use UUID::randomUUID. This is plausibly better, but was there a reason for using it here specifically?

metrics.notEnoughFreshTimestamps());
}

@Override
Expand Down Expand Up @@ -146,23 +158,27 @@ private Optional<TimestampLeaseResponses> acquireLeases(Map<TimestampLeaseName,
requestedFreshTimestamps.keySet().equals(responseMap.keySet()),
"Response lease timestamps need to match request timestamp names exactly");

boolean wasFullyFulfilled = requestedFreshTimestamps.keySet().stream().allMatch(timestampName -> {
int requestedTimestamps = requestedFreshTimestamps.get(timestampName);
long returnedTimestamps =
responseMap.get(timestampName).getFreshTimestamps().getCount();
return returnedTimestamps >= requestedTimestamps;
});
long wereNotFullyFulfilled = requestedFreshTimestamps.keySet().stream()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: unfulfilledRequestCount or similar?

.filter(timestampName -> {
int requestedTimestamps = requestedFreshTimestamps.get(timestampName);
long returnedTimestamps =
responseMap.get(timestampName).getFreshTimestamps().getCount();
return returnedTimestamps < requestedTimestamps;
})
.count();

if (wereNotFullyFulfilled > 0) {
notEnoughFreshTimestampsCounter.inc(wereNotFullyFulfilled);

if (!wasFullyFulfilled) {
unlock(response);
log.info(
"Timestamp lease request was not fully fulfilled. This should happen infrequently.",
SafeArg.of("requests", requests),
SafeArg.of("requests", request),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: makes sense, but change the arg name too.

SafeArg.of("responses", response));
return Optional.empty();
} else {
return Optional.of(response);
}

return Optional.of(response);
}

private void unlock(TimestampLeaseResponses responses) {
Expand Down
6 changes: 6 additions & 0 deletions lock-api/src/main/metrics/metric-schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,10 @@ namespaces:
type: timer
docs: observed call duration during leader election

timestampLease:
docs: Timestamp lease client side telemetry
metrics:
notEnoughFreshTimestamps:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pedantry: I'd probably have instances somewhere in the name, to be explicit that it's not the amount of shortfall that matters in this count

type: counter
docs: Counts instances where TimeLock returns less than the requested number of timestamps in acquire timestamp lease calls

Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.palantir.lock.client.NamespacedConjureTimelockServiceImpl;
import com.palantir.lock.client.RemoteLockServiceAdapter;
import com.palantir.lock.client.RemoteTimelockServiceAdapter;
import com.palantir.lock.client.TimestampLeaseMetrics;
import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetter;
import com.palantir.lock.client.timestampleases.MinLeasedTimestampGetterImpl;
import com.palantir.lock.client.timestampleases.NamespacedTimestampLeaseService;
Expand All @@ -55,6 +56,7 @@
import com.palantir.timestamp.TimestampManagementRpcClient;
import com.palantir.timestamp.TimestampManagementService;
import com.palantir.timestamp.TimestampRange;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import java.util.Set;
import org.immutables.value.Value;

Expand Down Expand Up @@ -94,8 +96,8 @@ default TimelockService timelockService() {
NamespacedTimestampLeaseService timestampLeaseService = new NamespacedTimestampLeaseServiceImpl(
Namespace.of(namespace()), internalMultiClientConjureTimelockService());

TimestampLeaseAcquirer timestampLeaseAcquirer =
TimestampLeaseAcquirerImpl.create(timestampLeaseService, unlocker);
TimestampLeaseAcquirer timestampLeaseAcquirer = TimestampLeaseAcquirerImpl.create(
timestampLeaseService, unlocker, TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));

MinLeasedTimestampGetter minLeasedTimestampGetter = new MinLeasedTimestampGetterImpl(timestampLeaseService);

Expand Down