diff --git a/serving/src/main/java/feast/serving/controller/ServingServiceGRpcController.java b/serving/src/main/java/feast/serving/controller/ServingServiceGRpcController.java index 531be39..81bbfd0 100644 --- a/serving/src/main/java/feast/serving/controller/ServingServiceGRpcController.java +++ b/serving/src/main/java/feast/serving/controller/ServingServiceGRpcController.java @@ -25,6 +25,7 @@ import feast.proto.serving.ServingServiceGrpc.ServingServiceImplBase; import feast.serving.config.FeastProperties; import feast.serving.exception.SpecRetrievalException; +import feast.serving.interceptors.GrpcMonitoringContext; import feast.serving.interceptors.GrpcMonitoringInterceptor; import feast.serving.service.ServingServiceV2; import feast.serving.util.RequestHelper; @@ -86,6 +87,9 @@ public void getOnlineFeaturesV2( // project set at root level overrides the project set at feature table level this.authorizationService.authorizeRequest( SecurityContextHolder.getContext(), request.getProject()); + + // update monitoring context + GrpcMonitoringContext.getInstance().setProject(request.getProject()); } RequestHelper.validateOnlineRequest(request); Span span = tracer.buildSpan("getOnlineFeaturesV2").start(); diff --git a/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringContext.java b/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringContext.java new file mode 100644 index 0000000..48d8d76 --- /dev/null +++ b/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringContext.java @@ -0,0 +1,47 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright 2018-2021 The Feast Authors + * + * 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 + * + * https://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 feast.serving.interceptors; + +import java.util.Optional; + +public class GrpcMonitoringContext { + private static GrpcMonitoringContext INSTANCE; + + final ThreadLocal project = new ThreadLocal(); + + private GrpcMonitoringContext() {} + + public static GrpcMonitoringContext getInstance() { + if (INSTANCE == null) { + INSTANCE = new GrpcMonitoringContext(); + } + + return INSTANCE; + } + + public void setProject(String name) { + this.project.set(name); + } + + public Optional getProject() { + return Optional.ofNullable(this.project.get()); + } + + public void clearProject() { + this.project.set(null); + } +} diff --git a/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringInterceptor.java b/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringInterceptor.java index bc7ed89..735f8c5 100644 --- a/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringInterceptor.java +++ b/serving/src/main/java/feast/serving/interceptors/GrpcMonitoringInterceptor.java @@ -24,6 +24,7 @@ import io.grpc.ServerCallHandler; import io.grpc.ServerInterceptor; import io.grpc.Status; +import java.util.Optional; /** * GrpcMonitoringInterceptor intercepts GRPC calls to provide request latency histogram metrics in @@ -39,12 +40,16 @@ public Listener interceptCall( String fullMethodName = call.getMethodDescriptor().getFullMethodName(); String methodName = fullMethodName.substring(fullMethodName.indexOf("/") + 1); + GrpcMonitoringContext.getInstance().clearProject(); + return next.startCall( new SimpleForwardingServerCall(call) { @Override public void close(Status status, Metadata trailers) { + Optional projectName = GrpcMonitoringContext.getInstance().getProject(); + Metrics.requestLatency - .labels(methodName) + .labels(methodName, projectName.orElse("")) .observe((System.currentTimeMillis() - startCallMillis) / 1000f); Metrics.grpcRequestCount.labels(methodName, status.getCode().name()).inc(); super.close(status, trailers); diff --git a/serving/src/main/java/feast/serving/util/Metrics.java b/serving/src/main/java/feast/serving/util/Metrics.java index 90b9493..dca2b5e 100644 --- a/serving/src/main/java/feast/serving/util/Metrics.java +++ b/serving/src/main/java/feast/serving/util/Metrics.java @@ -26,7 +26,7 @@ public class Metrics { .name("request_latency_seconds") .subsystem("feast_serving") .help("Request latency in seconds") - .labelNames("method") + .labelNames("method", "project") .register(); public static final Histogram requestEntityCountDistribution =