diff --git a/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java b/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java index 5b9265cf012..a8cba94ed94 100644 --- a/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java +++ b/timelock-agent/src/main/java/com/palantir/timelock/paxos/AsyncTimeLockServicesCreator.java @@ -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; @@ -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())); diff --git a/timelock-impl/build.gradle b/timelock-impl/build.gradle index 361bcd9ef18..bcaf63a584a 100644 --- a/timelock-impl/build.gradle +++ b/timelock-impl/build.gradle @@ -113,4 +113,5 @@ dependencies { license { exclude '**/RequestMetrics.java' exclude '**/BufferMetrics.java' + exclude '**/TimestampLeaseMetrics.java' } diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java index 967cb8f5abe..bc6fca41335 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/AsyncLockService.java @@ -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; @@ -64,7 +65,8 @@ public static AsyncLockService createDefault( LockLog lockLog, ScheduledExecutorService reaperExecutor, ScheduledExecutorService timeoutExecutor, - BufferMetrics bufferMetrics) { + BufferMetrics bufferMetrics, + TimestampLeaseMetrics timestampLeaseMetrics) { LeaderClock clock = LeaderClock.create(); @@ -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(), diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java index 0b2aae7132d..bd3cd9e9a99 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/LockManager.java @@ -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 descriptors) { return exclusiveLocks.getAll(descriptors); diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java index 16e4681beb1..87bb4bc93a0 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollection.java @@ -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 namedMinTimestampTrackers = - Caffeine.newBuilder().build(NamedMinTimestampTrackerImpl::new); + private final LoadingCache namedMinTimestampTrackers; + + private NamedMinTimestampLockCollection(LoadingCache namedMinTimestampTrackers) { + this.namedMinTimestampTrackers = namedMinTimestampTrackers; + } + + static NamedMinTimestampLockCollection create(TimestampLeaseMetrics metrics) { + LoadingCache 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); diff --git a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java index ce648ed1ee5..311a0e3e6ac 100644 --- a/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java +++ b/timelock-impl/src/main/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerImpl.java @@ -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; @@ -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 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); + + return new NamedMinTimestampTrackerImpl(timestampName, numLocksHeld); } @Override @@ -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 @@ -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 diff --git a/timelock-impl/src/main/metrics/timestampleases.yml b/timelock-impl/src/main/metrics/timestampleases.yml new file mode 100644 index 00000000000..b9fce0b9bd8 --- /dev/null +++ b/timelock-impl/src/main/metrics/timestampleases.yml @@ -0,0 +1,12 @@ +options: + javaPackage: 'com.palantir.atlasdb.timelock.timestampleases' + +namespaces: + timestampLease: + docs: Metrics tracking TimeLock's implementation of timestamp leases + metrics: + locksHeld: + docs: Number of locks held in timestamp trackers + type: gauge + tags: + - name diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java index d42cc2163f4..9a79ae90438 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/AsyncTimelockServiceImplTest.java @@ -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; @@ -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( diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java index bae17272c87..4482b2e956e 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/batch/RemotingTimestampLeaseServiceAdapterTest.java @@ -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; @@ -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, diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java index ee97facee0f..d8a400b8cdc 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceTest.java @@ -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; @@ -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(); diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java index b0962e3937c..0014ed9afcb 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampLockCollectionTest.java @@ -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; @@ -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 diff --git a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java index 342ca6c4d06..14ce1dd7e94 100644 --- a/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java +++ b/timelock-impl/src/test/java/com/palantir/atlasdb/timelock/lock/NamedMinTimestampTrackerTest.java @@ -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; @@ -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() { diff --git a/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java b/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java index 70cefd07a3c..3694d38ed76 100644 --- a/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java +++ b/timelock-server/src/integTest/java/com/palantir/atlasdb/timelock/AsyncTimeLockServiceMetadataTest.java @@ -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; @@ -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 = diff --git a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java index f578e11691d..3efbaab9a3c 100644 --- a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java +++ b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/AsyncLockServiceEteTest.java @@ -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; @@ -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(), diff --git a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java index 9bf50d06b2a..7c1f8b362e7 100644 --- a/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java +++ b/timelock-server/src/test/java/com/palantir/atlasdb/timelock/lock/LockCollectionTest.java @@ -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; @@ -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() {