com.palantir.atlasdb.debug.TransactionPostMortemRunner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of atlasdb-config Show documentation
Show all versions of atlasdb-config Show documentation
Palantir open source project
/*
* (c) Copyright 2019 Palantir Technologies Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.palantir.atlasdb.debug;
import com.codahale.metrics.MetricRegistry;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.palantir.atlasdb.config.AtlasDbConfig;
import com.palantir.atlasdb.config.AtlasDbRuntimeConfig;
import com.palantir.atlasdb.config.ImmutableTimeLockClientConfig;
import com.palantir.atlasdb.config.ServerListConfig;
import com.palantir.atlasdb.config.ServerListConfigs;
import com.palantir.atlasdb.config.TimeLockClientConfig;
import com.palantir.atlasdb.debug.ClientLockDiagnosticCollector.ClientLockDiagnosticDigest;
import com.palantir.atlasdb.debug.FullDiagnosticDigest.LockDigest;
import com.palantir.atlasdb.factory.ServiceCreator;
import com.palantir.atlasdb.keyvalue.api.TableReference;
import com.palantir.atlasdb.timelock.api.ConjureLockDescriptor;
import com.palantir.atlasdb.transaction.api.TransactionManager;
import com.palantir.atlasdb.util.MetricsManager;
import com.palantir.common.persist.Persistable;
import com.palantir.common.streams.KeyedStream;
import com.palantir.conjure.java.api.config.service.UserAgent;
import com.palantir.logsafe.SafeArg;
import com.palantir.logsafe.UnsafeArg;
import com.palantir.logsafe.logger.SafeLogger;
import com.palantir.logsafe.logger.SafeLoggerFactory;
import com.palantir.refreshable.Refreshable;
import com.palantir.tritium.metrics.registry.DefaultTaggedMetricRegistry;
import com.palantir.util.OptionalResolver;
import java.time.Instant;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* TODO(fdesouza): Remove this once PDS-95791 is resolved.
* @deprecated Remove this once PDS-95791 is resolved.
*/
@Deprecated
public class TransactionPostMortemRunner {
private static final SafeLogger log = SafeLoggerFactory.get(TransactionPostMortemRunner.class);
private final String timelockNamespace;
private final ClientLockDiagnosticCollector clientLockDiagnosticCollector;
private final WritesDigestEmitter writesDigestEmitter;
private final LockDiagnosticInfoService timelockDiagnosticService;
private final LocalLockTracker localLockTracker;
public TransactionPostMortemRunner(
TransactionManager transactionManager,
TableReference tableReference,
AtlasDbConfig install,
Refreshable runtime,
ClientLockDiagnosticCollector clientLockDiagnosticCollector,
LocalLockTracker localLockTracker) {
this.timelockNamespace = timelockNamespace(install);
this.clientLockDiagnosticCollector = clientLockDiagnosticCollector;
this.timelockDiagnosticService = createRpcClient(install, runtime);
this.writesDigestEmitter = new WritesDigestEmitter(transactionManager, tableReference);
this.localLockTracker = localLockTracker;
}
public FullDiagnosticDigest conductPostMortem(Persistable row, byte[] columnName) {
WritesDigest digest = writesDigestEmitter.getDigest(row, columnName);
log.info("raw digest", SafeArg.of("rawDigest", digest));
Map snapshot = clientLockDiagnosticCollector.getSnapshot();
log.info("client lock diagnostic digest", UnsafeArg.of("clientLockDiagnosticDigest", snapshot));
Optional lockDiagnosticInfo = getTimelockDiagnostics(snapshot);
log.info("lock diagnostic info", UnsafeArg.of("timelockLockDiagnosticInfo", lockDiagnosticInfo));
Set lockRequestIdsEvictedMidLockRequest = lockDiagnosticInfo
.map(LockDiagnosticInfo::requestIdsEvictedMidLockRequest)
.orElseGet(ImmutableSet::of);
log.info(
"lock Request Ids Evicted Mid Lock Request",
SafeArg.of("lockRequestIdsEvictedMidLockRequest", lockRequestIdsEvictedMidLockRequest));
Set> transactionDigests =
digest.completedOrAbortedTransactions().keySet().stream()
.map(startTimestamp -> transactionDigest(
startTimestamp,
digest,
lockDiagnosticInfo,
snapshot.getOrDefault(startTimestamp, ClientLockDiagnosticDigest.missingEntry())))
.collect(Collectors.toSet());
log.info("transaction digests", UnsafeArg.of("transactionDigests", transactionDigests));
List locallyTrackedLockEvents = localLockTracker.getLocalLockHistory();
return ImmutableFullDiagnosticDigest.builder()
.rawData(ImmutableRawData.of(digest, lockDiagnosticInfo, snapshot))
.addAllInProgressTransactions(digest.inProgressTransactions())
.lockRequestIdsEvictedMidLockRequest(lockRequestIdsEvictedMidLockRequest)
.completedTransactionDigests(transactionDigests)
.trackedLockEvents(locallyTrackedLockEvents)
.build();
}
private Optional getTimelockDiagnostics(Map snapshot) {
try {
return timelockDiagnosticService.getEnhancedLockDiagnosticInfo(timelockNamespace, requestIds(snapshot));
} catch (Exception e) {
log.warn("recieved exception whilst trying to fetch timelock diagnostics", e);
return Optional.empty();
}
}
private static Set requestIds(Map clientDigests) {
return clientDigests.values().stream()
.map(TransactionPostMortemRunner::requestIds)
.flatMap(Collection::stream)
.collect(Collectors.toSet());
}
private static Set requestIds(ClientLockDiagnosticDigest clientDigest) {
return ImmutableSet.builder()
.addAll(clientDigest.lockRequests().keySet())
.add(clientDigest.immutableTimestampRequestId())
.build();
}
private static FullDiagnosticDigest.CompletedTransactionDigest transactionDigest(
long startTimestamp,
WritesDigest writesDigest,
Optional timelockLockInfo,
ClientLockDiagnosticDigest clientLockDigest) {
Map> lockRequests = ImmutableMap.>builder()
.putAll(clientLockDigest.lockRequests())
.put(clientLockDigest.immutableTimestampRequestId(), ImmutableSet.of())
.buildOrThrow();
Map lockDigests = KeyedStream.stream(lockRequests)
.map((requestId, descriptors) ->
lockDigest(descriptors, timelockLockInfo.map(info -> lockState(requestId, info))))
.collectToMap();
return ImmutableCompletedTransactionDigest.builder()
.startTimestamp(startTimestamp)
.commitTimestamp(writesDigest.completedOrAbortedTransactions().get(startTimestamp))
.value(writesDigest.allWrittenValuesDeserialized().get(startTimestamp))
.immutableTimestamp(clientLockDigest.immutableTimestamp())
.immutableTimestampLockRequestId(clientLockDigest.immutableTimestampRequestId())
.locks(lockDigests)
.addAllConflictTrace(clientLockDigest.writeWriteConflictTrace())
.build();
}
private static Map lockState(UUID requestId, LockDiagnosticInfo diagnosticInfo) {
return diagnosticInfo.lockInfos().get(requestId).lockStates();
}
private static LockDigest lockDigest(
Set lockDescriptors, Optional