Code refactoring for bpa operator
[icn.git] / cmd / bpa-operator / vendor / google.golang.org / grpc / internal / binarylog / binarylog.go
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 )
29
30 // Logger is the global binary logger. It can be used to get binary logger for
31 // each method.
32 type Logger interface {
33         getMethodLogger(methodName string) *MethodLogger
34 }
35
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).
38 //
39 // It is used to get a methodLogger for each individual method.
40 var binLogger Logger
41
42 // SetLogger sets the binarg logger.
43 //
44 // Only call this at init time.
45 func SetLogger(l Logger) {
46         binLogger = l
47 }
48
49 // GetMethodLogger returns the methodLogger for the given methodName.
50 //
51 // methodName should be in the format of "/service/method".
52 //
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 {
56         if binLogger == nil {
57                 return nil
58         }
59         return binLogger.getMethodLogger(methodName)
60 }
61
62 func init() {
63         const envStr = "GRPC_BINARY_LOG_FILTER"
64         configStr := os.Getenv(envStr)
65         binLogger = NewLoggerFromConfigString(configStr)
66 }
67
68 type methodLoggerConfig struct {
69         // Max length of header and message.
70         hdr, msg uint64
71 }
72
73 type logger struct {
74         all      *methodLoggerConfig
75         services map[string]*methodLoggerConfig
76         methods  map[string]*methodLoggerConfig
77
78         blacklist map[string]struct{}
79 }
80
81 // newEmptyLogger creates an empty logger. The map fields need to be filled in
82 // using the set* functions.
83 func newEmptyLogger() *logger {
84         return &logger{}
85 }
86
87 // Set method logger for "*".
88 func (l *logger) setDefaultMethodLogger(ml *methodLoggerConfig) error {
89         if l.all != nil {
90                 return fmt.Errorf("conflicting global rules found")
91         }
92         l.all = ml
93         return nil
94 }
95
96 // Set method logger for "service/*".
97 //
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)
102         }
103         if l.services == nil {
104                 l.services = make(map[string]*methodLoggerConfig)
105         }
106         l.services[service] = ml
107         return nil
108 }
109
110 // Set method logger for "service/method".
111 //
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)
116         }
117         if _, ok := l.methods[method]; ok {
118                 return fmt.Errorf("conflicting rules for method %v found", method)
119         }
120         if l.methods == nil {
121                 l.methods = make(map[string]*methodLoggerConfig)
122         }
123         l.methods[method] = ml
124         return nil
125 }
126
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)
131         }
132         if _, ok := l.methods[method]; ok {
133                 return fmt.Errorf("conflicting rules for method %v found", method)
134         }
135         if l.blacklist == nil {
136                 l.blacklist = make(map[string]struct{})
137         }
138         l.blacklist[method] = struct{}{}
139         return nil
140 }
141
142 // getMethodLogger returns the methodLogger for the given methodName.
143 //
144 // methodName should be in the format of "/service/method".
145 //
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)
150         if err != nil {
151                 grpclog.Infof("binarylogging: failed to parse %q: %v", methodName, err)
152                 return nil
153         }
154         if ml, ok := l.methods[s+"/"+m]; ok {
155                 return newMethodLogger(ml.hdr, ml.msg)
156         }
157         if _, ok := l.blacklist[s+"/"+m]; ok {
158                 return nil
159         }
160         if ml, ok := l.services[s]; ok {
161                 return newMethodLogger(ml.hdr, ml.msg)
162         }
163         if l.all == nil {
164                 return nil
165         }
166         return newMethodLogger(l.all.hdr, l.all.msg)
167 }