Add extension points that allows to listen to incoming requests
Basic information about the incoming request is provided when this extension point is invoked. This includes: * the request type (whether this is a REST request, an SSH request or a git upload or receive) * the calling user * the trace context * the name of the project for which the request is being done (only available if the request is tied to a project or change) TraceContext gets 2 new methods so that implementations of the extension point can check if tracing is enabled and if yes, which trace ID is set. Possible use cases for the extension point are: * setting logging tags for a request (implemented in follow-up change) * implement advanced tracing (e.g. allow to enable tracing for a certain user or project by configuration) If implementations of the extension point have the need to open resources that must be closed when the request is done, we should consider to allow adding close listeners to the TraceContext, that are guranteed to be invoked when the TraceContext gets closed. Signed-off-by: Edwin Kempin <ekempin@google.com> Change-Id: Ic328c4d6a66ab7dbfb848c41dd4ada9b1dedb847
This commit is contained in:
@@ -2810,6 +2810,12 @@ invocation of the extension point does not happen immediately, but only at the
|
|||||||
end of a request (REST call, SSH call, git push). Implementors can write the
|
end of a request (REST call, SSH call, git push). Implementors can write the
|
||||||
execution times into a performance log for further analysis.
|
execution times into a performance log for further analysis.
|
||||||
|
|
||||||
|
[[request-listener]]
|
||||||
|
== Request Listener
|
||||||
|
|
||||||
|
`com.google.gerrit.server.RequestListener` is an extension point that is
|
||||||
|
invoked each time the server executes a request from a user.
|
||||||
|
|
||||||
[[plugins_hosting]]
|
[[plugins_hosting]]
|
||||||
== Plugins source code hosting
|
== Plugins source code hosting
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ java_library(
|
|||||||
"//java/com/google/gerrit/exceptions",
|
"//java/com/google/gerrit/exceptions",
|
||||||
"//java/com/google/gerrit/extensions:api",
|
"//java/com/google/gerrit/extensions:api",
|
||||||
"//java/com/google/gerrit/git",
|
"//java/com/google/gerrit/git",
|
||||||
|
"//java/com/google/gerrit/index:query_exception",
|
||||||
"//java/com/google/gerrit/json",
|
"//java/com/google/gerrit/json",
|
||||||
"//java/com/google/gerrit/launcher",
|
"//java/com/google/gerrit/launcher",
|
||||||
"//java/com/google/gerrit/lifecycle",
|
"//java/com/google/gerrit/lifecycle",
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import com.google.gerrit.reviewdb.client.Project;
|
|||||||
import com.google.gerrit.server.AccessPath;
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.AnonymousUser;
|
import com.google.gerrit.server.AnonymousUser;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
|
import com.google.gerrit.server.RequestInfo;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.audit.HttpAuditEvent;
|
import com.google.gerrit.server.audit.HttpAuditEvent;
|
||||||
import com.google.gerrit.server.cache.CacheModule;
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
import com.google.gerrit.server.git.DefaultAdvertiseRefsHook;
|
import com.google.gerrit.server.git.DefaultAdvertiseRefsHook;
|
||||||
@@ -35,6 +37,7 @@ import com.google.gerrit.server.git.UploadPackInitializer;
|
|||||||
import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
|
import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
|
||||||
import com.google.gerrit.server.git.validators.UploadValidators;
|
import com.google.gerrit.server.git.validators.UploadValidators;
|
||||||
import com.google.gerrit.server.group.GroupAuditService;
|
import com.google.gerrit.server.group.GroupAuditService;
|
||||||
|
import com.google.gerrit.server.logging.TraceContext;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
|
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||||
@@ -339,6 +342,7 @@ public class GitOverHttpServlet extends GitServlet {
|
|||||||
private final Provider<CurrentUser> userProvider;
|
private final Provider<CurrentUser> userProvider;
|
||||||
private final GroupAuditService groupAuditService;
|
private final GroupAuditService groupAuditService;
|
||||||
private final Metrics metrics;
|
private final Metrics metrics;
|
||||||
|
private final PluginSetContext<RequestListener> requestListeners;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
UploadFilter(
|
UploadFilter(
|
||||||
@@ -346,12 +350,14 @@ public class GitOverHttpServlet extends GitServlet {
|
|||||||
PermissionBackend permissionBackend,
|
PermissionBackend permissionBackend,
|
||||||
Provider<CurrentUser> userProvider,
|
Provider<CurrentUser> userProvider,
|
||||||
GroupAuditService groupAuditService,
|
GroupAuditService groupAuditService,
|
||||||
Metrics metrics) {
|
Metrics metrics,
|
||||||
|
PluginSetContext<RequestListener> requestListeners) {
|
||||||
this.uploadValidatorsFactory = uploadValidatorsFactory;
|
this.uploadValidatorsFactory = uploadValidatorsFactory;
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.userProvider = userProvider;
|
this.userProvider = userProvider;
|
||||||
this.groupAuditService = groupAuditService;
|
this.groupAuditService = groupAuditService;
|
||||||
this.metrics = metrics;
|
this.metrics = metrics;
|
||||||
|
this.requestListeners = requestListeners;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -369,7 +375,14 @@ public class GitOverHttpServlet extends GitServlet {
|
|||||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
String sessionId = httpRequest.getSession().getId();
|
String sessionId = httpRequest.getSession().getId();
|
||||||
|
|
||||||
try {
|
try (TraceContext traceContext = TraceContext.open()) {
|
||||||
|
RequestInfo requestInfo =
|
||||||
|
RequestInfo.builder(
|
||||||
|
RequestInfo.RequestType.GIT_UPLOAD, userProvider.get(), traceContext)
|
||||||
|
.project(state.getNameKey())
|
||||||
|
.build();
|
||||||
|
requestListeners.runEach(l -> l.onRequest(requestInfo));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
perm.check(ProjectPermission.RUN_UPLOAD_PACK);
|
perm.check(ProjectPermission.RUN_UPLOAD_PACK);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
|
|||||||
@@ -102,22 +102,30 @@ import com.google.gerrit.git.LockFailureException;
|
|||||||
import com.google.gerrit.httpd.WebSession;
|
import com.google.gerrit.httpd.WebSession;
|
||||||
import com.google.gerrit.httpd.restapi.ParameterParser.QueryParams;
|
import com.google.gerrit.httpd.restapi.ParameterParser.QueryParams;
|
||||||
import com.google.gerrit.json.OutputFormat;
|
import com.google.gerrit.json.OutputFormat;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
import com.google.gerrit.server.AccessPath;
|
import com.google.gerrit.server.AccessPath;
|
||||||
import com.google.gerrit.server.AnonymousUser;
|
import com.google.gerrit.server.AnonymousUser;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.OptionUtil;
|
import com.google.gerrit.server.OptionUtil;
|
||||||
|
import com.google.gerrit.server.RequestInfo;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.audit.ExtendedHttpAuditEvent;
|
import com.google.gerrit.server.audit.ExtendedHttpAuditEvent;
|
||||||
import com.google.gerrit.server.cache.PerThreadCache;
|
import com.google.gerrit.server.cache.PerThreadCache;
|
||||||
|
import com.google.gerrit.server.change.ChangeFinder;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.group.GroupAuditService;
|
import com.google.gerrit.server.group.GroupAuditService;
|
||||||
import com.google.gerrit.server.logging.PerformanceLogContext;
|
import com.google.gerrit.server.logging.PerformanceLogContext;
|
||||||
import com.google.gerrit.server.logging.PerformanceLogger;
|
import com.google.gerrit.server.logging.PerformanceLogger;
|
||||||
import com.google.gerrit.server.logging.RequestId;
|
import com.google.gerrit.server.logging.RequestId;
|
||||||
import com.google.gerrit.server.logging.TraceContext;
|
import com.google.gerrit.server.logging.TraceContext;
|
||||||
|
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||||
import com.google.gerrit.server.permissions.GlobalPermission;
|
import com.google.gerrit.server.permissions.GlobalPermission;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||||
|
import com.google.gerrit.server.plugincontext.PluginSetContext;
|
||||||
import com.google.gerrit.server.quota.QuotaException;
|
import com.google.gerrit.server.quota.QuotaException;
|
||||||
|
import com.google.gerrit.server.restapi.change.ChangesCollection;
|
||||||
|
import com.google.gerrit.server.restapi.project.ProjectsCollection;
|
||||||
import com.google.gerrit.server.update.UpdateException;
|
import com.google.gerrit.server.update.UpdateException;
|
||||||
import com.google.gerrit.server.util.time.TimeUtil;
|
import com.google.gerrit.server.util.time.TimeUtil;
|
||||||
import com.google.gerrit.util.http.CacheHeaders;
|
import com.google.gerrit.util.http.CacheHeaders;
|
||||||
@@ -227,6 +235,7 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
final Provider<CurrentUser> currentUser;
|
final Provider<CurrentUser> currentUser;
|
||||||
final DynamicItem<WebSession> webSession;
|
final DynamicItem<WebSession> webSession;
|
||||||
final Provider<ParameterParser> paramParser;
|
final Provider<ParameterParser> paramParser;
|
||||||
|
final PluginSetContext<RequestListener> requestListeners;
|
||||||
final PermissionBackend permissionBackend;
|
final PermissionBackend permissionBackend;
|
||||||
final GroupAuditService auditService;
|
final GroupAuditService auditService;
|
||||||
final RestApiMetrics metrics;
|
final RestApiMetrics metrics;
|
||||||
@@ -234,27 +243,32 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
final RestApiQuotaEnforcer quotaChecker;
|
final RestApiQuotaEnforcer quotaChecker;
|
||||||
final Config config;
|
final Config config;
|
||||||
final DynamicSet<PerformanceLogger> performanceLoggers;
|
final DynamicSet<PerformanceLogger> performanceLoggers;
|
||||||
|
final ChangeFinder changeFinder;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
Globals(
|
Globals(
|
||||||
Provider<CurrentUser> currentUser,
|
Provider<CurrentUser> currentUser,
|
||||||
DynamicItem<WebSession> webSession,
|
DynamicItem<WebSession> webSession,
|
||||||
Provider<ParameterParser> paramParser,
|
Provider<ParameterParser> paramParser,
|
||||||
|
PluginSetContext<RequestListener> requestListeners,
|
||||||
PermissionBackend permissionBackend,
|
PermissionBackend permissionBackend,
|
||||||
GroupAuditService auditService,
|
GroupAuditService auditService,
|
||||||
RestApiMetrics metrics,
|
RestApiMetrics metrics,
|
||||||
RestApiQuotaEnforcer quotaChecker,
|
RestApiQuotaEnforcer quotaChecker,
|
||||||
@GerritServerConfig Config config,
|
@GerritServerConfig Config config,
|
||||||
DynamicSet<PerformanceLogger> performanceLoggers) {
|
DynamicSet<PerformanceLogger> performanceLoggers,
|
||||||
|
ChangeFinder changeFinder) {
|
||||||
this.currentUser = currentUser;
|
this.currentUser = currentUser;
|
||||||
this.webSession = webSession;
|
this.webSession = webSession;
|
||||||
this.paramParser = paramParser;
|
this.paramParser = paramParser;
|
||||||
|
this.requestListeners = requestListeners;
|
||||||
this.permissionBackend = permissionBackend;
|
this.permissionBackend = permissionBackend;
|
||||||
this.auditService = auditService;
|
this.auditService = auditService;
|
||||||
this.metrics = metrics;
|
this.metrics = metrics;
|
||||||
this.quotaChecker = quotaChecker;
|
this.quotaChecker = quotaChecker;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.performanceLoggers = performanceLoggers;
|
this.performanceLoggers = performanceLoggers;
|
||||||
|
this.changeFinder = changeFinder;
|
||||||
allowOrigin = makeAllowOrigin(config);
|
allowOrigin = makeAllowOrigin(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +315,11 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
ViewData viewData = null;
|
ViewData viewData = null;
|
||||||
|
|
||||||
try (TraceContext traceContext = enableTracing(req, res)) {
|
try (TraceContext traceContext = enableTracing(req, res)) {
|
||||||
|
List<IdString> path = splitPath(req);
|
||||||
|
|
||||||
|
RequestInfo requestInfo = createRequestInfo(traceContext, path);
|
||||||
|
globals.requestListeners.runEach(l -> l.onRequest(requestInfo));
|
||||||
|
|
||||||
try (PerThreadCache ignored = PerThreadCache.create()) {
|
try (PerThreadCache ignored = PerThreadCache.create()) {
|
||||||
// It's important that the PerformanceLogContext is closed before the response is sent to
|
// It's important that the PerformanceLogContext is closed before the response is sent to
|
||||||
// the client. Only this way it is ensured that the invocation of the PerformanceLogger
|
// the client. Only this way it is ensured that the invocation of the PerformanceLogger
|
||||||
@@ -329,7 +348,6 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
}
|
}
|
||||||
checkUserSession(req);
|
checkUserSession(req);
|
||||||
|
|
||||||
List<IdString> path = splitPath(req);
|
|
||||||
RestCollection<RestResource, RestResource> rc = members.get();
|
RestCollection<RestResource, RestResource> rc = members.get();
|
||||||
globals
|
globals
|
||||||
.permissionBackend
|
.permissionBackend
|
||||||
@@ -1406,6 +1424,27 @@ public class RestApiServlet extends HttpServlet {
|
|||||||
return traceContext;
|
return traceContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private RequestInfo createRequestInfo(TraceContext traceContext, List<IdString> path) {
|
||||||
|
RequestInfo.Builder requestInfo =
|
||||||
|
RequestInfo.builder(RequestInfo.RequestType.REST, globals.currentUser.get(), traceContext);
|
||||||
|
|
||||||
|
if (path.size() < 1) {
|
||||||
|
return requestInfo.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
RestCollection<?, ?> rootCollection = members.get();
|
||||||
|
String resourceId = path.get(0).get();
|
||||||
|
if (rootCollection instanceof ProjectsCollection) {
|
||||||
|
requestInfo.project(Project.nameKey(resourceId));
|
||||||
|
} else if (rootCollection instanceof ChangesCollection) {
|
||||||
|
ChangeNotes changeNotes = globals.changeFinder.findOne(resourceId);
|
||||||
|
if (changeNotes != null) {
|
||||||
|
requestInfo.project(changeNotes.getProjectName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return requestInfo.build();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isDelete(HttpServletRequest req) {
|
private boolean isDelete(HttpServletRequest req) {
|
||||||
return "DELETE".equals(req.getMethod());
|
return "DELETE".equals(req.getMethod());
|
||||||
}
|
}
|
||||||
|
|||||||
85
java/com/google/gerrit/server/RequestInfo.java
Normal file
85
java/com/google/gerrit/server/RequestInfo.java
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
// Copyright (C) 2019 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// 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.google.gerrit.server;
|
||||||
|
|
||||||
|
import com.google.auto.value.AutoValue;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project;
|
||||||
|
import com.google.gerrit.server.logging.TraceContext;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/** Information about a request that was received from a user. */
|
||||||
|
@AutoValue
|
||||||
|
public abstract class RequestInfo {
|
||||||
|
/** Channel through which a user request was received. */
|
||||||
|
public enum RequestType {
|
||||||
|
/** request type for git push */
|
||||||
|
GIT_RECEIVE,
|
||||||
|
|
||||||
|
/** request type for git fetch */
|
||||||
|
GIT_UPLOAD,
|
||||||
|
|
||||||
|
/** request type for call to REST API */
|
||||||
|
REST,
|
||||||
|
|
||||||
|
/** request type for call to SSH API */
|
||||||
|
SSH
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type of the request, telling through which channel the request was coming in.
|
||||||
|
*
|
||||||
|
* <p>See {@link RequestType} for the types that are used by Gerrit core. Other request types are
|
||||||
|
* possible, e.g. if a plugin supports receiving requests through another channel.
|
||||||
|
*/
|
||||||
|
public abstract String requestType();
|
||||||
|
|
||||||
|
/** The user that has sent the request. */
|
||||||
|
public abstract CurrentUser callingUser();
|
||||||
|
|
||||||
|
/** The trace context of the request. */
|
||||||
|
public abstract TraceContext traceContext();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the project for which the request is being done. Only available if the request is
|
||||||
|
* tied to a project or change. If a project is available it's not guaranteed that it actually
|
||||||
|
* exists (e.g. if a user made a request for a project that doesn't exist).
|
||||||
|
*/
|
||||||
|
public abstract Optional<Project.NameKey> project();
|
||||||
|
|
||||||
|
public static RequestInfo.Builder builder(
|
||||||
|
RequestType requestType, CurrentUser callingUser, TraceContext traceContext) {
|
||||||
|
return new AutoValue_RequestInfo.Builder()
|
||||||
|
.requestType(requestType)
|
||||||
|
.callingUser(callingUser)
|
||||||
|
.traceContext(traceContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AutoValue.Builder
|
||||||
|
public abstract static class Builder {
|
||||||
|
public abstract Builder requestType(String requestType);
|
||||||
|
|
||||||
|
public Builder requestType(RequestType requestType) {
|
||||||
|
return requestType(requestType.name());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Builder callingUser(CurrentUser callingUser);
|
||||||
|
|
||||||
|
public abstract Builder traceContext(TraceContext traceContext);
|
||||||
|
|
||||||
|
public abstract Builder project(Project.NameKey projectName);
|
||||||
|
|
||||||
|
public abstract RequestInfo build();
|
||||||
|
}
|
||||||
|
}
|
||||||
22
java/com/google/gerrit/server/RequestListener.java
Normal file
22
java/com/google/gerrit/server/RequestListener.java
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (C) 2019 The Android Open Source Project
|
||||||
|
//
|
||||||
|
// 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.google.gerrit.server;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.annotations.ExtensionPoint;
|
||||||
|
|
||||||
|
@ExtensionPoint
|
||||||
|
public interface RequestListener {
|
||||||
|
void onRequest(RequestInfo requestInfo);
|
||||||
|
}
|
||||||
@@ -79,6 +79,7 @@ import com.google.gerrit.server.CmdLineParserModule;
|
|||||||
import com.google.gerrit.server.CreateGroupPermissionSyncer;
|
import com.google.gerrit.server.CreateGroupPermissionSyncer;
|
||||||
import com.google.gerrit.server.DynamicOptions;
|
import com.google.gerrit.server.DynamicOptions;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.account.AccountCacheImpl;
|
import com.google.gerrit.server.account.AccountCacheImpl;
|
||||||
import com.google.gerrit.server.account.AccountControl;
|
import com.google.gerrit.server.account.AccountControl;
|
||||||
import com.google.gerrit.server.account.AccountDeactivator;
|
import com.google.gerrit.server.account.AccountDeactivator;
|
||||||
@@ -384,6 +385,7 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
DynamicSet.setOf(binder(), SubmitRule.class);
|
DynamicSet.setOf(binder(), SubmitRule.class);
|
||||||
DynamicSet.setOf(binder(), QuotaEnforcer.class);
|
DynamicSet.setOf(binder(), QuotaEnforcer.class);
|
||||||
DynamicSet.setOf(binder(), PerformanceLogger.class);
|
DynamicSet.setOf(binder(), PerformanceLogger.class);
|
||||||
|
DynamicSet.setOf(binder(), RequestListener.class);
|
||||||
|
|
||||||
DynamicMap.mapOf(binder(), MailFilter.class);
|
DynamicMap.mapOf(binder(), MailFilter.class);
|
||||||
bind(MailFilter.class).annotatedWith(Exports.named("ListMailFilter")).to(ListMailFilter.class);
|
bind(MailFilter.class).annotatedWith(Exports.named("ListMailFilter")).to(ListMailFilter.class);
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ import com.google.gerrit.server.CreateGroupPermissionSyncer;
|
|||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.PatchSetUtil;
|
import com.google.gerrit.server.PatchSetUtil;
|
||||||
import com.google.gerrit.server.PublishCommentUtil;
|
import com.google.gerrit.server.PublishCommentUtil;
|
||||||
|
import com.google.gerrit.server.RequestInfo;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.account.AccountResolver;
|
import com.google.gerrit.server.account.AccountResolver;
|
||||||
import com.google.gerrit.server.change.ChangeInserter;
|
import com.google.gerrit.server.change.ChangeInserter;
|
||||||
import com.google.gerrit.server.change.NotifyResolver;
|
import com.google.gerrit.server.change.NotifyResolver;
|
||||||
@@ -329,6 +331,7 @@ class ReceiveCommits {
|
|||||||
private final ReceiveConfig receiveConfig;
|
private final ReceiveConfig receiveConfig;
|
||||||
private final RefOperationValidators.Factory refValidatorsFactory;
|
private final RefOperationValidators.Factory refValidatorsFactory;
|
||||||
private final ReplaceOp.Factory replaceOpFactory;
|
private final ReplaceOp.Factory replaceOpFactory;
|
||||||
|
private final PluginSetContext<RequestListener> requestListeners;
|
||||||
private final RetryHelper retryHelper;
|
private final RetryHelper retryHelper;
|
||||||
private final RequestScopePropagator requestScopePropagator;
|
private final RequestScopePropagator requestScopePropagator;
|
||||||
private final Sequences seq;
|
private final Sequences seq;
|
||||||
@@ -407,6 +410,7 @@ class ReceiveCommits {
|
|||||||
ReceiveConfig receiveConfig,
|
ReceiveConfig receiveConfig,
|
||||||
RefOperationValidators.Factory refValidatorsFactory,
|
RefOperationValidators.Factory refValidatorsFactory,
|
||||||
ReplaceOp.Factory replaceOpFactory,
|
ReplaceOp.Factory replaceOpFactory,
|
||||||
|
PluginSetContext<RequestListener> requestListeners,
|
||||||
RetryHelper retryHelper,
|
RetryHelper retryHelper,
|
||||||
RequestScopePropagator requestScopePropagator,
|
RequestScopePropagator requestScopePropagator,
|
||||||
Sequences seq,
|
Sequences seq,
|
||||||
@@ -452,6 +456,7 @@ class ReceiveCommits {
|
|||||||
this.receiveConfig = receiveConfig;
|
this.receiveConfig = receiveConfig;
|
||||||
this.refValidatorsFactory = refValidatorsFactory;
|
this.refValidatorsFactory = refValidatorsFactory;
|
||||||
this.replaceOpFactory = replaceOpFactory;
|
this.replaceOpFactory = replaceOpFactory;
|
||||||
|
this.requestListeners = requestListeners;
|
||||||
this.retryHelper = retryHelper;
|
this.retryHelper = retryHelper;
|
||||||
this.requestScopePropagator = requestScopePropagator;
|
this.requestScopePropagator = requestScopePropagator;
|
||||||
this.seq = seq;
|
this.seq = seq;
|
||||||
@@ -537,6 +542,11 @@ class ReceiveCommits {
|
|||||||
newTimer("processCommands", Metadata.builder().resourceCount(commandCount));
|
newTimer("processCommands", Metadata.builder().resourceCount(commandCount));
|
||||||
PerformanceLogContext performanceLogContext =
|
PerformanceLogContext performanceLogContext =
|
||||||
new PerformanceLogContext(config, performanceLoggers)) {
|
new PerformanceLogContext(config, performanceLoggers)) {
|
||||||
|
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()));
|
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
|
// Log the push options here, rather than in parsePushOptions(), so that they are included
|
||||||
|
|||||||
@@ -243,6 +243,15 @@ public class TraceContext implements AutoCloseable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isTracing() {
|
||||||
|
return LoggingContext.getInstance().isLoggingForced();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getTraceId() {
|
||||||
|
return LoggingContext.getInstance().getTagsAsMap().get(RequestId.Type.TRACE_ID.name()).stream()
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
for (Table.Cell<String, String, Boolean> cell : tags.cellSet()) {
|
for (Table.Cell<String, String, Boolean> cell : tags.cellSet()) {
|
||||||
|
|||||||
@@ -16,10 +16,13 @@ package com.google.gerrit.sshd;
|
|||||||
|
|
||||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
import com.google.gerrit.server.AccessPath;
|
import com.google.gerrit.server.AccessPath;
|
||||||
|
import com.google.gerrit.server.RequestInfo;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.config.GerritServerConfig;
|
import com.google.gerrit.server.config.GerritServerConfig;
|
||||||
import com.google.gerrit.server.logging.PerformanceLogContext;
|
import com.google.gerrit.server.logging.PerformanceLogContext;
|
||||||
import com.google.gerrit.server.logging.PerformanceLogger;
|
import com.google.gerrit.server.logging.PerformanceLogger;
|
||||||
import com.google.gerrit.server.logging.TraceContext;
|
import com.google.gerrit.server.logging.TraceContext;
|
||||||
|
import com.google.gerrit.server.plugincontext.PluginSetContext;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -29,6 +32,7 @@ import org.kohsuke.args4j.Option;
|
|||||||
|
|
||||||
public abstract class SshCommand extends BaseCommand {
|
public abstract class SshCommand extends BaseCommand {
|
||||||
@Inject private DynamicSet<PerformanceLogger> performanceLoggers;
|
@Inject private DynamicSet<PerformanceLogger> performanceLoggers;
|
||||||
|
@Inject private PluginSetContext<RequestListener> requestListeners;
|
||||||
@Inject @GerritServerConfig private Config config;
|
@Inject @GerritServerConfig private Config config;
|
||||||
|
|
||||||
@Option(name = "--trace", usage = "enable request tracing")
|
@Option(name = "--trace", usage = "enable request tracing")
|
||||||
@@ -50,6 +54,9 @@ public abstract class SshCommand extends BaseCommand {
|
|||||||
try (TraceContext traceContext = enableTracing();
|
try (TraceContext traceContext = enableTracing();
|
||||||
PerformanceLogContext performanceLogContext =
|
PerformanceLogContext performanceLogContext =
|
||||||
new PerformanceLogContext(config, performanceLoggers)) {
|
new PerformanceLogContext(config, performanceLoggers)) {
|
||||||
|
RequestInfo requestInfo =
|
||||||
|
RequestInfo.builder(RequestInfo.RequestType.SSH, user, traceContext).build();
|
||||||
|
requestListeners.runEach(l -> l.onRequest(requestInfo));
|
||||||
SshCommand.this.run();
|
SshCommand.this.run();
|
||||||
} finally {
|
} finally {
|
||||||
stdout.flush();
|
stdout.flush();
|
||||||
|
|||||||
@@ -17,15 +17,19 @@ package com.google.gerrit.sshd.commands;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
import com.google.gerrit.extensions.restapi.AuthException;
|
import com.google.gerrit.extensions.restapi.AuthException;
|
||||||
|
import com.google.gerrit.server.RequestInfo;
|
||||||
|
import com.google.gerrit.server.RequestListener;
|
||||||
import com.google.gerrit.server.git.DefaultAdvertiseRefsHook;
|
import com.google.gerrit.server.git.DefaultAdvertiseRefsHook;
|
||||||
import com.google.gerrit.server.git.TransferConfig;
|
import com.google.gerrit.server.git.TransferConfig;
|
||||||
import com.google.gerrit.server.git.UploadPackInitializer;
|
import com.google.gerrit.server.git.UploadPackInitializer;
|
||||||
import com.google.gerrit.server.git.validators.UploadValidationException;
|
import com.google.gerrit.server.git.validators.UploadValidationException;
|
||||||
import com.google.gerrit.server.git.validators.UploadValidators;
|
import com.google.gerrit.server.git.validators.UploadValidators;
|
||||||
|
import com.google.gerrit.server.logging.TraceContext;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
|
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||||
import com.google.gerrit.server.permissions.ProjectPermission;
|
import com.google.gerrit.server.permissions.ProjectPermission;
|
||||||
|
import com.google.gerrit.server.plugincontext.PluginSetContext;
|
||||||
import com.google.gerrit.sshd.AbstractGitCommand;
|
import com.google.gerrit.sshd.AbstractGitCommand;
|
||||||
import com.google.gerrit.sshd.SshSession;
|
import com.google.gerrit.sshd.SshSession;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -43,6 +47,7 @@ final class Upload extends AbstractGitCommand {
|
|||||||
@Inject private DynamicSet<PreUploadHook> preUploadHooks;
|
@Inject private DynamicSet<PreUploadHook> preUploadHooks;
|
||||||
@Inject private DynamicSet<PostUploadHook> postUploadHooks;
|
@Inject private DynamicSet<PostUploadHook> postUploadHooks;
|
||||||
@Inject private DynamicSet<UploadPackInitializer> uploadPackInitializers;
|
@Inject private DynamicSet<UploadPackInitializer> uploadPackInitializers;
|
||||||
|
@Inject private PluginSetContext<RequestListener> requestListeners;
|
||||||
@Inject private UploadValidators.Factory uploadValidatorsFactory;
|
@Inject private UploadValidators.Factory uploadValidatorsFactory;
|
||||||
@Inject private SshSession session;
|
@Inject private SshSession session;
|
||||||
@Inject private PermissionBackend permissionBackend;
|
@Inject private PermissionBackend permissionBackend;
|
||||||
@@ -73,7 +78,13 @@ final class Upload extends AbstractGitCommand {
|
|||||||
for (UploadPackInitializer initializer : uploadPackInitializers) {
|
for (UploadPackInitializer initializer : uploadPackInitializers) {
|
||||||
initializer.init(projectState.getNameKey(), up);
|
initializer.init(projectState.getNameKey(), up);
|
||||||
}
|
}
|
||||||
try {
|
try (TraceContext traceContext = TraceContext.open()) {
|
||||||
|
RequestInfo requestInfo =
|
||||||
|
RequestInfo.builder(RequestInfo.RequestType.GIT_UPLOAD, user, traceContext)
|
||||||
|
.project(projectState.getNameKey())
|
||||||
|
.build();
|
||||||
|
requestListeners.runEach(l -> l.onRequest(requestInfo));
|
||||||
|
|
||||||
up.upload(in, out, err);
|
up.upload(in, out, err);
|
||||||
session.setPeerAgent(up.getPeerUserAgent());
|
session.setPeerAgent(up.getPeerUserAgent());
|
||||||
} catch (UploadValidationException e) {
|
} catch (UploadValidationException e) {
|
||||||
|
|||||||
@@ -25,5 +25,6 @@ junit_tests(
|
|||||||
"//lib/jgit/org.eclipse.jgit:jgit",
|
"//lib/jgit/org.eclipse.jgit:jgit",
|
||||||
"//lib/jgit/org.eclipse.jgit.junit:junit",
|
"//lib/jgit/org.eclipse.jgit.junit:junit",
|
||||||
"//lib/truth",
|
"//lib/truth",
|
||||||
|
"//lib/truth:truth-java8-extension",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user