forked from toolshed/abra
		
	
		
			
				
	
	
		
			193 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| /*
 | |
|  *
 | |
|  * Copyright 2018 gRPC 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
 | |
|  *
 | |
|  *     http://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 binarylog implementation binary logging as defined in
 | |
| // https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
 | |
| package binarylog
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 
 | |
| 	"google.golang.org/grpc/grpclog"
 | |
| 	"google.golang.org/grpc/internal/grpcutil"
 | |
| )
 | |
| 
 | |
| var grpclogLogger = grpclog.Component("binarylog")
 | |
| 
 | |
| // Logger specifies MethodLoggers for method names with a Log call that
 | |
| // takes a context.
 | |
| //
 | |
| // This is used in the 1.0 release of gcp/observability, and thus must not be
 | |
| // deleted or changed.
 | |
| type Logger interface {
 | |
| 	GetMethodLogger(methodName string) MethodLogger
 | |
| }
 | |
| 
 | |
| // binLogger is the global binary logger for the binary. One of this should be
 | |
| // built at init time from the configuration (environment variable or flags).
 | |
| //
 | |
| // It is used to get a MethodLogger for each individual method.
 | |
| var binLogger Logger
 | |
| 
 | |
| // SetLogger sets the binary logger.
 | |
| //
 | |
| // Only call this at init time.
 | |
| func SetLogger(l Logger) {
 | |
| 	binLogger = l
 | |
| }
 | |
| 
 | |
| // GetLogger gets the binary logger.
 | |
| //
 | |
| // Only call this at init time.
 | |
| func GetLogger() Logger {
 | |
| 	return binLogger
 | |
| }
 | |
| 
 | |
| // GetMethodLogger returns the MethodLogger for the given methodName.
 | |
| //
 | |
| // methodName should be in the format of "/service/method".
 | |
| //
 | |
| // Each MethodLogger returned by this method is a new instance. This is to
 | |
| // generate sequence id within the call.
 | |
| func GetMethodLogger(methodName string) MethodLogger {
 | |
| 	if binLogger == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return binLogger.GetMethodLogger(methodName)
 | |
| }
 | |
| 
 | |
| func init() {
 | |
| 	const envStr = "GRPC_BINARY_LOG_FILTER"
 | |
| 	configStr := os.Getenv(envStr)
 | |
| 	binLogger = NewLoggerFromConfigString(configStr)
 | |
| }
 | |
| 
 | |
| // MethodLoggerConfig contains the setting for logging behavior of a method
 | |
| // logger. Currently, it contains the max length of header and message.
 | |
| type MethodLoggerConfig struct {
 | |
| 	// Max length of header and message.
 | |
| 	Header, Message uint64
 | |
| }
 | |
| 
 | |
| // LoggerConfig contains the config for loggers to create method loggers.
 | |
| type LoggerConfig struct {
 | |
| 	All      *MethodLoggerConfig
 | |
| 	Services map[string]*MethodLoggerConfig
 | |
| 	Methods  map[string]*MethodLoggerConfig
 | |
| 
 | |
| 	Blacklist map[string]struct{}
 | |
| }
 | |
| 
 | |
| type logger struct {
 | |
| 	config LoggerConfig
 | |
| }
 | |
| 
 | |
| // NewLoggerFromConfig builds a logger with the given LoggerConfig.
 | |
| func NewLoggerFromConfig(config LoggerConfig) Logger {
 | |
| 	return &logger{config: config}
 | |
| }
 | |
| 
 | |
| // newEmptyLogger creates an empty logger. The map fields need to be filled in
 | |
| // using the set* functions.
 | |
| func newEmptyLogger() *logger {
 | |
| 	return &logger{}
 | |
| }
 | |
| 
 | |
| // Set method logger for "*".
 | |
| func (l *logger) setDefaultMethodLogger(ml *MethodLoggerConfig) error {
 | |
| 	if l.config.All != nil {
 | |
| 		return fmt.Errorf("conflicting global rules found")
 | |
| 	}
 | |
| 	l.config.All = ml
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Set method logger for "service/*".
 | |
| //
 | |
| // New MethodLogger with same service overrides the old one.
 | |
| func (l *logger) setServiceMethodLogger(service string, ml *MethodLoggerConfig) error {
 | |
| 	if _, ok := l.config.Services[service]; ok {
 | |
| 		return fmt.Errorf("conflicting service rules for service %v found", service)
 | |
| 	}
 | |
| 	if l.config.Services == nil {
 | |
| 		l.config.Services = make(map[string]*MethodLoggerConfig)
 | |
| 	}
 | |
| 	l.config.Services[service] = ml
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Set method logger for "service/method".
 | |
| //
 | |
| // New MethodLogger with same method overrides the old one.
 | |
| func (l *logger) setMethodMethodLogger(method string, ml *MethodLoggerConfig) error {
 | |
| 	if _, ok := l.config.Blacklist[method]; ok {
 | |
| 		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
 | |
| 	}
 | |
| 	if _, ok := l.config.Methods[method]; ok {
 | |
| 		return fmt.Errorf("conflicting method rules for method %v found", method)
 | |
| 	}
 | |
| 	if l.config.Methods == nil {
 | |
| 		l.config.Methods = make(map[string]*MethodLoggerConfig)
 | |
| 	}
 | |
| 	l.config.Methods[method] = ml
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // Set blacklist method for "-service/method".
 | |
| func (l *logger) setBlacklist(method string) error {
 | |
| 	if _, ok := l.config.Blacklist[method]; ok {
 | |
| 		return fmt.Errorf("conflicting blacklist rules for method %v found", method)
 | |
| 	}
 | |
| 	if _, ok := l.config.Methods[method]; ok {
 | |
| 		return fmt.Errorf("conflicting method rules for method %v found", method)
 | |
| 	}
 | |
| 	if l.config.Blacklist == nil {
 | |
| 		l.config.Blacklist = make(map[string]struct{})
 | |
| 	}
 | |
| 	l.config.Blacklist[method] = struct{}{}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| // getMethodLogger returns the MethodLogger for the given methodName.
 | |
| //
 | |
| // methodName should be in the format of "/service/method".
 | |
| //
 | |
| // Each MethodLogger returned by this method is a new instance. This is to
 | |
| // generate sequence id within the call.
 | |
| func (l *logger) GetMethodLogger(methodName string) MethodLogger {
 | |
| 	s, m, err := grpcutil.ParseMethod(methodName)
 | |
| 	if err != nil {
 | |
| 		grpclogLogger.Infof("binarylogging: failed to parse %q: %v", methodName, err)
 | |
| 		return nil
 | |
| 	}
 | |
| 	if ml, ok := l.config.Methods[s+"/"+m]; ok {
 | |
| 		return NewTruncatingMethodLogger(ml.Header, ml.Message)
 | |
| 	}
 | |
| 	if _, ok := l.config.Blacklist[s+"/"+m]; ok {
 | |
| 		return nil
 | |
| 	}
 | |
| 	if ml, ok := l.config.Services[s]; ok {
 | |
| 		return NewTruncatingMethodLogger(ml.Header, ml.Message)
 | |
| 	}
 | |
| 	if l.config.All == nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 	return NewTruncatingMethodLogger(l.config.All.Header, l.config.All.Message)
 | |
| }
 |