Search in sources :

Example 1 with RequestId

use of com.google.gerrit.server.logging.RequestId in project gerrit by GerritCodeReview.

the class ReceiveCommits method processCommands.

ReceiveCommitsResult processCommands(Collection<ReceiveCommand> commands, MultiProgressMonitor progress) throws StorageException {
    checkState(!used, "Tried to re-use a ReceiveCommits objects that is single-use only");
    long start = TimeUtil.nowNanos();
    parsePushOptions();
    String clientProvidedDeadlineValue = Iterables.getLast(pushOptions.get("deadline"), /* defaultValue= */
    null);
    int commandCount = commands.size();
    try (TraceContext traceContext = TraceContext.newTrace(tracePushOption.isPresent(), tracePushOption.orElse(null), (tagName, traceId) -> addMessage(tagName + ": " + traceId));
        PerformanceLogContext performanceLogContext = new PerformanceLogContext(config, performanceLoggers);
        TraceTimer traceTimer = newTimer("processCommands", Metadata.builder().resourceCount(commandCount))) {
        RequestInfo requestInfo = RequestInfo.builder(RequestInfo.RequestType.GIT_RECEIVE, user, traceContext).project(project.getNameKey()).build();
        requestListeners.runEach(l -> l.onRequest(requestInfo));
        traceContext.addTag(RequestId.Type.RECEIVE_ID, new RequestId(project.getNameKey().get()));
        // Log the push options here, rather than in parsePushOptions(), so that they are included
        // into the trace if tracing is enabled.
        logger.atFine().log("push options: %s", receivePack.getPushOptions());
        Task commandProgress = progress.beginSubTask("refs", UNKNOWN);
        commands = commands.stream().map(c -> wrapReceiveCommand(c, commandProgress)).collect(toList());
        try (RequestStateContext requestStateContext = RequestStateContext.open().addRequestStateProvider(progress).addRequestStateProvider(deadlineCheckerFactory.create(start, requestInfo, clientProvidedDeadlineValue))) {
            processCommandsUnsafe(commands, progress);
            rejectRemaining(commands, INTERNAL_SERVER_ERROR);
        } catch (InvalidDeadlineException e) {
            rejectRemaining(commands, e.getMessage());
        } catch (RuntimeException e) {
            Optional<RequestCancelledException> requestCancelledException = RequestCancelledException.getFromCausalChain(e);
            if (!requestCancelledException.isPresent()) {
                Throwables.throwIfUnchecked(e);
            }
            cancellationMetrics.countCancelledRequest(requestInfo, requestCancelledException.get().getCancellationReason());
            StringBuilder msg = new StringBuilder(requestCancelledException.get().formatCancellationReason());
            if (requestCancelledException.get().getCancellationMessage().isPresent()) {
                msg.append(String.format(" (%s)", requestCancelledException.get().getCancellationMessage().get()));
            }
            rejectRemaining(commands, msg.toString());
        }
        // This sends error messages before the 'done' string of the progress monitor is sent.
        // Currently, the test framework relies on this ordering to understand if pushes completed
        // successfully.
        sendErrorMessages();
        commandProgress.end();
        loggingTags = traceContext.getTags();
        logger.atFine().log("Processing commands done.");
    }
    progress.end();
    return result.build();
}
Also used : Task(com.google.gerrit.server.git.MultiProgressMonitor.Task) RequestStateContext(com.google.gerrit.server.cancellation.RequestStateContext) RequestId(com.google.gerrit.server.logging.RequestId) Optional(java.util.Optional) RequestInfo(com.google.gerrit.server.RequestInfo) PerformanceLogContext(com.google.gerrit.server.logging.PerformanceLogContext) InvalidDeadlineException(com.google.gerrit.server.InvalidDeadlineException) TraceTimer(com.google.gerrit.server.logging.TraceContext.TraceTimer) TraceContext(com.google.gerrit.server.logging.TraceContext)

Example 2 with RequestId

use of com.google.gerrit.server.logging.RequestId in project gerrit by GerritCodeReview.

the class MergeOp method merge.

