blob: b5560b47ec4ba7fc6592e49be10eb4449a1ee8af [file] [log] [blame]
khenaidoo5fc5cea2021-08-11 17:39:16 -04001/*
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 (
khenaidoo5cb0d402021-12-08 14:09:16 -050022 "encoding/json"
23 "fmt"
khenaidoo5fc5cea2021-08-11 17:39:16 -040024 "io"
25 "io/ioutil"
26 "log"
27 "os"
28 "strconv"
khenaidoo5cb0d402021-12-08 14:09:16 -050029 "strings"
khenaidoo5fc5cea2021-08-11 17:39:16 -040030
31 "google.golang.org/grpc/internal/grpclog"
32)
33
34// LoggerV2 does underlying logging work for grpclog.
35type LoggerV2 interface {
36 // Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
37 Info(args ...interface{})
38 // Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
39 Infoln(args ...interface{})
40 // Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
41 Infof(format string, args ...interface{})
42 // Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
43 Warning(args ...interface{})
44 // Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
45 Warningln(args ...interface{})
46 // Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
47 Warningf(format string, args ...interface{})
48 // Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
49 Error(args ...interface{})
50 // Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
51 Errorln(args ...interface{})
52 // Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
53 Errorf(format string, args ...interface{})
54 // Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
55 // gRPC ensures that all Fatal logs will exit with os.Exit(1).
56 // Implementations may also call os.Exit() with a non-zero exit code.
57 Fatal(args ...interface{})
58 // Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
59 // gRPC ensures that all Fatal logs will exit with os.Exit(1).
60 // Implementations may also call os.Exit() with a non-zero exit code.
61 Fatalln(args ...interface{})
62 // Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
63 // gRPC ensures that all Fatal logs will exit with os.Exit(1).
64 // Implementations may also call os.Exit() with a non-zero exit code.
65 Fatalf(format string, args ...interface{})
66 // V reports whether verbosity level l is at least the requested verbose level.
67 V(l int) bool
68}
69
70// SetLoggerV2 sets logger that is used in grpc to a V2 logger.
71// Not mutex-protected, should be called before any gRPC functions.
72func SetLoggerV2(l LoggerV2) {
73 if _, ok := l.(*componentData); ok {
74 panic("cannot use component logger as grpclog logger")
75 }
76 grpclog.Logger = l
77 grpclog.DepthLogger, _ = l.(grpclog.DepthLoggerV2)
78}
79
80const (
81 // infoLog indicates Info severity.
82 infoLog int = iota
83 // warningLog indicates Warning severity.
84 warningLog
85 // errorLog indicates Error severity.
86 errorLog
87 // fatalLog indicates Fatal severity.
88 fatalLog
89)
90
91// severityName contains the string representation of each severity.
92var severityName = []string{
93 infoLog: "INFO",
94 warningLog: "WARNING",
95 errorLog: "ERROR",
96 fatalLog: "FATAL",
97}
98
99// loggerT is the default logger used by grpclog.
100type loggerT struct {
khenaidoo5cb0d402021-12-08 14:09:16 -0500101 m []*log.Logger
102 v int
103 jsonFormat bool
khenaidoo5fc5cea2021-08-11 17:39:16 -0400104}
105
106// NewLoggerV2 creates a loggerV2 with the provided writers.
107// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1).
108// Error logs will be written to errorW, warningW and infoW.
109// Warning logs will be written to warningW and infoW.
110// Info logs will be written to infoW.
111func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
khenaidoo5cb0d402021-12-08 14:09:16 -0500112 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{})
khenaidoo5fc5cea2021-08-11 17:39:16 -0400113}
114
115// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
116// verbosity level.
117func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
khenaidoo5cb0d402021-12-08 14:09:16 -0500118 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v})
119}
120
121type loggerV2Config struct {
122 verbose int
123 jsonFormat bool
124}
125
126func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 {
khenaidoo5fc5cea2021-08-11 17:39:16 -0400127 var m []*log.Logger
khenaidoo5cb0d402021-12-08 14:09:16 -0500128 flag := log.LstdFlags
129 if c.jsonFormat {
130 flag = 0
131 }
132 m = append(m, log.New(infoW, "", flag))
133 m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400134 ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
khenaidoo5cb0d402021-12-08 14:09:16 -0500135 m = append(m, log.New(ew, "", flag))
136 m = append(m, log.New(ew, "", flag))
137 return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat}
khenaidoo5fc5cea2021-08-11 17:39:16 -0400138}
139
140// newLoggerV2 creates a loggerV2 to be used as default logger.
141// All logs are written to stderr.
142func newLoggerV2() LoggerV2 {
143 errorW := ioutil.Discard
144 warningW := ioutil.Discard
145 infoW := ioutil.Discard
146
147 logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
148 switch logLevel {
149 case "", "ERROR", "error": // If env is unset, set level to ERROR.
150 errorW = os.Stderr
151 case "WARNING", "warning":
152 warningW = os.Stderr
153 case "INFO", "info":
154 infoW = os.Stderr
155 }
156
157 var v int
158 vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
159 if vl, err := strconv.Atoi(vLevel); err == nil {
160 v = vl
161 }
khenaidoo5cb0d402021-12-08 14:09:16 -0500162
163 jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json")
164
165 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{
166 verbose: v,
167 jsonFormat: jsonFormat,
168 })
169}
170
171func (g *loggerT) output(severity int, s string) {
172 sevStr := severityName[severity]
173 if !g.jsonFormat {
174 g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s))
175 return
176 }
177 // TODO: we can also include the logging component, but that needs more
178 // (API) changes.
179 b, _ := json.Marshal(map[string]string{
180 "severity": sevStr,
181 "message": s,
182 })
183 g.m[severity].Output(2, string(b))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400184}
185
186func (g *loggerT) Info(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500187 g.output(infoLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400188}
189
190func (g *loggerT) Infoln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500191 g.output(infoLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400192}
193
194func (g *loggerT) Infof(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500195 g.output(infoLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400196}
197
198func (g *loggerT) Warning(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500199 g.output(warningLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400200}
201
202func (g *loggerT) Warningln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500203 g.output(warningLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400204}
205
206func (g *loggerT) Warningf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500207 g.output(warningLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400208}
209
210func (g *loggerT) Error(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500211 g.output(errorLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400212}
213
214func (g *loggerT) Errorln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500215 g.output(errorLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400216}
217
218func (g *loggerT) Errorf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500219 g.output(errorLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400220}
221
222func (g *loggerT) Fatal(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500223 g.output(fatalLog, fmt.Sprint(args...))
224 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400225}
226
227func (g *loggerT) Fatalln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500228 g.output(fatalLog, fmt.Sprintln(args...))
229 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400230}
231
232func (g *loggerT) Fatalf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500233 g.output(fatalLog, fmt.Sprintf(format, args...))
234 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400235}
236
237func (g *loggerT) V(l int) bool {
238 return l <= g.v
239}
240
241// DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements
242// DepthLoggerV2, the below functions will be called with the appropriate stack
243// depth set for trivial functions the logger may ignore.
244//
Joey Armstrongba3d9d12024-01-15 14:22:11 -0500245// # Experimental
khenaidoo5fc5cea2021-08-11 17:39:16 -0400246//
247// Notice: This type is EXPERIMENTAL and may be changed or removed in a
248// later release.
249type DepthLoggerV2 interface {
250 LoggerV2
khenaidoo257f3192021-12-15 16:46:37 -0500251 // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400252 InfoDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500253 // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400254 WarningDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500255 // ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400256 ErrorDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500257 // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400258 FatalDepth(depth int, args ...interface{})
259}