github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/grpc/internal/binarylog/binarylog.go (about)

     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  	"github.com/hxx258456/ccgo/grpc/grpclog"
    28  	"github.com/hxx258456/ccgo/grpc/internal/grpcutil"
    29  )
    30  
    31  // Logger is the global binary logger. It can be used to get binary logger for
    32  // each method.
    33  type Logger interface {
    34  	getMethodLogger(methodName string) *MethodLogger
    35  }
    36  
    37  // binLogger is the global binary logger for the binary. One of this should be
    38  // built at init time from the configuration (environment variable or flags).
    39  //
    40  // It is used to get a methodLogger for each individual method.
    41  var binLogger Logger
    42  
    43  var grpclogLogger = grpclog.Component("binarylog")
    44  
    45  // SetLogger sets the binarg logger.
    46  //
    47  // Only call this at init time.
    48  func SetLogger(l Logger) {
    49  	binLogger = l
    50  }
    51  
    52  // GetMethodLogger returns the methodLogger for the given methodName.
    53  //
    54  // methodName should be in the format of "/service/method".
    55  //
    56  // Each methodLogger returned by this method is a new instance. This is to
    57  // generate sequence id within the call.
    58  func GetMethodLogger(methodName string) *MethodLogger {
    59  	if binLogger == nil {
    60  		return nil
    61  	}
    62  	return binLogger.getMethodLogger(methodName)
    63  }
    64  
    65  func init() {
    66  	const envStr = "GRPC_BINARY_LOG_FILTER"
    67  	configStr := os.Getenv(envStr)
    68  	binLogger = NewLoggerFromConfigString(configStr)
    69  }
    70  
    71  type methodLoggerConfig struct {
    72  	// Max length of header and message.
    73  	hdr, msg uint64
    74  }
    75  
    76  type logger struct {
    77  	all      *methodLoggerConfig
    78  	services map[string]*methodLoggerConfig
    79  	methods  map[string]*methodLoggerConfig
    80  
    81  	blacklist map[string]struct{}
    82  }
    83  
    84  // newEmptyLogger creates an empty logger. The map fields need to be filled in
    85  // using the set* functions.
    86  func newEmptyLogger() *logger {
    87  	return &logger{}
    88  }
    89  
    90  // Set method logger for "*".
    91  func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
    92  	if l.all != nil {
    93  		return fmt.Errorf("conflicting global rules found")
    94  	}
    95  	l.all = ml
    96  	return nil
    97  }
    98  
    99  // Set method logger for "service/*".
   100  //
   101  // New methodLogger with same service overrides the old one.
   102  func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
   103  	if _, ok := l.services[service]; ok {
   104  		return fmt.Errorf("conflicting service rules for service %v found", service)
   105  	}
   106  	if l.services == nil {
   107  		l.services = make(map[string]*methodLoggerConfig)
   108  	}
   109  	l.services[service] = ml
   110  	return nil
   111  }
   112  
   113  // Set method logger for "service/method".
   114  //
   115  // New methodLogger with same method overrides the old one.
   116  func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
   117  	if _, ok := l.blacklist[method]; ok {
   118  		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
   119  	}
   120  	if _, ok := l.methods[method]; ok {
   121  		return fmt.Errorf("conflicting method rules for method %v found", method)
   122  	}
   123  	if l.methods == nil {
   124  		l.methods = make(map[string]*methodLoggerConfig)
   125  	}
   126  	l.methods[method] = ml
   127  	return nil
   128  }
   129  
   130  // Set blacklist method for "-service/method".
   131  func (l *logger) setBlacklist(method string) error {
   132  	if _, ok := l.blacklist[method]; ok {
   133  		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
   134  	}
   135  	if _, ok := l.methods[method]; ok {
   136  		return fmt.Errorf("conflicting method rules for method %v found", method)
   137  	}
   138  	if l.blacklist == nil {
   139  		l.blacklist = make(map[string]struct{})
   140  	}
   141  	l.blacklist[method] = struct{}{}
   142  	return nil
   143  }
   144  
   145  // getMethodLogger returns the methodLogger for the given methodName.
   146  //
   147  // methodName should be in the format of "/service/method".
   148  //
   149  // Each methodLogger returned by this method is a new instance. This is to
   150  // generate sequence id within the call.
   151  func (l *logger) getMethodLogger(methodName string) *MethodLogger {
   152  	s, m, err := grpcutil.ParseMethod(methodName)
   153  	if err != nil {
   154  		grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
   155  		return nil
   156  	}
   157  	if ml, ok := l.methods[s+"/"+m]; ok {
   158  		return newMethodLogger(ml.hdr, ml.msg)
   159  	}
   160  	if _, ok := l.blacklist[s+"/"+m]; ok {
   161  		return nil
   162  	}
   163  	if ml, ok := l.services[s]; ok {
   164  		return newMethodLogger(ml.hdr, ml.msg)
   165  	}
   166  	if l.all == nil {
   167  		return nil
   168  	}
   169  	return newMethodLogger(l.all.hdr, l.all.msg)
   170  }