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

[Named min timestamp leases] Add metric for number of locked timestamps #7406

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 @@ -28,6 +28,7 @@
import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics;
import com.palantir.atlasdb.timelock.paxos.LeadershipComponents;
import com.palantir.atlasdb.timelock.paxos.LeadershipComponents.LeadershipProxies;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.atlasdb.util.MetricsManager;
import com.palantir.common.concurrent.NamedThreadFactory;
import com.palantir.common.concurrent.PTExecutors;
Expand Down Expand Up @@ -96,7 +97,8 @@ private AsyncTimelockService createRawAsyncTimelockService(
maybeEnhancedLockLog,
reaperExecutor,
timeoutExecutor,
BufferMetrics.of(metricsManager.getTaggedRegistry())),
BufferMetrics.of(metricsManager.getTaggedRegistry()),
TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())),
timestampServiceSupplier.get(),
maybeEnhancedLockLog,
RequestMetrics.of(metricsManager.getTaggedRegistry()));
Expand Down
1 change: 1 addition & 0 deletions timelock-impl/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,5 @@ dependencies {
license {
exclude '**/RequestMetrics.java'
exclude '**/BufferMetrics.java'
exclude '**/TimestampLeaseMetrics.java'
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import com.palantir.atlasdb.timelock.lock.watch.LockWatchingService;
import com.palantir.atlasdb.timelock.lock.watch.LockWatchingServiceImpl;
import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.lock.LockDescriptor;
import com.palantir.lock.v2.LeaderTime;
import com.palantir.lock.v2.LockToken;
Expand Down Expand Up @@ -64,7 +65,8 @@ public static AsyncLockService createDefault(
LockLog lockLog,
ScheduledExecutorService reaperExecutor,
ScheduledExecutorService timeoutExecutor,
BufferMetrics bufferMetrics) {
BufferMetrics bufferMetrics,
TimestampLeaseMetrics timestampLeaseMetrics) {

LeaderClock clock = LeaderClock.create();

Expand All @@ -73,7 +75,7 @@ public static AsyncLockService createDefault(
LockAcquirer lockAcquirer = new LockAcquirer(lockLog, timeoutExecutor, clock, lockWatchingService);

return new AsyncLockService(
new LockManager(),
LockManager.create(timestampLeaseMetrics),
lockAcquirer,
heldLocks,
new AwaitedLocksCollection(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@
package com.palantir.atlasdb.timelock.lock;

import com.palantir.atlasdb.timelock.api.TimestampLeaseName;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.lock.LockDescriptor;
import java.util.Optional;
import java.util.Set;

final class LockManager {
private final ExclusiveLockCollection exclusiveLocks = new ExclusiveLockCollection();
private final NamedMinTimestampLockCollection namedMinTimestampLockCollection =
new NamedMinTimestampLockCollection();
private final ExclusiveLockCollection exclusiveLocks;
private final NamedMinTimestampLockCollection namedMinTimestampLockCollection;

private LockManager(
ExclusiveLockCollection exclusiveLocks, NamedMinTimestampLockCollection namedMinTimestampLockCollection) {
this.exclusiveLocks = exclusiveLocks;
this.namedMinTimestampLockCollection = namedMinTimestampLockCollection;
}

static LockManager create(TimestampLeaseMetrics metrics) {
return new LockManager(new ExclusiveLockCollection(), NamedMinTimestampLockCollection.create(metrics));
}

OrderedLocks getAllExclusiveLocks(Set<LockDescriptor> descriptors) {
return exclusiveLocks.getAll(descriptors);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.palantir.atlasdb.timelock.api.TimestampLeaseName;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import java.util.Optional;

final class NamedMinTimestampLockCollection {
private final LoadingCache<String, NamedMinTimestampTracker> namedMinTimestampTrackers =
Caffeine.newBuilder().build(NamedMinTimestampTrackerImpl::new);
private final LoadingCache<String, NamedMinTimestampTracker> namedMinTimestampTrackers;

private NamedMinTimestampLockCollection(LoadingCache<String, NamedMinTimestampTracker> namedMinTimestampTrackers) {
this.namedMinTimestampTrackers = namedMinTimestampTrackers;
}

static NamedMinTimestampLockCollection create(TimestampLeaseMetrics metrics) {
LoadingCache<String, NamedMinTimestampTracker> namedMinTimestampTrackers =
Caffeine.newBuilder().build(name -> NamedMinTimestampTrackerImpl.create(name, metrics));
return new NamedMinTimestampLockCollection(namedMinTimestampTrackers);
}

AsyncLock getImmutableTimestampLock(long timestamp) {
return getNamedTimestampLockInternal(TimestampLeaseName.RESERVED_NAME_FOR_IMMUTABLE_TIMESTAMP, timestamp);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.palantir.atlasdb.timelock.lock;

import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.lock.LockDescriptor;
import com.palantir.lock.StringLockDescriptor;
import com.palantir.logsafe.SafeArg;
Expand All @@ -24,16 +25,26 @@
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.concurrent.GuardedBy;

final class NamedMinTimestampTrackerImpl implements NamedMinTimestampTracker {
private final String timestampName;
private final AtomicInteger numLocksHeld;

@GuardedBy("this")
private final SortedMap<Long, UUID> holdersByTimestamp = new TreeMap<>();

NamedMinTimestampTrackerImpl(String timestampName) {
private NamedMinTimestampTrackerImpl(String timestampName, AtomicInteger numLocksHeld) {
this.timestampName = timestampName;
this.numLocksHeld = numLocksHeld;
}

static NamedMinTimestampTracker create(String timestampName, TimestampLeaseMetrics metrics) {
AtomicInteger numLocksHeld = new AtomicInteger();
metrics.locksHeld().name(timestampName).build(numLocksHeld::get);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I left comments on this in #7400. The writes are synchronized through the object's intrinsic lock, and the get under the hood is a volatile read. Should I just make this a volatile?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I think that's right, go for it


return new NamedMinTimestampTrackerImpl(timestampName, numLocksHeld);
}

@Override
Expand All @@ -46,6 +57,7 @@ public synchronized void lock(long timestamp, UUID requestId) {
SafeArg.of("requestId", requestId),
SafeArg.of("currentHolder", holdersByTimestamp.get(timestamp)));
}
numLocksHeld.incrementAndGet();
}

@Override
Expand All @@ -58,6 +70,7 @@ public synchronized void unlock(long timestamp, UUID requestId) {
SafeArg.of("requestId", requestId),
SafeArg.of("currentHolder", holdersByTimestamp.get(timestamp)));
}
numLocksHeld.decrementAndGet();
}

@Override
Expand Down
12 changes: 12 additions & 0 deletions timelock-impl/src/main/metrics/timestampleases.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
options:
javaPackage: 'com.palantir.atlasdb.timelock.timestampleases'

namespaces:
timestampLease:
docs: Metrics tracking TimeLock's implementation of timestamp leases
metrics:
locksHeld:
Copy link
Contributor

Choose a reason for hiding this comment

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

Should trackers be aware of the concept of locks / is that an implementation detail? I'd be more inclined to say number of lease holders or similar...

docs: Number of locks held in timestamp trackers
type: gauge
tags:
- name
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: timestampName or similar

Also, importantly, this means that we must not have a large number of timestamp names without breaking metrics infrastructure; how are we going to track that?

Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.palantir.atlasdb.timelock.lock.LockLog;
import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.lock.v2.LockToken;
import com.palantir.timestamp.InMemoryTimestampService;
import com.palantir.timestamp.ManagedTimestampService;
Expand Down Expand Up @@ -261,7 +262,8 @@ private static AsyncLockService createLockService(ScheduledExecutorService execu
new LockLog(new MetricRegistry(), () -> 100L),
executor,
executor,
BufferMetrics.of(new DefaultTaggedMetricRegistry()));
BufferMetrics.of(new DefaultTaggedMetricRegistry()),
TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));
}

private static AsyncTimelockService createAsyncTimelockService(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.palantir.atlasdb.timelock.lock.LockLog;
import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.timestamp.InMemoryTimestampService;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import java.util.List;
Expand Down Expand Up @@ -60,7 +61,8 @@ private AsyncTimelockService createTimelockService() {
new LockLog(new MetricRegistry(), () -> 100L),
executor,
executor,
BufferMetrics.of(new DefaultTaggedMetricRegistry()));
BufferMetrics.of(new DefaultTaggedMetricRegistry()),
TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));

return new AsyncTimelockServiceImpl(
lockService,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.atlasdb.util.MetricsManager;
import com.palantir.atlasdb.util.MetricsManagers;
import com.palantir.common.concurrent.PTExecutors;
Expand All @@ -36,7 +37,8 @@ public void executorsShutDownAfterClose() {
new LockLog(metricsManager.getRegistry(), () -> 1L),
reaperExecutor,
timeoutExecutor,
BufferMetrics.of(metricsManager.getTaggedRegistry()));
BufferMetrics.of(metricsManager.getTaggedRegistry()),
TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry()));

asyncLockService.close();
assertThat(reaperExecutor.isShutdown()).isTrue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;

import com.palantir.atlasdb.timelock.api.TimestampLeaseName;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import java.util.Set;
Expand All @@ -32,7 +34,8 @@ public final class NamedMinTimestampLockCollectionTest {
private static final UUID REQUEST_ID_2 = UUID.randomUUID();
private static final UUID REQUEST_ID_3 = UUID.randomUUID();

private final NamedMinTimestampLockCollection locks = new NamedMinTimestampLockCollection();
private final NamedMinTimestampLockCollection locks =
NamedMinTimestampLockCollection.create(TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));

@MethodSource("getTimestampLeaseNames")
@ParameterizedTest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import static com.palantir.logsafe.testing.Assertions.assertThatLoggableExceptionThrownBy;
import static org.assertj.core.api.Assertions.assertThat;

import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.logsafe.SafeArg;
import com.palantir.logsafe.exceptions.SafeIllegalStateException;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
import org.junit.jupiter.api.Test;
Expand All @@ -31,7 +33,8 @@ public final class NamedMinTimestampTrackerTest {

private static final long TIMESTAMP_1 = 5L;

private final NamedMinTimestampTracker tracker = new NamedMinTimestampTrackerImpl("ts");
private final NamedMinTimestampTracker tracker =
NamedMinTimestampTrackerImpl.create("ts", TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));

@Test
public void registersTimestampWhenLocked() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import com.palantir.atlasdb.timelock.lock.LockLog;
import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.lockwatches.RequestMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.atlasdb.util.MetricsManager;
import com.palantir.atlasdb.util.MetricsManagers;
import com.palantir.lock.AtlasRowLockDescriptor;
Expand Down Expand Up @@ -78,7 +79,8 @@ public class AsyncTimeLockServiceMetadataTest {
lockLog,
scheduledExecutorService,
scheduledExecutorService,
BufferMetrics.of(metricsManager.getTaggedRegistry()));
BufferMetrics.of(metricsManager.getTaggedRegistry()),
TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry()));
private final AsyncTimelockServiceImpl timeLockService =
new AsyncTimelockServiceImpl(asyncLockService, new InMemoryTimestampService(), lockLog, requestMetrics);
private final ConjureStartTransactionsRequest startTransactionsRequestWithInitialVersion =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import com.palantir.atlasdb.timelock.lock.watch.LockWatchingService;
import com.palantir.atlasdb.timelock.lock.watch.LockWatchingServiceImpl;
import com.palantir.atlasdb.timelock.lockwatches.BufferMetrics;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.atlasdb.util.MetricsManager;
import com.palantir.atlasdb.util.MetricsManagers;
import com.palantir.flake.FlakeRetryTest;
import com.palantir.leader.NotCurrentLeaderException;
Expand Down Expand Up @@ -62,12 +64,11 @@ public class AsyncLockServiceEteTest {

private final LockLog lockLog = new LockLog(new MetricRegistry(), () -> 2L);
private final HeldLocksCollection heldLocks = HeldLocksCollection.create(clock);
private final LockWatchingService lockWatchingService = new LockWatchingServiceImpl(
heldLocks,
clock.id(),
BufferMetrics.of(MetricsManagers.createForTests().getTaggedRegistry()));
private final MetricsManager metricsManager = MetricsManagers.createForTests();
private final LockWatchingService lockWatchingService =
new LockWatchingServiceImpl(heldLocks, clock.id(), BufferMetrics.of(metricsManager.getTaggedRegistry()));
private final AsyncLockService service = new AsyncLockService(
new LockManager(),
LockManager.create(TimestampLeaseMetrics.of(metricsManager.getTaggedRegistry())),
new LockAcquirer(
new LockLog(new MetricRegistry(), () -> 2L),
Executors.newSingleThreadScheduledExecutor(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import static org.assertj.core.api.Assertions.assertThat;

import com.google.common.collect.ImmutableSet;
import com.palantir.atlasdb.timelock.timestampleases.TimestampLeaseMetrics;
import com.palantir.lock.LockDescriptor;
import com.palantir.lock.StringLockDescriptor;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
Expand All @@ -30,7 +32,8 @@

public class LockCollectionTest {

private final LockManager lockManager = new LockManager();
private final LockManager lockManager =
LockManager.create(TimestampLeaseMetrics.of(new DefaultTaggedMetricRegistry()));

@Test
public void createsLocksOnDemand() {
Expand Down