1/* 2 * 3 * Copyright 2017 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 19package grpclog 20 21import ( 22 "io" 23 "io/ioutil" 24 "log" 25 "os" 26 "strconv" 27) 28 29// LoggerV2 does underlying logging work for grpclog. 30type LoggerV2 interface { 31 // Info logs to INFO log. Arguments are handled in the manner of fmt.Print. 32 Info(args ...interface{}) 33 // Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println. 34 Infoln(args ...interface{}) 35 // Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf. 36 Infof(format string, args ...interface{}) 37 // Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print. 38 Warning(args ...interface{}) 39 // Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println. 40 Warningln(args ...interface{}) 41 // Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf. 42 Warningf(format string, args ...interface{}) 43 // Error logs to ERROR log. Arguments are handled in the manner of fmt.Print. 44 Error(args ...interface{}) 45 // Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println. 46 Errorln(args ...interface{}) 47 // Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf. 48 Errorf(format string, args ...interface{}) 49 // Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print. 50 // gRPC ensures that all Fatal logs will exit with os.Exit(1). 51 // Implementations may also call os.Exit() with a non-zero exit code. 52 Fatal(args ...interface{}) 53 // Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println. 54 // gRPC ensures that all Fatal logs will exit with os.Exit(1). 55 // Implementations may also call os.Exit() with a non-zero exit code. 56 Fatalln(args ...interface{}) 57 // Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf. 58 // gRPC ensures that all Fatal logs will exit with os.Exit(1). 59 // Implementations may also call os.Exit() with a non-zero exit code. 60 Fatalf(format string, args ...interface{}) 61 // V reports whether verbosity level l is at least the requested verbose level. 62 V(l int) bool 63} 64 65// SetLoggerV2 sets logger that is used in grpc to a V2 logger. 66// Not mutex-protected, should be called before any gRPC functions. 67func SetLoggerV2(l LoggerV2) { 68 logger = l 69} 70 71const ( 72 // infoLog indicates Info severity. 73 infoLog int = iota 74 // warningLog indicates Warning severity. 75 warningLog 76 // errorLog indicates Error severity. 77 errorLog 78 // fatalLog indicates Fatal severity. 79 fatalLog 80) 81 82// severityName contains the string representation of each severity. 83var severityName = []string{ 84 infoLog: "INFO", 85 warningLog: "WARNING", 86 errorLog: "ERROR", 87 fatalLog: "FATAL", 88} 89 90// loggerT is the default logger used by grpclog. 91type loggerT struct { 92 m []*log.Logger 93 v int 94} 95 96// NewLoggerV2 creates a loggerV2 with the provided writers. 97// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1). 98// Error logs will be written to errorW, warningW and infoW. 99// Warning logs will be written to warningW and infoW. 100// Info logs will be written to infoW. 101func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 { 102 return NewLoggerV2WithVerbosity(infoW, warningW, errorW, 0) 103} 104 105// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and 106// verbosity level. 107func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 { 108 var m []*log.Logger 109 m = append(m, log.New(infoW, severityName[infoLog]+": ", log.LstdFlags)) 110 m = append(m, log.New(io.MultiWriter(infoW, warningW), severityName[warningLog]+": ", log.LstdFlags)) 111 ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal. 112 m = append(m, log.New(ew, severityName[errorLog]+": ", log.LstdFlags)) 113 m = append(m, log.New(ew, severityName[fatalLog]+": ", log.LstdFlags)) 114 return &loggerT{m: m, v: v} 115} 116 117// newLoggerV2 creates a loggerV2 to be used as default logger. 118// All logs are written to stderr. 119func newLoggerV2() LoggerV2 { 120 errorW := ioutil.Discard 121 warningW := ioutil.Discard 122 infoW := ioutil.Discard 123 124 logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL") 125 switch logLevel { 126 case "", "ERROR", "error": // If env is unset, set level to ERROR. 127 errorW = os.Stderr 128 case "WARNING", "warning": 129 warningW = os.Stderr 130 case "INFO", "info": 131 infoW = os.Stderr 132 } 133 134 var v int 135 vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL") 136 if vl, err := strconv.Atoi(vLevel); err == nil { 137 v = vl 138 } 139 return NewLoggerV2WithVerbosity(infoW, warningW, errorW, v) 140} 141 142func (g *loggerT) Info(args ...interface{}) { 143 g.m[infoLog].Print(args...) 144} 145 146func (g *loggerT) Infoln(args ...interface{}) { 147 g.m[infoLog].Println(args...) 148} 149 150func (g *loggerT) Infof(format string, args ...interface{}) { 151 g.m[infoLog].Printf(format, args...) 152} 153 154func (g *loggerT) Warning(args ...interface{}) { 155 g.m[warningLog].Print(args...) 156} 157 158func (g *loggerT) Warningln(args ...interface{}) { 159 g.m[warningLog].Println(args...) 160} 161 162func (g *loggerT) Warningf(format string, args ...interface{}) { 163 g.m[warningLog].Printf(format, args...) 164} 165 166func (g *loggerT) Error(args ...interface{}) { 167 g.m[errorLog].Print(args...) 168} 169 170func (g *loggerT) Errorln(args ...interface{}) { 171 g.m[errorLog].Println(args...) 172} 173 174func (g *loggerT) Errorf(format string, args ...interface{}) { 175 g.m[errorLog].Printf(format, args...) 176} 177 178func (g *loggerT) Fatal(args ...interface{}) { 179 g.m[fatalLog].Fatal(args...) 180 // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). 181} 182 183func (g *loggerT) Fatalln(args ...interface{}) { 184 g.m[fatalLog].Fatalln(args...) 185 // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). 186} 187 188func (g *loggerT) Fatalf(format string, args ...interface{}) { 189 g.m[fatalLog].Fatalf(format, args...) 190 // No need to call os.Exit() again because log.Logger.Fatal() calls os.Exit(). 191} 192 193func (g *loggerT) V(l int) bool { 194 return l <= g.v 195} 196