1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

Capture glog output and redirect to standard logging service

This commit is contained in:
Ewout Prangsma 2018-06-26 12:14:05 +02:00
parent a9247586f7
commit b3abeafcc4
No known key found for this signature in database
GPG key ID: 4DBAD380D93D0698
3 changed files with 139 additions and 5 deletions

View file

@ -0,0 +1,89 @@
//
// DISCLAIMER
//
// Copyright 2018 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Ewout Prangsma
//
//
// Note: This code is added to the standard glog package.
// It has to be here because it needs package level
// access to some members.
// Do not remove this when updating the vendored glog package!
//
package glog
import "strings"
type LogLevel int
const (
// Make sure these constants end up having the same indexes as the severity constants
LogLevelInfo LogLevel = iota
LogLevelWarning
LogLevelError
LogLevelFatal
)
// redirectWriter wraps a callback that is called when data is written to it.
type redirectWriter struct {
cb func(level LogLevel, message string)
level LogLevel
}
func (w *redirectWriter) Flush() error {
return nil
}
func (w *redirectWriter) Sync() error {
return nil
}
func (w *redirectWriter) Write(p []byte) (n int, err error) {
msg := string(p)
if msg[len(msg)-1] == '\n' {
msg = msg[:len(msg)-1]
}
if idx := strings.IndexByte(msg, ']'); idx > 0 {
msg = strings.TrimSpace(msg[idx+1:])
}
w.cb(w.level, msg)
return len(p), nil
}
// RedirectOutput redirects output of the given logging to the given callback.
func (l *loggingT) RedirectOutput(cb func(level LogLevel, message string)) {
l.mu.Lock()
defer l.mu.Unlock()
l.toStderr = false
l.alsoToStderr = false
for i := range logging.file {
logging.file[i] = &redirectWriter{
cb: cb,
level: LogLevel(i),
}
}
return
}
// RedirectOutput redirects output of thestandard logging to the given callback.
func RedirectOutput(cb func(level LogLevel, message string)) {
logging.RedirectOutput(cb)
}

24
main.go
View file

@ -29,6 +29,7 @@ import (
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/pkg/errors"
@ -116,12 +117,25 @@ func cmdUsage(cmd *cobra.Command, args []string) {
// Run the operator
func cmdMainRun(cmd *cobra.Command, args []string) {
// Get environment
namespace := os.Getenv(constants.EnvOperatorPodNamespace)
name := os.Getenv(constants.EnvOperatorPodName)
ip := os.Getenv(constants.EnvOperatorPodIP)
// Prepare log service
goflag.CommandLine.Parse([]string{"-logtostderr"})
var err error
logService, err = logging.NewService(logLevel)
if err != nil {
cliLog.Fatal().Err(err).Msg("Failed to initialize log service")
}
logService.ConfigureRootLogger(func(log zerolog.Logger) zerolog.Logger {
podNameParts := strings.Split(name, "-")
operatorID := podNameParts[len(podNameParts)-1]
cliLog = cliLog.With().Str("operator-id", operatorID).Logger()
return log.With().Str("operator-id", operatorID).Logger()
})
logService.CaptureGLog(logService.MustGetLogger("glog"))
// Check operating mode
if !operatorOptions.enableDeployment && !operatorOptions.enableDeploymentReplication && !operatorOptions.enableStorage {
@ -129,18 +143,18 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
}
// Log version
cliLog.Info().Msgf("Starting arangodb-operator, version %s build %s", projectVersion, projectBuild)
cliLog.Info().
Str("pod-name", name).
Str("pod-namespace", namespace).
Msgf("Starting arangodb-operator, version %s build %s", projectVersion, projectBuild)
// Get environment
namespace := os.Getenv(constants.EnvOperatorPodNamespace)
// Check environment
if len(namespace) == 0 {
cliLog.Fatal().Msgf("%s environment variable missing", constants.EnvOperatorPodNamespace)
}
name := os.Getenv(constants.EnvOperatorPodName)
if len(name) == 0 {
cliLog.Fatal().Msgf("%s environment variable missing", constants.EnvOperatorPodName)
}
ip := os.Getenv(constants.EnvOperatorPodIP)
if len(ip) == 0 {
cliLog.Fatal().Msgf("%s environment variable missing", constants.EnvOperatorPodIP)
}

View file

@ -28,6 +28,7 @@ import (
"strings"
"sync"
"github.com/golang/glog"
"github.com/rs/zerolog"
)
@ -47,6 +48,10 @@ type Service interface {
MustGetLogger(name string) zerolog.Logger
// MustSetLevel sets the log level for the component with given name to given level.
MustSetLevel(name, level string)
// ConfigureRootLogger calls the given callback to modify the root logger.
ConfigureRootLogger(cb func(rootLog zerolog.Logger) zerolog.Logger)
// CaptureGLog configures glog to write to the given logger
CaptureGLog(log zerolog.Logger)
}
// loggingService implements Service
@ -83,6 +88,32 @@ func NewService(defaultLevel string) (Service, error) {
return s, nil
}
// ConfigureRootLogger calls the given callback to modify the root logger.
func (s *loggingService) ConfigureRootLogger(cb func(rootLog zerolog.Logger) zerolog.Logger) {
s.mutex.Lock()
defer s.mutex.Unlock()
s.rootLog = cb(s.rootLog)
}
// CaptureGLog configures glog to write to the given logger
func (s *loggingService) CaptureGLog(log zerolog.Logger) {
glog.RedirectOutput(func(level glog.LogLevel, msg string) {
var e *zerolog.Event
switch level {
case glog.LogLevelWarning:
e = log.WithLevel(zerolog.WarnLevel)
case glog.LogLevelError:
e = log.WithLevel(zerolog.ErrorLevel)
case glog.LogLevelFatal:
e = log.WithLevel(zerolog.FatalLevel)
default:
e = log.WithLevel(zerolog.InfoLevel)
}
e.Msg(msg)
})
}
// MustGetLogger creates a logger with given name
func (s *loggingService) MustGetLogger(name string) zerolog.Logger {
s.mutex.Lock()