gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

binarylog.go (5579B)


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