/*
 *
 * 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 ( ) // Logger is the global binary logger. It can be used to get binary logger for // each method. 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 var grpclogLogger = grpclog.Component("binarylog") // SetLogger sets the binary logger. // // Only call this at init time. func ( Logger) { binLogger = } // GetLogger gets the binary logger. // // Only call this at init time. func () 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 ( string) MethodLogger { if binLogger == nil { return nil } return binLogger.GetMethodLogger() } func () { const = "GRPC_BINARY_LOG_FILTER" := os.Getenv() binLogger = NewLoggerFromConfigString() } // 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 ( LoggerConfig) Logger { return &logger{config: } } // newEmptyLogger creates an empty logger. The map fields need to be filled in // using the set* functions. func () *logger { return &logger{} } // Set method logger for "*". func ( *logger) ( *MethodLoggerConfig) error { if .config.All != nil { return fmt.Errorf("conflicting global rules found") } .config.All = return nil } // Set method logger for "service/*". // // New MethodLogger with same service overrides the old one. func ( *logger) ( string, *MethodLoggerConfig) error { if , := .config.Services[]; { return fmt.Errorf("conflicting service rules for service %v found", ) } if .config.Services == nil { .config.Services = make(map[string]*MethodLoggerConfig) } .config.Services[] = return nil } // Set method logger for "service/method". // // New MethodLogger with same method overrides the old one. func ( *logger) ( string, *MethodLoggerConfig) error { if , := .config.Blacklist[]; { return fmt.Errorf("conflicting blacklist rules for method %v found", ) } if , := .config.Methods[]; { return fmt.Errorf("conflicting method rules for method %v found", ) } if .config.Methods == nil { .config.Methods = make(map[string]*MethodLoggerConfig) } .config.Methods[] = return nil } // Set blacklist method for "-service/method". func ( *logger) ( string) error { if , := .config.Blacklist[]; { return fmt.Errorf("conflicting blacklist rules for method %v found", ) } if , := .config.Methods[]; { return fmt.Errorf("conflicting method rules for method %v found", ) } if .config.Blacklist == nil { .config.Blacklist = make(map[string]struct{}) } .config.Blacklist[] = 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 ( *logger) ( string) MethodLogger { , , := grpcutil.ParseMethod() if != nil { grpclogLogger.Infof("binarylogging: failed to parse %q: %v", , ) return nil } if , := .config.Methods[+"/"+]; { return NewTruncatingMethodLogger(.Header, .Message) } if , := .config.Blacklist[+"/"+]; { return nil } if , := .config.Services[]; { return NewTruncatingMethodLogger(.Header, .Message) } if .config.All == nil { return nil } return NewTruncatingMethodLogger(.config.All.Header, .config.All.Message) }