...

Source file src/google.golang.org/grpc/internal/binarylog/binarylog.go

Documentation: google.golang.org/grpc/internal/binarylog

     1  /*
     2   *
     3   * Copyright 2018 gRPC authors.
     4   *
     5   * Licensed under the Apache License, Version 2.0 (the "License");
     6   * you may not use this file except in compliance with the License.
     7   * You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   *
    17   */
    18  
    19  // Package binarylog implementation binary logging as defined in
    20  // https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
    21  package binarylog
    22  
    23  import (
    24  	"fmt"
    25  	"os"
    26  
    27  	"google.golang.org/grpc/grpclog"
    28  	"google.golang.org/grpc/internal/grpcutil"
    29  )
    30  
    31  var grpclogLogger = grpclog.Component("binarylog")
    32  
    33  // Logger specifies MethodLoggers for method names with a Log call that
    34  // takes a context.
    35  //
    36  // This is used in the 1.0 release of gcp/observability, and thus must not be
    37  // deleted or changed.
    38  type Logger interface {
    39  	GetMethodLogger(methodName string) MethodLogger
    40  }
    41  
    42  // binLogger is the global binary logger for the binary. One of this should be
    43  // built at init time from the configuration (environment variable or flags).
    44  //
    45  // It is used to get a MethodLogger for each individual method.
    46  var binLogger Logger
    47  
    48  // SetLogger sets the binary logger.
    49  //
    50  // Only call this at init time.
    51  func SetLogger(l Logger) {
    52  	binLogger = l
    53  }
    54  
    55  // GetLogger gets the binary logger.
    56  //
    57  // Only call this at init time.
    58  func GetLogger() Logger {
    59  	return binLogger
    60  }
    61  
    62  // GetMethodLogger returns the MethodLogger for the given methodName.
    63  //
    64  // methodName should be in the format of "/service/method".
    65  //
    66  // Each MethodLogger returned by this method is a new instance. This is to
    67  // generate sequence id within the call.
    68  func GetMethodLogger(methodName string) MethodLogger {
    69  	if binLogger == nil {
    70  		return nil
    71  	}
    72  	return binLogger.GetMethodLogger(methodName)
    73  }
    74  
    75  func init() {
    76  	const envStr = "GRPC_BINARY_LOG_FILTER"
    77  	configStr := os.Getenv(envStr)
    78  	binLogger = NewLoggerFromConfigString(configStr)
    79  }
    80  
    81  // MethodLoggerConfig contains the setting for logging behavior of a method
    82  // logger. Currently, it contains the max length of header and message.
    83  type MethodLoggerConfig struct {
    84  	// Max length of header and message.
    85  	Header, Message uint64
    86  }
    87  
    88  // LoggerConfig contains the config for loggers to create method loggers.
    89  type LoggerConfig struct {
    90  	All      *MethodLoggerConfig
    91  	Services map[string]*MethodLoggerConfig
    92  	Methods  map[string]*MethodLoggerConfig
    93  
    94  	Blacklist map[string]struct{}
    95  }
    96  
    97  type logger struct {
    98  	config LoggerConfig
    99  }
   100  
   101  // NewLoggerFromConfig builds a logger with the given LoggerConfig.
   102  func NewLoggerFromConfig(config LoggerConfig) Logger {
   103  	return &logger{config: config}
   104  }
   105  
   106  // newEmptyLogger creates an empty logger. The map fields need to be filled in
   107  // using the set* functions.
   108  func newEmptyLogger() *logger {
   109  	return &logger{}
   110  }
   111  
   112  // Set method logger for "*".
   113  func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
   114  	if l.config.All != nil {
   115  		return fmt.Errorf("conflicting global rules found")
   116  	}
   117  	l.config.All = ml
   118  	return nil
   119  }
   120  
   121  // Set method logger for "service/*".
   122  //
   123  // New MethodLogger with same service overrides the old one.
   124  func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
   125  	if _, ok := l.config.Services[service]; ok {
   126  		return fmt.Errorf("conflicting service rules for service %v found", service)
   127  	}
   128  	if l.config.Services == nil {
   129  		l.config.Services = make(map[string]*MethodLoggerConfig)
   130  	}
   131  	l.config.Services[service] = ml
   132  	return nil
   133  }
   134  
   135  // Set method logger for "service/method".
   136  //
   137  // New MethodLogger with same method overrides the old one.
   138  func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
   139  	if _, ok := l.config.Blacklist[method]; ok {
   140  		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
   141  	}
   142  	if _, ok := l.config.Methods[method]; ok {
   143  		return fmt.Errorf("conflicting method rules for method %v found", method)
   144  	}
   145  	if l.config.Methods == nil {
   146  		l.config.Methods = make(map[string]*MethodLoggerConfig)
   147  	}
   148  	l.config.Methods[method] = ml
   149  	return nil
   150  }
   151  
   152  // Set blacklist method for "-service/method".
   153  func (l *logger) setBlacklist(method string) error {
   154  	if _, ok := l.config.Blacklist[method]; ok {
   155  		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
   156  	}
   157  	if _, ok := l.config.Methods[method]; ok {
   158  		return fmt.Errorf("conflicting method rules for method %v found", method)
   159  	}
   160  	if l.config.Blacklist == nil {
   161  		l.config.Blacklist = make(map[string]struct{})
   162  	}
   163  	l.config.Blacklist[method] = struct{}{}
   164  	return nil
   165  }
   166  
   167  // getMethodLogger returns the MethodLogger for the given methodName.
   168  //
   169  // methodName should be in the format of "/service/method".
   170  //
   171  // Each MethodLogger returned by this method is a new instance. This is to
   172  // generate sequence id within the call.
   173  func (l *logger) GetMethodLogger(methodName string) MethodLogger {
   174  	s, m, err := grpcutil.ParseMethod(methodName)
   175  	if err != nil {
   176  		grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
   177  		return nil
   178  	}
   179  	if ml, ok := l.config.Methods[s+"/"+m]; ok {
   180  		return NewTruncatingMethodLogger(ml.Header, ml.Message)
   181  	}
   182  	if _, ok := l.config.Blacklist[s+"/"+m]; ok {
   183  		return nil
   184  	}
   185  	if ml, ok := l.config.Services[s]; ok {
   186  		return NewTruncatingMethodLogger(ml.Header, ml.Message)
   187  	}
   188  	if l.config.All == nil {
   189  		return nil
   190  	}
   191  	return NewTruncatingMethodLogger(l.config.All.Header, l.config.All.Message)
   192  }
   193  

View as plain text