Skip to content

Commit

Permalink
Add Severity and VerboseLevel to grpclog.
Browse files Browse the repository at this point in the history
  • Loading branch information
menghanl committed Oct 7, 2016
1 parent 0bfe362 commit 3c39586
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 49 deletions.
33 changes: 13 additions & 20 deletions grpclog/glogger/glogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,19 @@ func init() {

type glogger struct{}

func (g *glogger) Fatal(args ...interface{}) {
glog.Fatal(args...)
func (g *glogger) Print(l grpclog.Severity, args ...interface{}) {
switch l {
case grpclog.InfoLog:
glog.Info(args...)
case grpclog.WarningLog:
glog.Warning(args...)
case grpclog.ErrorLog:
glog.Error(args...)
case grpclog.FatalLog:
glog.Fatal(args...)
}
}

func (g *glogger) Fatalf(format string, args ...interface{}) {
glog.Fatalf(format, args...)
}

func (g *glogger) Fatalln(args ...interface{}) {
glog.Fatalln(args...)
}

func (g *glogger) Print(args ...interface{}) {
glog.Info(args...)
}

func (g *glogger) Printf(format string, args ...interface{}) {
glog.Infof(format, args...)
}

func (g *glogger) Println(args ...interface{}) {
glog.Infoln(args...)
func (g *glogger) V(l grpclog.VerboseLevel) bool {
return bool(glog.V(glog.Level(l)))
}
153 changes: 131 additions & 22 deletions grpclog/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,57 +37,166 @@ Package grpclog defines logging for grpc.
package grpclog // import "google.golang.org/grpc/grpclog"

import (
"fmt"
"log"
"os"
)

// Use golang's standard logger by default.
// Access is not mutex-protected: do not modify except in init()
// functions.
var logger Logger = log.New(os.Stderr, "", log.LstdFlags)
// Severity identifies the log severity: info, error, warning, fatal.
type Severity int32

// Logger mimics golang's standard Logger as an interface.
const (
// InfoLog indicates Info severity.
InfoLog Severity = iota
// WarningLog indicates Warning severity.
WarningLog
// ErrorLog indicates Error severity.
ErrorLog
// FatalLog indicates Fatal severity.
// Print() with FatalLog should call os.Exit() with a non-zero exit code.
FatalLog
)

// SeverityName contains the string representation of each severity.
var SeverityName = []string{
InfoLog: "INFO",
WarningLog: "WARNING",
ErrorLog: "ERROR",
FatalLog: "FATAL",
}

// VerboseLevel identifies the verbose level used in grpclog.V() function.
type VerboseLevel int32

// Logger does underlying logging work for grpclog.
type Logger interface {
Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Fatalln(args ...interface{})
Print(args ...interface{})
Printf(format string, args ...interface{})
Println(args ...interface{})
// Print logs args. Arguments are handled in the manner of fmt.Print.
// l specifies the logging severity for this Print().
Print(l Severity, args ...interface{})
// V reports whether verbosity level l is at least the requested verbose level.
V(l VerboseLevel) bool
}

// SetLogger sets the logger that is used in grpc. Call only from
// init() functions.
// SetLogger sets the logger that is used in grpc.
// Not mutex-protected, should be called before any gRPC functions.
func SetLogger(l Logger) {
logger = l
}

// Fatal is equivalent to Print() followed by a call to os.Exit() with a non-zero exit code.
// loggerT is the default logger used by grpclog.
type loggerT struct {
m []*log.Logger
}

// newLogger creates a default logger.
func newLogger() Logger {
var m []*log.Logger
for s := range SeverityName {
if s == int(FatalLog) {
// Don't create logger for FatalLog, use InfoLog instead.
break
}
m = append(m, log.New(os.Stderr, SeverityName[s]+": ", log.LstdFlags))
}
return &loggerT{m: m}
}

func (g *loggerT) Print(l Severity, args ...interface{}) {
switch l {
case InfoLog, WarningLog, ErrorLog:
g.m[l].Print(args...)
case FatalLog:
g.m[InfoLog].Fatal(args...)
}
}

func (g *loggerT) V(l VerboseLevel) bool {
// Returns true for all verbose level.
// TODO support verbose level in the default logger.
return true
}

var logger = newLogger()

// V reports whether verbosity level l is at least the requested verbose level.
func V(l VerboseLevel) bool {
return logger.V(l)
}

// Info logs to the INFO log.
func Info(args ...interface{}) {
logger.Print(InfoLog, args...)
}

// Infof logs to the INFO log. Arguments are handled in the manner of fmt.Printf.
func Infof(format string, args ...interface{}) {
logger.Print(InfoLog, fmt.Sprintf(format, args...))
}

// Infoln logs to the INFO log. Arguments are handled in the manner of fmt.Println.
func Infoln(args ...interface{}) {
logger.Print(InfoLog, fmt.Sprintln(args...))
}

// Warning logs to the WARNING log.
func Warning(args ...interface{}) {
logger.Print(WarningLog, args...)
}

// Warningf logs to the WARNING log. Arguments are handled in the manner of fmt.Printf.
func Warningf(format string, args ...interface{}) {
logger.Print(WarningLog, fmt.Sprintf(format, args...))
}

// Warningln logs to the WARNING log. Arguments are handled in the manner of fmt.Println.
func Warningln(args ...interface{}) {
logger.Print(WarningLog, fmt.Sprintln(args...))
}

// Error logs to the ERROR log.
func Error(args ...interface{}) {
logger.Print(ErrorLog, args...)
}

// Errorf logs to the ERROR log. Arguments are handled in the manner of fmt.Printf.
func Errorf(format string, args ...interface{}) {
logger.Print(ErrorLog, fmt.Sprintf(format, args...))
}

// Errorln logs to the ERROR log. Arguments are handled in the manner of fmt.Println.
func Errorln(args ...interface{}) {
logger.Print(ErrorLog, fmt.Sprintln(args...))
}

// Fatal is equivalent to Info() followed by a call to os.Exit() with a non-zero exit code.
func Fatal(args ...interface{}) {
logger.Fatal(args...)
logger.Print(FatalLog, args...)
}

// Fatalf is equivalent to Printf() followed by a call to os.Exit() with a non-zero exit code.
// Fatalf is equivalent to Infof() followed by a call to os.Exit() with a non-zero exit code.
func Fatalf(format string, args ...interface{}) {
logger.Fatalf(format, args...)
logger.Print(FatalLog, fmt.Sprintf(format, args...))
}

// Fatalln is equivalent to Println() followed by a call to os.Exit()) with a non-zero exit code.
// Fatalln is equivalent to Infoln() followed by a call to os.Exit()) with a non-zero exit code.
func Fatalln(args ...interface{}) {
logger.Fatalln(args...)
logger.Print(FatalLog, fmt.Sprintln(args...))
}

// Print prints to the logger. Arguments are handled in the manner of fmt.Print.
// Print is deprecated, please use Info.
func Print(args ...interface{}) {
logger.Print(args...)
logger.Print(InfoLog, args...)
}

// Printf prints to the logger. Arguments are handled in the manner of fmt.Printf.
// Printf is deprecated, please use Infof.
func Printf(format string, args ...interface{}) {
logger.Printf(format, args...)
logger.Print(InfoLog, fmt.Sprintf(format, args...))
}

// Println prints to the logger. Arguments are handled in the manner of fmt.Println.
// Println is deprecated, please use Infoln.
func Println(args ...interface{}) {
logger.Println(args...)
logger.Print(InfoLog, fmt.Sprintln(args...))
}
64 changes: 64 additions & 0 deletions grpclog/logger_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
*
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/

package grpclog

import (
"bytes"
"fmt"
"regexp"
"testing"
)

func TestLoggerSeverity(t *testing.T) {
var buffers []*bytes.Buffer
logger := newLogger().(*loggerT)
for i := 0; i < int(FatalLog); i++ {
b := new(bytes.Buffer)
buffers = append(buffers, b)
logger.m[i].SetOutput(b)
}
SetLogger(logger)

Info(SeverityName[InfoLog])
Warning(SeverityName[WarningLog])
Error(SeverityName[ErrorLog])

for i := 0; i < int(FatalLog); i++ {
b := buffers[i]
expected := regexp.MustCompile(fmt.Sprintf(`^%s: [0-9]{4}/[0-9]{2}/[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2} %s\n$`, SeverityName[i], SeverityName[i]))
if m := expected.MatchReader(b); !m {
t.Errorf("got: %v, want string in format of: %v\n", b.String(), SeverityName[i]+": 2016/10/05 17:09:26 "+SeverityName[i])
}
}
}
9 changes: 2 additions & 7 deletions test/end2end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ import (
"flag"
"fmt"
"io"
"log"
"math"
"net"
"os"
Expand All @@ -59,7 +58,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/grpclog"
_ "google.golang.org/grpc/grpclog/glogger"
"google.golang.org/grpc/health"
healthpb "google.golang.org/grpc/health/grpc_health_v1"
"google.golang.org/grpc/internal"
Expand Down Expand Up @@ -2712,12 +2711,12 @@ func interestingGoroutines() (gs []string) {
strings.Contains(stack, "testing.tRunner(") ||
strings.Contains(stack, "runtime.goexit") ||
strings.Contains(stack, "created by runtime.gc") ||
strings.Contains(stack, "created by google3/base/go/log.init") ||
strings.Contains(stack, "interestingGoroutines") ||
strings.Contains(stack, "runtime.MHeap_Scavenger") ||
strings.Contains(stack, "signal.signal_recv") ||
strings.Contains(stack, "sigterm.handler") ||
strings.Contains(stack, "runtime_mcall") ||
strings.Contains(stack, "(*loggingT).flushDaemon") ||
strings.Contains(stack, "goroutine in C code") {
continue
}
Expand Down Expand Up @@ -2824,10 +2823,6 @@ func logOutputHasContents(v []byte, wakeup chan<- bool) bool {
return false
}

func init() {
grpclog.SetLogger(log.New(testLogOutput, "", log.LstdFlags))
}

var verboseLogs = flag.Bool("verbose_logs", false, "show all grpclog output, without filtering")

func noop() {}
Expand Down

0 comments on commit 3c39586

Please sign in to comment.