1 /* 2 * Copyright 2022 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.gcp.observability.interceptors; 18 19 import static com.google.common.base.Preconditions.checkNotNull; 20 21 import com.google.auto.value.AutoValue; 22 import com.google.common.annotations.VisibleForTesting; 23 import io.grpc.Internal; 24 import io.grpc.gcp.observability.ObservabilityConfig; 25 import io.grpc.gcp.observability.ObservabilityConfig.LogFilter; 26 import java.util.List; 27 28 /** 29 * Parses gRPC GcpObservability configuration filters for interceptors usage. 30 */ 31 @Internal 32 public class ConfigFilterHelper { 33 public static final FilterParams NO_FILTER_PARAMS 34 = FilterParams.create(false, 0, 0); 35 36 private final ObservabilityConfig config; 37 ConfigFilterHelper(ObservabilityConfig config)38 private ConfigFilterHelper(ObservabilityConfig config) { 39 this.config = config; 40 } 41 42 /** 43 * Creates and returns helper instance for log filtering. 44 * 45 * @param config processed ObservabilityConfig object 46 * @return helper instance for filtering 47 */ getInstance(ObservabilityConfig config)48 public static ConfigFilterHelper getInstance(ObservabilityConfig config) { 49 return new ConfigFilterHelper(config); 50 } 51 52 53 /** 54 * Checks if the corresponding service/method passed needs to be logged according to user provided 55 * observability configuration. 56 * Filters are evaluated in text order, first match is used. 57 * 58 * @param fullMethodName the fully qualified name of the method 59 * @param client set to true if method being checked is a client method; false otherwise 60 * @return FilterParams object 1. specifies if the corresponding method needs to be logged 61 * (log field will be set to true) 2. values of payload limits retrieved from configuration 62 */ logRpcMethod(String fullMethodName, boolean client)63 public FilterParams logRpcMethod(String fullMethodName, boolean client) { 64 FilterParams params = NO_FILTER_PARAMS; 65 66 int index = checkNotNull(fullMethodName, "fullMethodName").lastIndexOf('/'); 67 String serviceName = fullMethodName.substring(0, index); 68 69 List<LogFilter> logFilters = 70 client ? config.getClientLogFilters() : config.getServerLogFilters(); 71 72 // TODO (dnvindhya): Optimize by caching results for fullMethodName. 73 for (LogFilter logFilter : logFilters) { 74 if (logFilter.matchAll 75 || logFilter.services.contains(serviceName) 76 || logFilter.methods.contains(fullMethodName)) { 77 if (logFilter.excludePattern) { 78 return params; 79 } 80 int currentHeaderBytes = logFilter.headerBytes; 81 int currentMessageBytes = logFilter.messageBytes; 82 return FilterParams.create(true, currentHeaderBytes, currentMessageBytes); 83 } 84 } 85 return params; 86 } 87 88 /** 89 * Class containing results for method/service filter information, such as flag for logging 90 * method/service and payload limits to be used for filtering. 91 */ 92 @AutoValue 93 public abstract static class FilterParams { 94 log()95 abstract boolean log(); 96 headerBytes()97 abstract int headerBytes(); 98 messageBytes()99 abstract int messageBytes(); 100 101 @VisibleForTesting create(boolean log, int headerBytes, int messageBytes)102 public static FilterParams create(boolean log, int headerBytes, int messageBytes) { 103 return new AutoValue_ConfigFilterHelper_FilterParams( 104 log, headerBytes, messageBytes); 105 } 106 } 107 } 108