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 }