Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,8 @@ Please update to the latest version of gRPC-Go using

### How to turn on logging

The default logger is controlled by environment variables. Turn everything on
like this:

```console
$ export GRPC_GO_LOG_VERBOSITY_LEVEL=99
$ export GRPC_GO_LOG_SEVERITY_LEVEL=info
```
See the [grpclog package documentation](https://pkg.go.dev/google.golang.org/grpc/grpclog)
for details on how to configure logging.

### The RPC failed with error `"code = Unavailable desc = transport is closing"`

Expand Down
121 changes: 108 additions & 13 deletions grpclog/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,50 @@ package grpclog

import (
"fmt"
"os"
"sync"

"google.golang.org/grpc/grpclog/internal"
)

// componentData records the settings for a component.
type componentData struct {
name string
name string
logPrefix string

infoDepth func(depth int, args ...any)
warningDepth func(depth int, args ...any)
errorDepth func(depth int, args ...any)
fatalDepth func(depth int, args ...any)
Comment on lines +34 to +37
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need these function pointers? Can't we instead store the severityLevel for this component, and handle it directly in each of its methods?

func (c *componentData) InfoDepth(depth int, args ...any) {
    if c.level > severityInfo { return } // Fast-path exit
    // ... rest of logic
}

As an improvement, we could even store the computed prefix in the componentData struct. I'm talking about [" + string(c.name) + "] and not have to compute that for every log message.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@easwars
The reason why I use function pointers is to avoid checking severity every time a log function is called, by replacing loggers with the noopDepth function according to their levels.
I also think it's OK to handle it directly in each methods.
What do you think about this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the meantime, I updated the prefix computation logic: 619a19e

}

type componentCache struct {
mu sync.Mutex
data map[string]*componentData
}

var cache = map[string]*componentData{}
var cache = componentCache{
data: map[string]*componentData{},
}

func (c *componentData) InfoDepth(depth int, args ...any) {
args = append([]any{"[" + string(c.name) + "]"}, args...)
InfoDepth(depth+1, args...)
args = append([]any{c.logPrefix}, args...)
c.infoDepth(depth+1, args...)
}

func (c *componentData) WarningDepth(depth int, args ...any) {
args = append([]any{"[" + string(c.name) + "]"}, args...)
WarningDepth(depth+1, args...)
args = append([]any{c.logPrefix}, args...)
c.warningDepth(depth+1, args...)
}

func (c *componentData) ErrorDepth(depth int, args ...any) {
args = append([]any{"[" + string(c.name) + "]"}, args...)
ErrorDepth(depth+1, args...)
args = append([]any{c.logPrefix}, args...)
c.errorDepth(depth+1, args...)
}

func (c *componentData) FatalDepth(depth int, args ...any) {
args = append([]any{"[" + string(c.name) + "]"}, args...)
FatalDepth(depth+1, args...)
args = append([]any{c.logPrefix}, args...)
c.fatalDepth(depth+1, args...)
}

func (c *componentData) Info(args ...any) {
Expand Down Expand Up @@ -101,15 +118,93 @@ func (c *componentData) V(l int) bool {
return V(l)
}

func componentInfoDepth(depth int, args ...any) {
if internal.ComponentDepthLoggerV2Impl != nil {
internal.ComponentDepthLoggerV2Impl.InfoDepth(depth, args...)
} else {
internal.ComponentLoggerV2Impl.Infoln(args...)
}
}

func componentWarningDepth(depth int, args ...any) {
if internal.ComponentDepthLoggerV2Impl != nil {
internal.ComponentDepthLoggerV2Impl.WarningDepth(depth, args...)
} else {
internal.ComponentLoggerV2Impl.Warningln(args...)
}
}

func componentErrorDepth(depth int, args ...any) {
if internal.ComponentDepthLoggerV2Impl != nil {
internal.ComponentDepthLoggerV2Impl.ErrorDepth(depth, args...)
} else {
internal.ComponentLoggerV2Impl.Errorln(args...)
}
}

func componentFatalDepth(depth int, args ...any) {
if internal.ComponentDepthLoggerV2Impl != nil {
internal.ComponentDepthLoggerV2Impl.FatalDepth(depth, args...)
} else {
internal.ComponentLoggerV2Impl.Fatalln(args...)
}
os.Exit(1)
}

func noopDepth(int, ...any) {
}

// Component creates a new component and returns it for logging. If a component
// with the name already exists, nothing will be created and it will be
// returned. SetLoggerV2 will panic if it is called with a logger created by
// Component.
func Component(componentName string) DepthLoggerV2 {
if cData, ok := cache[componentName]; ok {
cache.mu.Lock()
defer cache.mu.Unlock()
if cData, ok := cache.data[componentName]; ok {
return cData
}
c := &componentData{componentName}
cache[componentName] = c
c := &componentData{
name: componentName,
logPrefix: "[" + componentName + "]",
infoDepth: InfoDepth,
warningDepth: WarningDepth,
errorDepth: ErrorDepth,
fatalDepth: FatalDepth,
}

if level, ok := componentLogLevels[componentName]; ok {
c.fatalDepth = func(depth int, args ...any) {
componentFatalDepth(depth+1, args...)
}
switch level {
case severityInfo:
c.infoDepth = func(depth int, args ...any) {
componentInfoDepth(depth+1, args...)
}
c.warningDepth = func(depth int, args ...any) {
componentWarningDepth(depth+1, args...)
}
c.errorDepth = func(depth int, args ...any) {
componentErrorDepth(depth+1, args...)
}
case severityWarning:
c.infoDepth = noopDepth
c.warningDepth = func(depth int, args ...any) {
componentWarningDepth(depth+1, args...)
}
c.errorDepth = func(depth int, args ...any) {
componentErrorDepth(depth+1, args...)
}
case severityError:
c.infoDepth = noopDepth
c.warningDepth = noopDepth
c.errorDepth = func(depth int, args ...any) {
componentErrorDepth(depth+1, args...)
}
}
}

cache.data[componentName] = c
return c
}
Loading
Loading