3 * Copyright 2018 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 // Package binarylog implementation binary logging as defined in
20 // https://github.com/grpc/proposal/blob/master/A16-binary-logging.md.
27 "google.golang.org/grpc/grpclog"
30 // Logger is the global binary logger. It can be used to get binary logger for
32 type Logger interface {
33 getMethodLogger(methodName string) *MethodLogger
36 // binLogger is the global binary logger for the binary. One of this should be
37 // built at init time from the configuration (environment varialbe or flags).
39 // It is used to get a methodLogger for each individual method.
42 // SetLogger sets the binarg logger.
44 // Only call this at init time.
45 func SetLogger(l Logger) {
49 // GetMethodLogger returns the methodLogger for the given methodName.
51 // methodName should be in the format of "/service/method".
53 // Each methodLogger returned by this method is a new instance. This is to
54 // generate sequence id within the call.
55 func GetMethodLogger(methodName string) *MethodLogger {
59 return binLogger.getMethodLogger(methodName)
63 const envStr = "GRPC_BINARY_LOG_FILTER"
64 configStr := os.Getenv(envStr)
65 binLogger = NewLoggerFromConfigString(configStr)
68 type methodLoggerConfig struct {
69 // Max length of header and message.
74 all *methodLoggerConfig
75 services map[string]*methodLoggerConfig
76 methods map[string]*methodLoggerConfig
78 blacklist map[string]struct{}
81 // newEmptyLogger creates an empty logger. The map fields need to be filled in
82 // using the set* functions.
83 func newEmptyLogger() *logger {
87 // Set method logger for "*".
88 func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
90 return fmt.Errorf("conflicting global rules found")
96 // Set method logger for "service/*".
98 // New methodLogger with same service overrides the old one.
99 func (l *logger) setServiceMethodLogger(service string, ml *methodLoggerConfig) error {
100 if _, ok := l.services[service]; ok {
101 return fmt.Errorf("conflicting rules for service %v found", service)
103 if l.services == nil {
104 l.services = make(map[string]*methodLoggerConfig)
106 l.services[service] = ml
110 // Set method logger for "service/method".
112 // New methodLogger with same method overrides the old one.
113 func (l *logger) setMethodMethodLogger(method string, ml *methodLoggerConfig) error {
114 if _, ok := l.blacklist[method]; ok {
115 return fmt.Errorf("conflicting rules for method %v found", method)
117 if _, ok := l.methods[method]; ok {
118 return fmt.Errorf("conflicting rules for method %v found", method)
120 if l.methods == nil {
121 l.methods = make(map[string]*methodLoggerConfig)
123 l.methods[method] = ml
127 // Set blacklist method for "-service/method".
128 func (l *logger) setBlacklist(method string) error {
129 if _, ok := l.blacklist[method]; ok {
130 return fmt.Errorf("conflicting rules for method %v found", method)
132 if _, ok := l.methods[method]; ok {
133 return fmt.Errorf("conflicting rules for method %v found", method)
135 if l.blacklist == nil {
136 l.blacklist = make(map[string]struct{})
138 l.blacklist[method] = struct{}{}
142 // getMethodLogger returns the methodLogger for the given methodName.
144 // methodName should be in the format of "/service/method".
146 // Each methodLogger returned by this method is a new instance. This is to
147 // generate sequence id within the call.
148 func (l *logger) getMethodLogger(methodName string) *MethodLogger {
149 s, m, err := parseMethodName(methodName)
151 grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
154 if ml, ok := l.methods[s+"/"+m]; ok {
155 return newMethodLogger(ml.hdr, ml.msg)
157 if _, ok := l.blacklist[s+"/"+m]; ok {
160 if ml, ok := l.services[s]; ok {
161 return newMethodLogger(ml.hdr, ml.msg)
166 return newMethodLogger(l.all.hdr, l.all.msg)