cmd: fix inconsistent logging for binaries
This commit is contained in:
@@ -52,7 +52,7 @@ func main() {
|
|||||||
|
|
||||||
if opts.logPath != "" {
|
if opts.logPath != "" {
|
||||||
// instead write parsable logs for logstash/splunk/etc
|
// instead write parsable logs for logstash/splunk/etc
|
||||||
output, err := os.Open(opts.logPath)
|
output, err := os.OpenFile(opts.logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithFields(logrus.Fields{
|
log.WithFields(logrus.Fields{
|
||||||
"error": err,
|
"error": err,
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gtank/ctxd/frontend"
|
|
||||||
"github.com/gtank/ctxd/rpc"
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/peer"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
|
|
||||||
|
"github.com/gtank/ctxd/frontend"
|
||||||
|
"github.com/gtank/ctxd/rpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
var log *logrus.Entry
|
var log *logrus.Entry
|
||||||
@@ -30,6 +34,44 @@ func init() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func LoggingInterceptor() grpc.ServerOption {
|
||||||
|
return grpc.UnaryInterceptor(logInterceptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func logInterceptor(
|
||||||
|
ctx context.Context,
|
||||||
|
req interface{},
|
||||||
|
info *grpc.UnaryServerInfo,
|
||||||
|
handler grpc.UnaryHandler,
|
||||||
|
) (interface{}, error) {
|
||||||
|
reqLog := loggerFromContext(ctx)
|
||||||
|
start := time.Now()
|
||||||
|
|
||||||
|
resp, err := handler(ctx, req)
|
||||||
|
|
||||||
|
entry := reqLog.WithFields(logrus.Fields{
|
||||||
|
"method": info.FullMethod,
|
||||||
|
"duration": time.Since(start),
|
||||||
|
"error": err,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
entry.Error("call failed")
|
||||||
|
} else {
|
||||||
|
entry.Info("method called")
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func loggerFromContext(ctx context.Context) *logrus.Entry {
|
||||||
|
// TODO: anonymize the addresses. cryptopan?
|
||||||
|
if peerInfo, ok := peer.FromContext(ctx); ok {
|
||||||
|
return log.WithFields(logrus.Fields{"peer_addr": peerInfo.Addr})
|
||||||
|
}
|
||||||
|
return log.WithFields(logrus.Fields{"peer_addr": "unknown"})
|
||||||
|
}
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
bindAddr string `json:"bind_address,omitempty"`
|
bindAddr string `json:"bind_address,omitempty"`
|
||||||
dbPath string `json:"db_path"`
|
dbPath string `json:"db_path"`
|
||||||
@@ -46,7 +88,7 @@ func main() {
|
|||||||
flag.StringVar(&opts.tlsCertPath, "tls-cert", "", "the path to a TLS certificate (optional)")
|
flag.StringVar(&opts.tlsCertPath, "tls-cert", "", "the path to a TLS certificate (optional)")
|
||||||
flag.StringVar(&opts.tlsKeyPath, "tls-key", "", "the path to a TLS key file (optional)")
|
flag.StringVar(&opts.tlsKeyPath, "tls-key", "", "the path to a TLS key file (optional)")
|
||||||
flag.Uint64Var(&opts.logLevel, "log-level", uint64(logrus.InfoLevel), "log level (logrus 1-7)")
|
flag.Uint64Var(&opts.logLevel, "log-level", uint64(logrus.InfoLevel), "log level (logrus 1-7)")
|
||||||
// TODO prod logging flag.StringVar(&opts.logPath, "log-file", "", "log file to write to")
|
flag.StringVar(&opts.logPath, "log-file", "", "log file to write to")
|
||||||
// TODO prod metrics
|
// TODO prod metrics
|
||||||
// TODO support config from file and env vars
|
// TODO support config from file and env vars
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@@ -56,6 +98,20 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.logPath != "" {
|
||||||
|
// instead write parsable logs for logstash/splunk/etc
|
||||||
|
output, err := os.OpenFile(opts.logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
log.WithFields(logrus.Fields{
|
||||||
|
"error": err,
|
||||||
|
"path": opts.logPath,
|
||||||
|
}).Fatal("couldn't open log file")
|
||||||
|
}
|
||||||
|
defer output.Close()
|
||||||
|
logger.SetOutput(output)
|
||||||
|
logger.SetFormatter(&logrus.JSONFormatter{})
|
||||||
|
}
|
||||||
|
|
||||||
logger.SetLevel(logrus.Level(opts.logLevel))
|
logger.SetLevel(logrus.Level(opts.logLevel))
|
||||||
|
|
||||||
// gRPC initialization
|
// gRPC initialization
|
||||||
@@ -70,9 +126,9 @@ func main() {
|
|||||||
"error": err,
|
"error": err,
|
||||||
}).Fatal("couldn't load TLS credentials")
|
}).Fatal("couldn't load TLS credentials")
|
||||||
}
|
}
|
||||||
server = grpc.NewServer(grpc.Creds(transportCreds), frontend.LoggingInterceptor())
|
server = grpc.NewServer(grpc.Creds(transportCreds), LoggingInterceptor())
|
||||||
} else {
|
} else {
|
||||||
server = grpc.NewServer(frontend.LoggingInterceptor())
|
server = grpc.NewServer(LoggingInterceptor())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable reflection for debugging
|
// Enable reflection for debugging
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
package frontend
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/peer"
|
|
||||||
)
|
|
||||||
|
|
||||||
var log *logrus.Entry
|
|
||||||
var logger = logrus.New()
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
logger.SetFormatter(&logrus.TextFormatter{
|
|
||||||
//DisableColors: true,
|
|
||||||
FullTimestamp: true,
|
|
||||||
DisableLevelTruncation: true,
|
|
||||||
})
|
|
||||||
|
|
||||||
log = logger.WithFields(logrus.Fields{
|
|
||||||
"app": "frontend-grpc",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func LoggingInterceptor() grpc.ServerOption {
|
|
||||||
return grpc.UnaryInterceptor(logInterceptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
func logInterceptor(
|
|
||||||
ctx context.Context,
|
|
||||||
req interface{},
|
|
||||||
info *grpc.UnaryServerInfo,
|
|
||||||
handler grpc.UnaryHandler,
|
|
||||||
) (interface{}, error) {
|
|
||||||
reqLog := loggerFromContext(ctx)
|
|
||||||
start := time.Now()
|
|
||||||
|
|
||||||
resp, err := handler(ctx, req)
|
|
||||||
|
|
||||||
entry := reqLog.WithFields(logrus.Fields{
|
|
||||||
"method": info.FullMethod,
|
|
||||||
"duration": time.Since(start),
|
|
||||||
"error": err,
|
|
||||||
})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
entry.Error("call failed")
|
|
||||||
} else {
|
|
||||||
entry.Info("method called")
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func loggerFromContext(ctx context.Context) *logrus.Entry {
|
|
||||||
// TODO: anonymize the addresses. cryptopan?
|
|
||||||
if peerInfo, ok := peer.FromContext(ctx); ok {
|
|
||||||
return log.WithFields(logrus.Fields{"peer_addr": peerInfo.Addr})
|
|
||||||
}
|
|
||||||
return log.WithFields(logrus.Fields{"peer_addr": "unknown"})
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user