1
18
19 package binarylog
20
21 import (
22 "errors"
23 "fmt"
24 "regexp"
25 "strconv"
26 "strings"
27 )
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 func NewLoggerFromConfigString(s string) Logger {
46 if s == "" {
47 return nil
48 }
49 l := newEmptyLogger()
50 methods := strings.Split(s, ",")
51 for _, method := range methods {
52 if err := l.fillMethodLoggerWithConfigString(method); err != nil {
53 grpclogLogger.Warningf("failed to parse binary log config: %v", err)
54 return nil
55 }
56 }
57 return l
58 }
59
60
61
62 func (l *logger) fillMethodLoggerWithConfigString(config string) error {
63
64 if config == "" {
65 return errors.New("empty string is not a valid method binary logging config")
66 }
67
68
69 if config[0] == '-' {
70 s, m, suffix, err := parseMethodConfigAndSuffix(config[1:])
71 if err != nil {
72 return fmt.Errorf("invalid config: %q, %v", config, err)
73 }
74 if m == "*" {
75 return fmt.Errorf("invalid config: %q, %v", config, "* not allowed in blacklist config")
76 }
77 if suffix != "" {
78 return fmt.Errorf("invalid config: %q, %v", config, "header/message limit not allowed in blacklist config")
79 }
80 if err := l.setBlacklist(s + "/" + m); err != nil {
81 return fmt.Errorf("invalid config: %v", err)
82 }
83 return nil
84 }
85
86
87 if config[0] == '*' {
88 hdr, msg, err := parseHeaderMessageLengthConfig(config[1:])
89 if err != nil {
90 return fmt.Errorf("invalid config: %q, %v", config, err)
91 }
92 if err := l.setDefaultMethodLogger(&MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
93 return fmt.Errorf("invalid config: %v", err)
94 }
95 return nil
96 }
97
98 s, m, suffix, err := parseMethodConfigAndSuffix(config)
99 if err != nil {
100 return fmt.Errorf("invalid config: %q, %v", config, err)
101 }
102 hdr, msg, err := parseHeaderMessageLengthConfig(suffix)
103 if err != nil {
104 return fmt.Errorf("invalid header/message length config: %q, %v", suffix, err)
105 }
106 if m == "*" {
107 if err := l.setServiceMethodLogger(s, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
108 return fmt.Errorf("invalid config: %v", err)
109 }
110 } else {
111 if err := l.setMethodMethodLogger(s+"/"+m, &MethodLoggerConfig{Header: hdr, Message: msg}); err != nil {
112 return fmt.Errorf("invalid config: %v", err)
113 }
114 }
115 return nil
116 }
117
118 const (
119
120
121 maxUInt = ^uint64(0)
122
123
124
125 longMethodConfigRegexpStr = `^([\w./]+)/((?:\w+)|[*])(.+)?$`
126
127
128 optionalLengthRegexpStr = `(?::(\d+))?`
129 headerConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `}$`
130 messageConfigRegexpStr = `^{m` + optionalLengthRegexpStr + `}$`
131 headerMessageConfigRegexpStr = `^{h` + optionalLengthRegexpStr + `;m` + optionalLengthRegexpStr + `}$`
132 )
133
134 var (
135 longMethodConfigRegexp = regexp.MustCompile(longMethodConfigRegexpStr)
136 headerConfigRegexp = regexp.MustCompile(headerConfigRegexpStr)
137 messageConfigRegexp = regexp.MustCompile(messageConfigRegexpStr)
138 headerMessageConfigRegexp = regexp.MustCompile(headerMessageConfigRegexpStr)
139 )
140
141
142 func parseMethodConfigAndSuffix(c string) (service, method, suffix string, _ error) {
143
144
145
146
147 match := longMethodConfigRegexp.FindStringSubmatch(c)
148 if match == nil {
149 return "", "", "", fmt.Errorf("%q contains invalid substring", c)
150 }
151 service = match[1]
152 method = match[2]
153 suffix = match[3]
154 return
155 }
156
157
158
159
160 func parseHeaderMessageLengthConfig(c string) (hdrLenStr, msgLenStr uint64, err error) {
161 if c == "" {
162 return maxUInt, maxUInt, nil
163 }
164
165 if match := headerConfigRegexp.FindStringSubmatch(c); match != nil {
166 if s := match[1]; s != "" {
167 hdrLenStr, err = strconv.ParseUint(s, 10, 64)
168 if err != nil {
169 return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
170 }
171 return hdrLenStr, 0, nil
172 }
173 return maxUInt, 0, nil
174 }
175
176
177 if match := messageConfigRegexp.FindStringSubmatch(c); match != nil {
178 if s := match[1]; s != "" {
179 msgLenStr, err = strconv.ParseUint(s, 10, 64)
180 if err != nil {
181 return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
182 }
183 return 0, msgLenStr, nil
184 }
185 return 0, maxUInt, nil
186 }
187
188
189 if match := headerMessageConfigRegexp.FindStringSubmatch(c); match != nil {
190
191 hdrLenStr = maxUInt
192 msgLenStr = maxUInt
193 if s := match[1]; s != "" {
194 hdrLenStr, err = strconv.ParseUint(s, 10, 64)
195 if err != nil {
196 return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
197 }
198 }
199 if s := match[2]; s != "" {
200 msgLenStr, err = strconv.ParseUint(s, 10, 64)
201 if err != nil {
202 return 0, 0, fmt.Errorf("failed to convert %q to uint", s)
203 }
204 }
205 return hdrLenStr, msgLenStr, nil
206 }
207 return 0, 0, fmt.Errorf("%q contains invalid substring", c)
208 }
209
View as plain text