/**
 * Merges the given change.
 *
 * <p>Depending on the server configuration, more changes may be affected, e.g. by submission of a
 * topic or via superproject subscriptions. All affected changes are integrated using the projects
 * integration strategy.
 *
 * @param change the change to be merged.
 * @param caller the identity of the caller
 * @param checkSubmitRules whether the prolog submit rules should be evaluated
 * @param submitInput parameters regarding the merge
 * @throws RestApiException if an error occurred.
 * @throws PermissionBackendException if permissions can't be checked
 * @throws IOException an error occurred reading from NoteDb.
 * @return the merged change
 */
public Change merge(Change change, IdentifiedUser caller, boolean checkSubmitRules, SubmitInput submitInput, boolean dryrun) throws RestApiException, UpdateException, IOException, ConfigInvalidException, PermissionBackendException {
    this.submitInput = submitInput;
    this.notify = notifyResolver.resolve(firstNonNull(submitInput.notify, NotifyHandling.ALL), submitInput.notifyDetails);
    this.dryrun = dryrun;
    this.caller = caller;
    this.ts = TimeUtil.now();
    this.submissionId = new SubmissionId(change);
    try (TraceContext traceContext = TraceContext.open().addTag(RequestId.Type.SUBMISSION_ID, new RequestId(submissionId.toString()))) {
        openRepoManager();
        logger.atFine().log("Beginning integration of %s", change);
        try {
            ChangeSet indexBackedChangeSet = mergeSuperSet.setMergeOpRepoManager(orm).completeChangeSet(change, caller, /* includingTopicClosure= */
            false);
            if (!indexBackedChangeSet.ids().contains(change.getId())) {
                // indexBackedChangeSet contains only open changes, if the change is missing in this set
                // it might be that the change was concurrently submitted in the meantime.
                change = changeDataFactory.create(change).reloadChange();
                if (!change.isNew()) {
                    throw new ResourceConflictException("change is " + ChangeUtil.status(change));
                }
                throw new IllegalStateException(String.format("change %s missing from %s", change.getId(), indexBackedChangeSet));
            }
            if (indexBackedChangeSet.furtherHiddenChanges()) {
                throw new AuthException("A change to be submitted with " + change.getId() + " is not visible");
            }
            logger.atFine().log("Calculated to merge %s", indexBackedChangeSet);
            // Reload ChangeSet so that we don't rely on (potentially) stale index data for merging
            ChangeSet noteDbChangeSet = reloadChanges(indexBackedChangeSet);
            // At this point, any change that isn't new can be filtered out since they were only here
            // in the first place due to stale index.
            List<ChangeData> filteredChanges = new ArrayList<>();
            for (ChangeData changeData : noteDbChangeSet.changes()) {
                if (!changeData.change().getStatus().equals(Status.NEW)) {
                    logger.atFine().log("Change %s has status %s due to stale index, so it is skipped during submit", changeData.getId(), changeData.change().getStatus().name());
                    continue;
                }
                filteredChanges.add(changeData);
            }
            // There are no hidden changes (or else we would have thrown AuthException above).
            ChangeSet filteredNoteDbChangeSet = new ChangeSet(filteredChanges, /* hiddenChanges= */
            ImmutableList.of());
            // Count cross-project submissions outside of the retry loop. The chance of a single project
            // failing increases with the number of projects, so the failure count would be inflated if
            // this metric were incremented inside of integrateIntoHistory.
            int projects = filteredNoteDbChangeSet.projects().size();
            if (projects > 1) {
                topicMetrics.topicSubmissions.increment();
            }
            SubmissionExecutor submissionExecutor = new SubmissionExecutor(dryrun, superprojectUpdateSubmissionListeners);
            RetryTracker retryTracker = new RetryTracker();
            retryHelper.changeUpdate("integrateIntoHistory", updateFactory -> {
                long attempt = retryTracker.lastAttemptNumber + 1;
                boolean isRetry = attempt > 1;
                if (isRetry) {
                    logger.atFine().log("Retrying, attempt #%d; skipping merged changes", attempt);
                    this.ts = TimeUtil.now();
                    openRepoManager();
                }
                this.commitStatus = new CommitStatus(filteredNoteDbChangeSet, isRetry);
                if (checkSubmitRules) {
                    logger.atFine().log("Checking submit rules and state");
                    checkSubmitRulesAndState(filteredNoteDbChangeSet, isRetry);
                } else {
                    logger.atFine().log("Bypassing submit rules");
                    bypassSubmitRulesAndRequirements(filteredNoteDbChangeSet);
                }
                integrateIntoHistory(filteredNoteDbChangeSet, submissionExecutor);
                return null;
            }).listener(retryTracker).defaultTimeoutMultiplier(filteredNoteDbChangeSet.projects().size() * 2).retryOn(t -> t instanceof RuntimeException).call();
            submissionExecutor.afterExecutions(orm);
            if (projects > 1) {
                topicMetrics.topicSubmissionsCompleted.increment();
            }
            // (e.g. caller provided a change that was already merged).
            return updatedChanges.containsKey(change.getId()) ? updatedChanges.get(change.getId()) : change;
        } catch (IOException e) {
            // Anything before the merge attempt is an error
            throw new StorageException(e);
        }
    }
}
Also used : ResourceNotFoundException(com.google.gerrit.extensions.restapi.ResourceNotFoundException) SuperprojectUpdateOnSubmission(com.google.gerrit.server.update.SuperprojectUpdateOnSubmission) ListMultimap(com.google.common.collect.ListMultimap) MultimapBuilder(com.google.common.collect.MultimapBuilder) InternalUser(com.google.gerrit.server.InternalUser) Inject(com.google.inject.Inject) SubmissionId(com.google.gerrit.entities.SubmissionId) UpdateException(com.google.gerrit.server.update.UpdateException) SubmitRequirementResult(com.google.gerrit.entities.SubmitRequirementResult) MergeUpdateException(com.google.gerrit.exceptions.MergeUpdateException) Preconditions.checkArgument(com.google.common.base.Preconditions.checkArgument) BatchUpdate(com.google.gerrit.server.update.BatchUpdate) SubmitInput(com.google.gerrit.extensions.api.changes.SubmitInput) Map(java.util.Map) AuthException(com.google.gerrit.extensions.restapi.AuthException) StoreSubmitRequirementsOp(com.google.gerrit.server.notedb.StoreSubmitRequirementsOp) RetryHelper(com.google.gerrit.server.update.RetryHelper) MergeTip(com.google.gerrit.server.git.MergeTip) Collectors.toSet(java.util.stream.Collectors.toSet) ImmutableSetMultimap(com.google.common.collect.ImmutableSetMultimap) ImmutableSet(com.google.common.collect.ImmutableSet) Status(com.google.gerrit.entities.Change.Status) ImmutableMap(com.google.common.collect.ImmutableMap) TraceContext(com.google.gerrit.server.logging.TraceContext) SubmitType(com.google.gerrit.extensions.client.SubmitType) Collection(java.util.Collection) Set(java.util.Set) Constants(org.eclipse.jgit.lib.Constants) CodeReviewCommit(com.google.gerrit.server.git.CodeReviewCommit) Instant(java.time.Instant) RetryListener(com.github.rholder.retry.RetryListener) SubmitRecord(com.google.gerrit.entities.SubmitRecord) Collectors(java.util.stream.Collectors) BranchNameKey(com.google.gerrit.entities.BranchNameKey) NotifyHandling(com.google.gerrit.extensions.api.changes.NotifyHandling) SubmitTypeRecord(com.google.gerrit.entities.SubmitTypeRecord) ChangeData(com.google.gerrit.server.query.change.ChangeData) List(java.util.List) Nullable(com.google.gerrit.common.Nullable) Ref(org.eclipse.jgit.lib.Ref) AutoValue(com.google.auto.value.AutoValue) InternalChangeQuery(com.google.gerrit.server.query.change.InternalChangeQuery) Optional(java.util.Optional) MoreObjects.firstNonNull(com.google.common.base.MoreObjects.firstNonNull) Counter0(com.google.gerrit.metrics.Counter0) MetricMaker(com.google.gerrit.metrics.MetricMaker) BatchUpdateOp(com.google.gerrit.server.update.BatchUpdateOp) FluentLogger(com.google.common.flogger.FluentLogger) Joiner(com.google.common.base.Joiner) ChangeMessagesUtil(com.google.gerrit.server.ChangeMessagesUtil) Singleton(com.google.inject.Singleton) PermissionBackendException(com.google.gerrit.server.permissions.PermissionBackendException) ConfigInvalidException(org.eclipse.jgit.errors.ConfigInvalidException) RevCommit(org.eclipse.jgit.revwalk.RevCommit) OpenRepo(com.google.gerrit.server.submit.MergeOpRepoManager.OpenRepo) IncorrectObjectTypeException(org.eclipse.jgit.errors.IncorrectObjectTypeException) HashMap(java.util.HashMap) Function(java.util.function.Function) SubmissionListener(com.google.gerrit.server.update.SubmissionListener) MergeValidators(com.google.gerrit.server.git.validators.MergeValidators) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) ImmutableList(com.google.common.collect.ImmutableList) SubmissionExecutor(com.google.gerrit.server.update.SubmissionExecutor) Description(com.google.gerrit.metrics.Description) Objects.requireNonNull(java.util.Objects.requireNonNull) Change(com.google.gerrit.entities.Change) PatchSet(com.google.gerrit.entities.PatchSet) Comparator.comparing(java.util.Comparator.comparing) RestApiException(com.google.gerrit.extensions.restapi.RestApiException) ChangeUtil(com.google.gerrit.server.ChangeUtil) LockFailureException(com.google.gerrit.git.LockFailureException) ChangeContext(com.google.gerrit.server.update.ChangeContext) MergeValidationException(com.google.gerrit.server.git.validators.MergeValidationException) LinkedHashSet(java.util.LinkedHashSet) SubmitRequirement(com.google.gerrit.entities.SubmitRequirement) NotifyResolver(com.google.gerrit.server.change.NotifyResolver) OpenBranch(com.google.gerrit.server.submit.MergeOpRepoManager.OpenBranch) StorageException(com.google.gerrit.exceptions.StorageException) Attempt(com.github.rholder.retry.Attempt) NoSuchProjectException(com.google.gerrit.server.project.NoSuchProjectException) ChangeNotes(com.google.gerrit.server.notedb.ChangeNotes) IOException(java.io.IOException) SubmitRuleOptions(com.google.gerrit.server.project.SubmitRuleOptions) SetMultimap(com.google.common.collect.SetMultimap) ObjectId(org.eclipse.jgit.lib.ObjectId) Provider(com.google.inject.Provider) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) IdentifiedUser(com.google.gerrit.server.IdentifiedUser) Project(com.google.gerrit.entities.Project) TimeUtil(com.google.gerrit.server.util.time.TimeUtil) RequestId(com.google.gerrit.server.logging.RequestId) RequestId(com.google.gerrit.server.logging.RequestId) ArrayList(java.util.ArrayList) AuthException(com.google.gerrit.extensions.restapi.AuthException) IOException(java.io.IOException) ChangeData(com.google.gerrit.server.query.change.ChangeData) ResourceConflictException(com.google.gerrit.extensions.restapi.ResourceConflictException) SubmissionId(com.google.gerrit.entities.SubmissionId) TraceContext(com.google.gerrit.server.logging.TraceContext) StorageException(com.google.gerrit.exceptions.StorageException) SubmissionExecutor(com.google.gerrit.server.update.SubmissionExecutor)

