blob: 5de66e40d365bef8f7e25c2b300b4da285322a1f [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"
khenaidoo5fc5cea2021-08-11 17:39:16 -040025 "log"
26 "os"
27 "strconv"
khenaidoo5cb0d402021-12-08 14:09:16 -050028 "strings"
khenaidoo5fc5cea2021-08-11 17:39:16 -040029
30 "google.golang.org/grpc/internal/grpclog"
31)
32
33// LoggerV2 does underlying logging work for grpclog.
34type LoggerV2 interface {
35 // Info logs to INFO log. Arguments are handled in the manner of fmt.Print.
36 Info(args ...interface{})
37 // Infoln logs to INFO log. Arguments are handled in the manner of fmt.Println.
38 Infoln(args ...interface{})
39 // Infof logs to INFO log. Arguments are handled in the manner of fmt.Printf.
40 Infof(format string, args ...interface{})
41 // Warning logs to WARNING log. Arguments are handled in the manner of fmt.Print.
42 Warning(args ...interface{})
43 // Warningln logs to WARNING log. Arguments are handled in the manner of fmt.Println.
44 Warningln(args ...interface{})
45 // Warningf logs to WARNING log. Arguments are handled in the manner of fmt.Printf.
46 Warningf(format string, args ...interface{})
47 // Error logs to ERROR log. Arguments are handled in the manner of fmt.Print.
48 Error(args ...interface{})
49 // Errorln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
50 Errorln(args ...interface{})
51 // Errorf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
52 Errorf(format string, args ...interface{})
53 // Fatal logs to ERROR log. Arguments are handled in the manner of fmt.Print.
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 Fatal(args ...interface{})
57 // Fatalln logs to ERROR log. Arguments are handled in the manner of fmt.Println.
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 Fatalln(args ...interface{})
61 // Fatalf logs to ERROR log. Arguments are handled in the manner of fmt.Printf.
62 // gRPC ensures that all Fatal logs will exit with os.Exit(1).
63 // Implementations may also call os.Exit() with a non-zero exit code.
64 Fatalf(format string, args ...interface{})
65 // V reports whether verbosity level l is at least the requested verbose level.
66 V(l int) bool
67}
68
69// SetLoggerV2 sets logger that is used in grpc to a V2 logger.
70// Not mutex-protected, should be called before any gRPC functions.
71func SetLoggerV2(l LoggerV2) {
72 if _, ok := l.(*componentData); ok {
73 panic("cannot use component logger as grpclog logger")
74 }
75 grpclog.Logger = l
76 grpclog.DepthLogger, _ = l.(grpclog.DepthLoggerV2)
77}
78
79const (
80 // infoLog indicates Info severity.
81 infoLog int = iota
82 // warningLog indicates Warning severity.
83 warningLog
84 // errorLog indicates Error severity.
85 errorLog
86 // fatalLog indicates Fatal severity.
87 fatalLog
88)
89
90// severityName contains the string representation of each severity.
91var severityName = []string{
92 infoLog: "INFO",
93 warningLog: "WARNING",
94 errorLog: "ERROR",
95 fatalLog: "FATAL",
96}
97
98// loggerT is the default logger used by grpclog.
99type loggerT struct {
khenaidoo5cb0d402021-12-08 14:09:16 -0500100 m []*log.Logger
101 v int
102 jsonFormat bool
khenaidoo5fc5cea2021-08-11 17:39:16 -0400103}
104
105// NewLoggerV2 creates a loggerV2 with the provided writers.
106// Fatal logs will be written to errorW, warningW, infoW, followed by exit(1).
107// Error logs will be written to errorW, warningW and infoW.
108// Warning logs will be written to warningW and infoW.
109// Info logs will be written to infoW.
110func NewLoggerV2(infoW, warningW, errorW io.Writer) LoggerV2 {
khenaidoo5cb0d402021-12-08 14:09:16 -0500111 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{})
khenaidoo5fc5cea2021-08-11 17:39:16 -0400112}
113
114// NewLoggerV2WithVerbosity creates a loggerV2 with the provided writers and
115// verbosity level.
116func NewLoggerV2WithVerbosity(infoW, warningW, errorW io.Writer, v int) LoggerV2 {
khenaidoo5cb0d402021-12-08 14:09:16 -0500117 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{verbose: v})
118}
119
120type loggerV2Config struct {
121 verbose int
122 jsonFormat bool
123}
124
125func newLoggerV2WithConfig(infoW, warningW, errorW io.Writer, c loggerV2Config) LoggerV2 {
khenaidoo5fc5cea2021-08-11 17:39:16 -0400126 var m []*log.Logger
khenaidoo5cb0d402021-12-08 14:09:16 -0500127 flag := log.LstdFlags
128 if c.jsonFormat {
129 flag = 0
130 }
131 m = append(m, log.New(infoW, "", flag))
132 m = append(m, log.New(io.MultiWriter(infoW, warningW), "", flag))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400133 ew := io.MultiWriter(infoW, warningW, errorW) // ew will be used for error and fatal.
khenaidoo5cb0d402021-12-08 14:09:16 -0500134 m = append(m, log.New(ew, "", flag))
135 m = append(m, log.New(ew, "", flag))
136 return &loggerT{m: m, v: c.verbose, jsonFormat: c.jsonFormat}
khenaidoo5fc5cea2021-08-11 17:39:16 -0400137}
138
139// newLoggerV2 creates a loggerV2 to be used as default logger.
140// All logs are written to stderr.
141func newLoggerV2() LoggerV2 {
Akash Kankanala761955c2024-02-21 19:32:20 +0530142 errorW := io.Discard
143 warningW := io.Discard
144 infoW := io.Discard
khenaidoo5fc5cea2021-08-11 17:39:16 -0400145
146 logLevel := os.Getenv("GRPC_GO_LOG_SEVERITY_LEVEL")
147 switch logLevel {
148 case "", "ERROR", "error": // If env is unset, set level to ERROR.
149 errorW = os.Stderr
150 case "WARNING", "warning":
151 warningW = os.Stderr
152 case "INFO", "info":
153 infoW = os.Stderr
154 }
155
156 var v int
157 vLevel := os.Getenv("GRPC_GO_LOG_VERBOSITY_LEVEL")
158 if vl, err := strconv.Atoi(vLevel); err == nil {
159 v = vl
160 }
khenaidoo5cb0d402021-12-08 14:09:16 -0500161
162 jsonFormat := strings.EqualFold(os.Getenv("GRPC_GO_LOG_FORMATTER"), "json")
163
164 return newLoggerV2WithConfig(infoW, warningW, errorW, loggerV2Config{
165 verbose: v,
166 jsonFormat: jsonFormat,
167 })
168}
169
170func (g *loggerT) output(severity int, s string) {
171 sevStr := severityName[severity]
172 if !g.jsonFormat {
173 g.m[severity].Output(2, fmt.Sprintf("%v: %v", sevStr, s))
174 return
175 }
176 // TODO: we can also include the logging component, but that needs more
177 // (API) changes.
178 b, _ := json.Marshal(map[string]string{
179 "severity": sevStr,
180 "message": s,
181 })
182 g.m[severity].Output(2, string(b))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400183}
184
185func (g *loggerT) Info(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500186 g.output(infoLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400187}
188
189func (g *loggerT) Infoln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500190 g.output(infoLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400191}
192
193func (g *loggerT) Infof(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500194 g.output(infoLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400195}
196
197func (g *loggerT) Warning(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500198 g.output(warningLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400199}
200
201func (g *loggerT) Warningln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500202 g.output(warningLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400203}
204
205func (g *loggerT) Warningf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500206 g.output(warningLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400207}
208
209func (g *loggerT) Error(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500210 g.output(errorLog, fmt.Sprint(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400211}
212
213func (g *loggerT) Errorln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500214 g.output(errorLog, fmt.Sprintln(args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400215}
216
217func (g *loggerT) Errorf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500218 g.output(errorLog, fmt.Sprintf(format, args...))
khenaidoo5fc5cea2021-08-11 17:39:16 -0400219}
220
221func (g *loggerT) Fatal(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500222 g.output(fatalLog, fmt.Sprint(args...))
223 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400224}
225
226func (g *loggerT) Fatalln(args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500227 g.output(fatalLog, fmt.Sprintln(args...))
228 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400229}
230
231func (g *loggerT) Fatalf(format string, args ...interface{}) {
khenaidoo5cb0d402021-12-08 14:09:16 -0500232 g.output(fatalLog, fmt.Sprintf(format, args...))
233 os.Exit(1)
khenaidoo5fc5cea2021-08-11 17:39:16 -0400234}
235
236func (g *loggerT) V(l int) bool {
237 return l <= g.v
238}
239
240// DepthLoggerV2 logs at a specified call frame. If a LoggerV2 also implements
241// DepthLoggerV2, the below functions will be called with the appropriate stack
242// depth set for trivial functions the logger may ignore.
243//
Joey Armstrongba3d9d12024-01-15 14:22:11 -0500244// # Experimental
khenaidoo5fc5cea2021-08-11 17:39:16 -0400245//
246// Notice: This type is EXPERIMENTAL and may be changed or removed in a
247// later release.
248type DepthLoggerV2 interface {
249 LoggerV2
khenaidoo257f3192021-12-15 16:46:37 -0500250 // InfoDepth logs to INFO log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400251 InfoDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500252 // WarningDepth logs to WARNING log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400253 WarningDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500254 // ErrorDepth logs to ERROR log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400255 ErrorDepth(depth int, args ...interface{})
khenaidoo257f3192021-12-15 16:46:37 -0500256 // FatalDepth logs to FATAL log at the specified depth. Arguments are handled in the manner of fmt.Println.
khenaidoo5fc5cea2021-08-11 17:39:16 -0400257 FatalDepth(depth int, args ...interface{})
258}