Skip to content
Merged
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
2 changes: 1 addition & 1 deletion cmd/base/options/generic.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func (o *GenericOptions) ApplyTo(c *generic.GenericConfiguration) error {
errList := make([]error, 0, 1)
errList = append(errList, o.qosOptions.ApplyTo(c.QoSConfiguration))
errList = append(errList, o.metricsOptions.ApplyTo(c.MetricsConfiguration))
errList = append(errList, o.logsOptions.ApplyTo())
errList = append(errList, o.logsOptions.ApplyTo(c.LogConfiguration))
errList = append(errList, o.authOptions.ApplyTo(c.AuthConfiguration))

c.ClientConnection.QPS = o.QPS
Expand Down
16 changes: 15 additions & 1 deletion cmd/base/options/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ package options
import (
"github.com/spf13/pflag"

"github.com/kubewharf/katalyst-core/pkg/config/generic"
"github.com/kubewharf/katalyst-core/pkg/util/general"
)

type LogsOptions struct {
LogPackageLevel general.LoggingPKG
LogFileMaxSizeInMB uint64
CustomLogDir string
LogBufferSize int
LogFileMaxAge int
LogFileMaxBackups int
}

func NewLogsOptions() *LogsOptions {
Expand All @@ -36,12 +41,21 @@ func NewLogsOptions() *LogsOptions {

// AddFlags adds flags to the specified FlagSet.
func (o *LogsOptions) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.CustomLogDir, "custom_log_dir", o.CustomLogDir, "directory to store logs for custom logger")
fs.Var(&o.LogPackageLevel, "logs-package-level", "the default package level for logging")
fs.Uint64Var(&o.LogFileMaxSizeInMB, "log-file-max-size", o.LogFileMaxSizeInMB, "Max size of klog file in MB.")
fs.IntVar(&o.LogBufferSize, "log-buffer-size", o.LogBufferSize, "size of the ring buffer to store async logs")
fs.IntVar(&o.LogFileMaxAge, "log-file-max-age", o.LogFileMaxAge, "max age of klog log file in days")
fs.IntVar(&o.LogFileMaxBackups, "log-file-max-backups", o.LogFileMaxBackups, "max number of klog log file backups")
}

func (o *LogsOptions) ApplyTo() error {
func (o *LogsOptions) ApplyTo(c *generic.LogConfiguration) error {
general.SetDefaultLoggingPackage(o.LogPackageLevel)
general.SetLogFileMaxSize(o.LogFileMaxSizeInMB)
c.CustomLogDir = o.CustomLogDir
c.LogBufferSize = o.LogBufferSize
c.LogFileMaxSize = int(o.LogFileMaxSizeInMB)
c.LogFileMaxAge = o.LogFileMaxAge
c.LogFileMaxBackups = o.LogFileMaxBackups
return nil
}
11 changes: 9 additions & 2 deletions cmd/katalyst-agent/app/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/kubewharf/katalyst-core/pkg/consts"
"github.com/kubewharf/katalyst-core/pkg/metrics"
"github.com/kubewharf/katalyst-core/pkg/util/general"
"github.com/kubewharf/katalyst-core/pkg/util/logging"
"github.com/kubewharf/katalyst-core/pkg/util/process"
)

Expand All @@ -45,7 +46,9 @@ const (
// Run starts common and uniformed agent components here, and starts other
// specific components in other separate repos (with common components as
// dependencies)
func Run(conf *config.Configuration, clientSet *client.GenericClientSet, genericOptions ...katalystbase.GenericOptions) error {
func Run(
conf *config.Configuration, clientSet *client.GenericClientSet, genericOptions ...katalystbase.GenericOptions,
) error {
// Set up signals so that we handle the first shutdown signal gracefully.
ctx := process.SetupSignalHandler()

Expand All @@ -60,6 +63,9 @@ func Run(conf *config.Configuration, clientSet *client.GenericClientSet, generic
return err
}

customLogger := logging.NewCustomLogger(genericCtx, conf.CustomLogDir, conf.LogFileMaxSize, conf.LogFileMaxAge, conf.LogFileMaxBackups, conf.LogBufferSize)
defer customLogger.Shutdown()

for _, genericOption := range genericOptions {
genericOption(genericCtx)
}
Expand All @@ -78,7 +84,8 @@ func Run(conf *config.Configuration, clientSet *client.GenericClientSet, generic
}

// startAgent is used to initialize and start each component in katalyst-agent
func startAgent(ctx context.Context, genericCtx *agent.GenericContext,
func startAgent(
ctx context.Context, genericCtx *agent.GenericContext,
conf *config.Configuration, agents map[string]AgentStarter,
) error {
componentMap := make(map[string]agent.Component)
Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ require (
github.com/prometheus/common v0.37.0
github.com/prometheus/procfs v0.10.0
github.com/robfig/cron/v3 v3.0.1
github.com/rs/zerolog v1.34.0
github.com/safchain/ethtool v0.5.10
github.com/samber/lo v1.39.0
github.com/slok/kubewebhook v0.11.0
Expand All @@ -49,6 +50,7 @@ require (
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
gonum.org/v1/gonum v0.8.2
google.golang.org/grpc v1.57.1
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.1
gotest.tools/v3 v3.0.3
k8s.io/api v0.26.1
Expand Down Expand Up @@ -83,7 +85,7 @@ require (
github.com/containerd/console v1.0.3 // indirect
github.com/containerd/ttrpc v1.2.3-0.20231030150553-baadfd8e7956 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
Expand Down Expand Up @@ -159,7 +161,6 @@ require (
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiextensions-apiserver v0.24.2 // indirect
k8s.io/cloud-provider v0.24.16 // indirect
Expand Down
14 changes: 13 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,9 @@ github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
Expand Down Expand Up @@ -601,11 +602,16 @@ github.com/matoous/godox v0.0.0-20190911065817-5d6d842e92eb/go.mod h1:1BELzlh859
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
Expand Down Expand Up @@ -797,6 +803,9 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
Expand Down Expand Up @@ -1266,8 +1275,11 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
2 changes: 2 additions & 0 deletions pkg/config/generic/generic_base.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type GenericConfiguration struct {
*QoSConfiguration
*MetricsConfiguration
*AuthConfiguration
*LogConfiguration

// ClientConnection specifies the kubeconfig file and client connection
// settings for the proxy server to use when communicating with the apiserver.
Expand All @@ -49,5 +50,6 @@ func NewGenericConfiguration() *GenericConfiguration {
QoSConfiguration: NewQoSConfiguration(),
MetricsConfiguration: NewMetricsConfiguration(),
AuthConfiguration: NewAuthConfiguration(),
LogConfiguration: NewLogConfiguration(),
}
}
29 changes: 29 additions & 0 deletions pkg/config/generic/log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
Copyright 2022 The Katalyst Authors.

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.
*/

package generic

type LogConfiguration struct {
CustomLogDir string
LogFileMaxSize int
LogBufferSize int
LogFileMaxAge int
LogFileMaxBackups int
}

func NewLogConfiguration() *LogConfiguration {
return &LogConfiguration{}
}
122 changes: 122 additions & 0 deletions pkg/util/logging/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
Copyright 2022 The Katalyst Authors.

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.
*/

package logging

import (
"fmt"
"os"
"path"
"path/filepath"
"time"

"github.com/rs/zerolog/diode"
"gopkg.in/natefinch/lumberjack.v2"
"k8s.io/klog/v2"

"github.com/kubewharf/katalyst-core/cmd/katalyst-agent/app/agent"
"github.com/kubewharf/katalyst-core/pkg/metrics"
)

type SeverityName string

const (
InfoSeverity SeverityName = "INFO"
WarningSeverity SeverityName = "WARNING"
ErrorSeverity SeverityName = "ERROR"
FatalSeverity SeverityName = "FATAL"
)

const (
metricsNameNumDroppedInfoLogs = "number_of_dropped_info_logs"
metricsNameNumDroppedWarningLogs = "number_of_dropped_warning_logs"
metricsNameNumDroppedErrorLogs = "number_of_dropped_error_logs"
metricsNameNumDroppedFatalLogs = "number_of_dropped_fatal_logs"
)

var (
basePath = filepath.Base(os.Args[0])
defaultInfoLogFileName = fmt.Sprintf("%s.%s.log", basePath, InfoSeverity)
defaultWarningLogFileName = fmt.Sprintf("%s.%s.log", basePath, WarningSeverity)
defaultErrorLogFileName = fmt.Sprintf("%s.%s.log", basePath, ErrorSeverity)
defaultFatalLogFileName = fmt.Sprintf("%s.%s.log", basePath, FatalSeverity)
)

type logInfo struct {
fileName string
metricsName string
}

var logInfoMap = map[SeverityName]*logInfo{
InfoSeverity: {fileName: defaultInfoLogFileName, metricsName: metricsNameNumDroppedInfoLogs},
WarningSeverity: {fileName: defaultWarningLogFileName, metricsName: metricsNameNumDroppedWarningLogs},
ErrorSeverity: {fileName: defaultErrorLogFileName, metricsName: metricsNameNumDroppedErrorLogs},
FatalSeverity: {fileName: defaultFatalLogFileName, metricsName: metricsNameNumDroppedFatalLogs},
}

type CustomLogger struct {
diodeWriters []diode.Writer
}

// NewCustomLogger creates a custom logger that can either be asynchronous or synchronous, depending on configuration.
func NewCustomLogger(
agentCtx *agent.GenericContext, logDir string, maxSizeMB, maxAge, maxBackups, bufferSize int,
) *CustomLogger {
wrappedEmitter := agentCtx.EmitterPool.GetDefaultMetricsEmitter()

// If logDir is not set, we are still using klog's native logger, so we just return an empty logger without calling SetOutput()
if logDir == "" {
return &CustomLogger{}
}

customLogger := &CustomLogger{}
for severity, logInfo := range logInfoMap {
filePath := path.Join(logDir, logInfo.fileName)

// lumberjackLogger is a logger that rotates log files
lumberjackLogger := &lumberjack.Logger{
Filename: filePath,
MaxSize: maxSizeMB,
MaxAge: maxAge,
MaxBackups: maxBackups,
}

// Enable async logger if buffer size is more than 0; otherwise, use synchronous lumberjack logger
if bufferSize > 0 {
// diodeWriter is a writer that stores logs in a ring buffer and asynchronously flushes them to disk
diodeWriter := diode.NewWriter(lumberjackLogger, bufferSize, 10*time.Millisecond, func(missed int) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

why using poller rather than waiter?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Polling performs better with high frequency logs; for waiting, the high frequency of logs will likely cause high frequency of context switching for waking up goroutines at every log, probably leading to high overhead.

_ = wrappedEmitter.StoreInt64(logInfo.metricsName, int64(missed), metrics.MetricTypeNameRaw)
})
// Overrides the default synchronous writer with the diode writer
klog.SetOutputBySeverity(string(severity), diodeWriter)
customLogger.diodeWriters = append(customLogger.diodeWriters, diodeWriter)
klog.Infof("custom async logger is enabled for the severity %s", severity)
} else {
klog.SetOutputBySeverity(string(severity), lumberjackLogger)
klog.Infof("custom sync logger is enabled for the severity %s", severity)
}
}

return customLogger
}

func (a *CustomLogger) Shutdown() {
klog.Info("[Shutdown] async writer is shutting down...")
klog.Flush()
for _, writer := range a.diodeWriters {
writer.Close()
}
}
Loading