Example 3 with RequestId

use of com.google.gerrit.server.logging.RequestId in project gerrit by GerritCodeReview.

the class RetryHelper method execute.

/**
 * Executes an action and records the number of attempts and the timeout as metrics.
 *
 * @param actionType the type of the action
 * @param action the action which should be executed and retried on failure
 * @param opts options for retrying the action on failure
 * @param exceptionPredicate predicate to control on which exception the action should be retried
 * @return the result of executing the action
 * @throws Exception any error or exception that made the action fail, callers are expected to
 *     catch and inspect this Throwable to decide carefully whether it should be re-thrown
 */
<T> T execute(String actionType, Action<T> action, Options opts, Predicate<Throwable> exceptionPredicate) throws Exception {
    MetricListener listener = new MetricListener();
    try (TraceContext traceContext = TraceContext.open()) {
        RetryerBuilder<T> retryerBuilder = createRetryerBuilder(actionType, opts, t -> {
            // retried (e.g. LockFailure). The retry has good chances to succeed.
            if (exceptionPredicate.test(t)) {
                return true;
            }
            String actionName = opts.actionName().orElse("N/A");
            // Exception hooks may identify additional exceptions for retry.
            if (exceptionHooks.stream().anyMatch(h -> h.shouldRetry(actionType, actionName, t))) {
                return true;
            }
            // of the failure. If a trace was already done there is no need to retry.
            if (retryWithTraceOnFailure && opts.retryWithTrace().isPresent() && opts.retryWithTrace().get().test(t)) {
                // skipped.
                if (exceptionHooks.stream().anyMatch(h -> h.skipRetryWithTrace(actionType, actionName, t))) {
                    return false;
                }
                String cause = formatCause(t);
                if (!TraceContext.isTracing()) {
                    String traceId = "retry-on-failure-" + new RequestId();
                    traceContext.addTag(RequestId.Type.TRACE_ID, traceId).forceLogging();
                    logger.atWarning().withCause(t).log("AutoRetry: %s failed, retry with tracing enabled (cause = %s)", actionName, cause);
                    opts.onAutoTrace().ifPresent(c -> c.accept(traceId));
                    metrics.autoRetryCount.increment(actionType, actionName, cause);
                    return true;
                }
                // A non-recoverable failure occurred. We retried the operation with tracing
                // enabled and it failed again. Log the failure so that admin can see if it
                // differs from the failure that triggered the retry.
                logger.atWarning().withCause(t).log("AutoRetry: auto-retry of %s has failed (cause = %s)", actionName, cause);
                metrics.failuresOnAutoRetryCount.increment(actionType, actionName, cause);
                return false;
            }
            return false;
        });
        retryerBuilder.withRetryListener(listener);
        return executeWithTimeoutCount(actionType, action, opts, retryerBuilder.build(), listener);
    } finally {
        if (listener.getAttemptCount() > 1) {
            logger.atWarning().log("%s was attempted %d times", actionType, listener.getAttemptCount());
            metrics.attemptCounts.incrementBy(actionType, opts.actionName().orElse("N/A"), listener.getOriginalCause().map(this::formatCause).orElse("_unknown"), listener.getAttemptCount() - 1);
        }
    }
}
Also used : RequestId(com.google.gerrit.server.logging.RequestId) TraceContext(com.google.gerrit.server.logging.TraceContext)

Aggregations

RequestId (com.google.gerrit.server.logging.RequestId)3 TraceContext (com.google.gerrit.server.logging.TraceContext)3 Optional (java.util.Optional)2 Attempt (com.github.rholder.retry.Attempt)1 RetryListener (com.github.rholder.retry.RetryListener)1 AutoValue (com.google.auto.value.AutoValue)1 Joiner (com.google.common.base.Joiner)1 MoreObjects.firstNonNull (com.google.common.base.MoreObjects.firstNonNull)1 Preconditions.checkArgument (com.google.common.base.Preconditions.checkArgument)1 ImmutableList (com.google.common.collect.ImmutableList)1 ImmutableMap (com.google.common.collect.ImmutableMap)1 ImmutableSet (com.google.common.collect.ImmutableSet)1 ImmutableSetMultimap (com.google.common.collect.ImmutableSetMultimap)1 ListMultimap (com.google.common.collect.ListMultimap)1 MultimapBuilder (com.google.common.collect.MultimapBuilder)1 SetMultimap (com.google.common.collect.SetMultimap)1 FluentLogger (com.google.common.flogger.FluentLogger)1 Nullable (com.google.gerrit.common.Nullable)1 BranchNameKey (com.google.gerrit.entities.BranchNameKey)1 Change (com.google.gerrit.entities.Change)1