2014-10-04 19:33:20 +08:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package log
import (
2022-09-21 00:32:06 +08:00
"context"
2014-10-04 19:33:20 +08:00
"fmt"
2022-01-06 22:28:05 +08:00
"io"
2014-10-04 19:33:20 +08:00
"os"
"path/filepath"
2022-02-03 23:20:02 +08:00
"sort"
2014-10-04 19:33:20 +08:00
"strings"
2022-02-03 23:20:02 +08:00
"sync"
2022-01-06 22:28:05 +08:00
"time"
2014-10-04 19:33:20 +08:00
2022-01-06 22:28:05 +08:00
gokitlog "github.com/go-kit/log"
2022-07-08 22:56:30 +08:00
"github.com/go-kit/log/level"
2016-06-11 19:49:11 +08:00
"github.com/go-stack/stack"
2022-06-30 06:16:10 +08:00
"github.com/mattn/go-isatty"
"gopkg.in/ini.v1"
2022-01-26 19:19:43 +08:00
"github.com/grafana/grafana/pkg/infra/log/term"
2022-06-23 19:24:26 +08:00
"github.com/grafana/grafana/pkg/infra/log/text"
2019-01-15 18:49:18 +08:00
"github.com/grafana/grafana/pkg/util"
2014-10-04 19:33:20 +08:00
)
2022-02-07 23:00:08 +08:00
var (
loggersToClose [ ] DisposableHandler
loggersToReload [ ] ReloadableHandler
root * logManager
now = time . Now
2022-07-08 22:56:30 +08:00
logTimeFormat = time . RFC3339Nano
2022-09-21 00:32:06 +08:00
ctxLogProviders = [ ] ContextualLogProviderFunc { }
2022-02-07 23:00:08 +08:00
)
2014-10-04 19:33:20 +08:00
2022-01-14 02:30:28 +08:00
const (
// top 7 calls in the stack are within logger
DefaultCallerDepth = 7
CallerContextKey = "caller"
)
2016-06-07 05:06:44 +08:00
func init ( ) {
loggersToClose = make ( [ ] DisposableHandler , 0 )
2018-09-04 16:31:41 +08:00
loggersToReload = make ( [ ] ReloadableHandler , 0 )
2022-01-26 19:19:43 +08:00
2022-04-06 02:15:41 +08:00
// Use discard by default
format := func ( w io . Writer ) gokitlog . Logger {
2022-08-10 21:37:51 +08:00
return gokitlog . NewLogfmtLogger ( gokitlog . NewSyncWriter ( io . Discard ) )
2022-04-06 02:15:41 +08:00
}
2022-02-03 23:20:02 +08:00
logger := level . NewFilter ( format ( os . Stderr ) , level . AllowInfo ( ) )
root = newManager ( logger )
2023-09-07 19:13:34 +08:00
RegisterContextualLogProvider ( func ( ctx context . Context ) ( [ ] any , bool ) {
pFromCtx := ctx . Value ( logParamsContextKey { } )
if pFromCtx != nil {
return pFromCtx . ( [ ] any ) , true
}
return nil , false
} )
2014-10-04 19:33:20 +08:00
}
2022-02-03 23:20:02 +08:00
// logManager manage loggers
type logManager struct {
* ConcreteLogger
2022-07-08 22:56:30 +08:00
loggersByName map [ string ] * ConcreteLogger
logFilters [ ] logWithFilters
mutex sync . RWMutex
2016-02-17 14:43:13 +08:00
}
2022-02-03 23:20:02 +08:00
func newManager ( logger gokitlog . Logger ) * logManager {
return & logManager {
ConcreteLogger : newConcreteLogger ( logger ) ,
loggersByName : map [ string ] * ConcreteLogger { } ,
}
2022-01-06 22:28:05 +08:00
}
2022-02-07 23:00:08 +08:00
func ( lm * logManager ) initialize ( loggers [ ] logWithFilters ) {
2022-02-03 23:20:02 +08:00
lm . mutex . Lock ( )
defer lm . mutex . Unlock ( )
2022-01-06 22:28:05 +08:00
2022-02-03 23:20:02 +08:00
defaultLoggers := make ( [ ] gokitlog . Logger , len ( loggers ) )
for index , logger := range loggers {
defaultLoggers [ index ] = level . NewFilter ( logger . val , logger . maxLevel )
}
2022-01-06 22:28:05 +08:00
2022-02-07 23:00:08 +08:00
lm . ConcreteLogger . Swap ( & compositeLogger { loggers : defaultLoggers } )
2022-02-03 23:20:02 +08:00
lm . logFilters = loggers
2022-01-06 22:28:05 +08:00
2022-02-03 23:20:02 +08:00
loggersByName := [ ] string { }
for k := range lm . loggersByName {
loggersByName = append ( loggersByName , k )
2014-10-04 19:33:20 +08:00
}
2022-02-03 23:20:02 +08:00
sort . Strings ( loggersByName )
for _ , name := range loggersByName {
ctxLoggers := make ( [ ] gokitlog . Logger , len ( loggers ) )
2020-12-15 16:32:06 +08:00
2022-02-03 23:20:02 +08:00
for index , logger := range loggers {
2022-02-07 23:00:08 +08:00
ctxLogger := gokitlog . With ( logger . val , lm . loggersByName [ name ] . ctx ... )
2022-02-03 23:20:02 +08:00
if filterLevel , exists := logger . filters [ name ] ; ! exists {
2022-02-07 23:00:08 +08:00
ctxLoggers [ index ] = level . NewFilter ( ctxLogger , logger . maxLevel )
2022-02-03 23:20:02 +08:00
} else {
2022-02-07 23:00:08 +08:00
ctxLoggers [ index ] = level . NewFilter ( ctxLogger , filterLevel )
2022-02-03 23:20:02 +08:00
}
}
2022-02-07 23:00:08 +08:00
lm . loggersByName [ name ] . Swap ( & compositeLogger { loggers : ctxLoggers } )
2018-09-04 16:31:41 +08:00
}
2022-01-06 22:28:05 +08:00
}
2023-08-30 23:46:47 +08:00
func ( lm * logManager ) New ( ctx ... any ) * ConcreteLogger {
2022-01-06 22:28:05 +08:00
if len ( ctx ) == 0 {
2022-02-03 23:20:02 +08:00
return lm . ConcreteLogger
2022-01-06 22:28:05 +08:00
}
2022-02-03 23:20:02 +08:00
2022-02-07 23:00:08 +08:00
lm . mutex . Lock ( )
defer lm . mutex . Unlock ( )
loggerName , ok := ctx [ 1 ] . ( string )
2022-02-03 23:20:02 +08:00
if ! ok {
return lm . ConcreteLogger
}
if logger , exists := lm . loggersByName [ loggerName ] ; exists {
return logger
}
if len ( lm . logFilters ) == 0 {
2022-02-07 23:00:08 +08:00
ctxLogger := newConcreteLogger ( & lm . SwapLogger , ctx ... )
2022-02-03 23:20:02 +08:00
lm . loggersByName [ loggerName ] = ctxLogger
return ctxLogger
}
compositeLogger := newCompositeLogger ( )
for _ , logWithFilter := range lm . logFilters {
filterLevel , ok := logWithFilter . filters [ loggerName ]
2022-01-06 22:28:05 +08:00
if ok {
2022-02-03 23:20:02 +08:00
logWithFilter . val = level . NewFilter ( logWithFilter . val , filterLevel )
2022-01-06 22:28:05 +08:00
} else {
logWithFilter . val = level . NewFilter ( logWithFilter . val , logWithFilter . maxLevel )
}
2022-02-03 23:20:02 +08:00
compositeLogger . loggers = append ( compositeLogger . loggers , logWithFilter . val )
2022-01-06 22:28:05 +08:00
}
2022-02-03 23:20:02 +08:00
ctxLogger := newConcreteLogger ( compositeLogger , ctx ... )
lm . loggersByName [ loggerName ] = ctxLogger
return ctxLogger
2022-01-06 22:28:05 +08:00
}
2022-02-03 23:20:02 +08:00
type ConcreteLogger struct {
2023-08-30 23:46:47 +08:00
ctx [ ] any
2022-02-07 23:00:08 +08:00
gokitlog . SwapLogger
2022-02-03 23:20:02 +08:00
}
2023-08-30 23:46:47 +08:00
func newConcreteLogger ( logger gokitlog . Logger , ctx ... any ) * ConcreteLogger {
2022-02-07 23:00:08 +08:00
var swapLogger gokitlog . SwapLogger
2022-01-14 02:30:28 +08:00
if len ( ctx ) == 0 {
2023-08-30 23:46:47 +08:00
ctx = [ ] any { }
2022-02-07 23:00:08 +08:00
swapLogger . Swap ( logger )
2022-02-03 23:20:02 +08:00
} else {
2022-02-07 23:00:08 +08:00
swapLogger . Swap ( gokitlog . With ( logger , ctx ... ) )
2022-01-14 02:30:28 +08:00
}
2022-02-03 23:20:02 +08:00
return & ConcreteLogger {
2022-02-07 23:00:08 +08:00
ctx : ctx ,
SwapLogger : swapLogger ,
2022-01-14 02:30:28 +08:00
}
2022-02-03 23:20:02 +08:00
}
2022-02-07 23:00:08 +08:00
func ( cl ConcreteLogger ) GetLogger ( ) gokitlog . Logger {
return & cl . SwapLogger
2022-02-03 23:20:02 +08:00
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) Warn ( msg string , args ... any ) {
2022-02-03 23:20:02 +08:00
_ = cl . log ( msg , level . WarnValue ( ) , args ... )
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) Debug ( msg string , args ... any ) {
2022-02-03 23:20:02 +08:00
_ = cl . log ( msg , level . DebugValue ( ) , args ... )
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) Log ( ctx ... any ) error {
2022-06-30 06:16:10 +08:00
logger := gokitlog . With ( & cl . SwapLogger , "t" , gokitlog . TimestampFormat ( now , logTimeFormat ) )
return logger . Log ( ctx ... )
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) Error ( msg string , args ... any ) {
2022-02-03 23:20:02 +08:00
_ = cl . log ( msg , level . ErrorValue ( ) , args ... )
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) Info ( msg string , args ... any ) {
2022-02-03 23:20:02 +08:00
_ = cl . log ( msg , level . InfoValue ( ) , args ... )
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) log ( msg string , logLevel level . Value , args ... any ) error {
return cl . Log ( append ( [ ] any { level . Key ( ) , logLevel , "msg" , msg } , args ... ) ... )
2022-02-03 23:20:02 +08:00
}
2022-09-21 00:32:06 +08:00
func ( cl * ConcreteLogger ) FromContext ( ctx context . Context ) Logger {
2023-08-30 23:46:47 +08:00
args := [ ] any { }
2022-09-21 00:32:06 +08:00
for _ , p := range ctxLogProviders {
if pArgs , exists := p ( ctx ) ; exists {
args = append ( args , pArgs ... )
}
}
if len ( args ) > 0 {
return cl . New ( args ... )
}
return cl
}
2023-08-30 23:46:47 +08:00
func ( cl * ConcreteLogger ) New ( ctx ... any ) * ConcreteLogger {
2022-02-03 23:20:02 +08:00
if len ( ctx ) == 0 {
root . New ( )
}
2022-02-07 23:00:08 +08:00
return newConcreteLogger ( gokitlog . With ( & cl . SwapLogger ) , ctx ... )
2022-02-03 23:20:02 +08:00
}
2022-04-01 19:24:39 +08:00
// New creates a new logger.
// First ctx argument is expected to be the name of the logger.
// Note: For a contextual logger, i.e. a logger with a shared
// name plus additional contextual information, you must use the
// Logger interface New method for it to work as expected.
// Example creating a shared logger:
2022-08-10 21:37:51 +08:00
//
// requestLogger := log.New("request-logger")
//
2022-04-01 19:24:39 +08:00
// Example creating a contextual logger:
2022-08-10 21:37:51 +08:00
//
// contextualLogger := requestLogger.New("username", "user123")
2023-08-30 23:46:47 +08:00
func New ( ctx ... any ) * ConcreteLogger {
2022-02-07 23:00:08 +08:00
if len ( ctx ) == 0 {
return root . New ( )
}
2022-02-03 23:20:02 +08:00
2023-08-30 23:46:47 +08:00
ctx = append ( [ ] any { "logger" } , ctx ... )
2022-02-07 23:00:08 +08:00
return root . New ( ctx ... )
2022-02-03 23:20:02 +08:00
}
2022-03-10 01:03:58 +08:00
// NewNopLogger returns a logger that doesn't do anything.
func NewNopLogger ( ) * ConcreteLogger {
return newConcreteLogger ( gokitlog . NewNopLogger ( ) )
}
2023-08-30 23:46:47 +08:00
func with ( ctxLogger * ConcreteLogger , withFunc func ( gokitlog . Logger , ... any ) gokitlog . Logger , ctx [ ] any ) * ConcreteLogger {
2022-02-03 23:20:02 +08:00
if len ( ctx ) == 0 {
return ctxLogger
}
2022-02-10 19:51:51 +08:00
ctxLogger . Swap ( withFunc ( ctxLogger . GetLogger ( ) , ctx ... ) )
2022-02-03 23:20:02 +08:00
return ctxLogger
2022-01-14 02:30:28 +08:00
}
// WithPrefix adds context that will be added to the log message
2023-08-30 23:46:47 +08:00
func WithPrefix ( ctxLogger * ConcreteLogger , ctx ... any ) * ConcreteLogger {
2022-02-03 23:20:02 +08:00
return with ( ctxLogger , gokitlog . WithPrefix , ctx )
2022-01-14 02:30:28 +08:00
}
// WithSuffix adds context that will be appended at the end of the log message
2023-08-30 23:46:47 +08:00
func WithSuffix ( ctxLogger * ConcreteLogger , ctx ... any ) * ConcreteLogger {
2022-02-03 23:20:02 +08:00
return with ( ctxLogger , gokitlog . WithSuffix , ctx )
2022-01-14 02:30:28 +08:00
}
2022-09-21 00:32:06 +08:00
// ContextualLogProviderFunc contextual log provider function definition.
2023-08-30 23:46:47 +08:00
type ContextualLogProviderFunc func ( ctx context . Context ) ( [ ] any , bool )
2022-09-21 00:32:06 +08:00
// RegisterContextualLogProvider registers a ContextualLogProviderFunc
// that will be used to provide context when Logger.FromContext is called.
func RegisterContextualLogProvider ( mw ContextualLogProviderFunc ) {
ctxLogProviders = append ( ctxLogProviders , mw )
}
2023-09-07 19:13:34 +08:00
type logParamsContextKey struct { }
// WithContextualAttributes adds contextual attributes to the logger based on the given context.
// That allows loggers further down the chain to automatically log those attributes.
func WithContextualAttributes ( ctx context . Context , logParams [ ] any ) context . Context {
p := logParams
if ctx . Value ( logParamsContextKey { } ) != nil {
p = append ( ctx . Value ( logParamsContextKey { } ) . ( [ ] any ) , logParams ... )
}
return context . WithValue ( ctx , logParamsContextKey { } , p )
}
2022-01-06 22:28:05 +08:00
var logLevels = map [ string ] level . Option {
"trace" : level . AllowDebug ( ) ,
"debug" : level . AllowDebug ( ) ,
"info" : level . AllowInfo ( ) ,
"warn" : level . AllowWarn ( ) ,
"error" : level . AllowError ( ) ,
"critical" : level . AllowError ( ) ,
2014-10-04 19:33:20 +08:00
}
2022-01-06 22:28:05 +08:00
func getLogLevelFromConfig ( key string , defaultName string , cfg * ini . File ) ( string , level . Option ) {
2016-12-15 20:54:47 +08:00
levelName := cfg . Section ( key ) . Key ( "level" ) . MustString ( defaultName )
2016-06-08 14:48:46 +08:00
levelName = strings . ToLower ( levelName )
2016-06-07 18:11:41 +08:00
level := getLogLevelFromString ( levelName )
return levelName , level
}
2014-10-04 19:33:20 +08:00
2022-01-06 22:28:05 +08:00
func getLogLevelFromString ( levelName string ) level . Option {
loglevel , ok := logLevels [ levelName ]
2016-06-07 18:11:41 +08:00
2016-06-07 05:06:44 +08:00
if ! ok {
2022-02-03 23:20:02 +08:00
_ = level . Error ( root ) . Log ( "Unknown log level" , "level" , levelName )
2022-01-06 22:28:05 +08:00
return level . AllowError ( )
2014-10-04 19:33:20 +08:00
}
2022-01-06 22:28:05 +08:00
return loglevel
2016-06-07 18:11:41 +08:00
}
2022-01-06 22:28:05 +08:00
// the filter is composed with logger name and level
func getFilters ( filterStrArray [ ] string ) map [ string ] level . Option {
filterMap := make ( map [ string ] level . Option )
2016-06-07 18:11:41 +08:00
2022-02-10 16:52:37 +08:00
for i := 0 ; i < len ( filterStrArray ) ; i ++ {
filterStr := strings . TrimSpace ( filterStrArray [ i ] )
if strings . HasPrefix ( filterStr , ";" ) || strings . HasPrefix ( filterStr , "#" ) {
if len ( filterStr ) == 1 {
i ++
}
continue
}
2016-06-07 18:11:41 +08:00
parts := strings . Split ( filterStr , ":" )
2016-07-26 18:29:52 +08:00
if len ( parts ) > 1 {
filterMap [ parts [ 0 ] ] = getLogLevelFromString ( parts [ 1 ] )
}
2016-06-07 18:11:41 +08:00
}
return filterMap
2014-10-04 19:33:20 +08:00
}
2022-01-06 22:28:05 +08:00
func Stack ( skip int ) string {
call := stack . Caller ( skip )
s := stack . Trace ( ) . TrimBelow ( call ) . TrimRuntime ( )
return s . String ( )
}
2022-01-14 02:30:28 +08:00
// StackCaller returns a go-kit Valuer function that returns the stack trace from the place it is called. Argument `skip` allows skipping top n lines from the stack.
func StackCaller ( skip int ) gokitlog . Valuer {
2023-08-30 23:46:47 +08:00
return func ( ) any {
2022-01-14 02:30:28 +08:00
return Stack ( skip + 1 )
}
}
// Caller proxies go-kit/log Caller and returns a Valuer function that returns a file and line from a specified depth
// in the callstack
func Caller ( depth int ) gokitlog . Valuer {
return gokitlog . Caller ( depth )
}
2022-01-06 22:28:05 +08:00
type Formatedlogger func ( w io . Writer ) gokitlog . Logger
func getLogFormat ( format string ) Formatedlogger {
2016-06-08 14:48:46 +08:00
switch format {
case "console" :
2017-10-24 01:57:19 +08:00
if isatty . IsTerminal ( os . Stdout . Fd ( ) ) {
2022-01-06 22:28:05 +08:00
return func ( w io . Writer ) gokitlog . Logger {
2022-01-26 19:19:43 +08:00
return term . NewTerminalLogger ( w )
2022-01-06 22:28:05 +08:00
}
}
return func ( w io . Writer ) gokitlog . Logger {
2022-06-23 19:24:26 +08:00
return text . NewTextLogger ( w )
2016-06-08 14:48:46 +08:00
}
case "text" :
2022-01-06 22:28:05 +08:00
return func ( w io . Writer ) gokitlog . Logger {
2022-06-23 19:24:26 +08:00
return text . NewTextLogger ( w )
2022-01-06 22:28:05 +08:00
}
2016-06-08 14:48:46 +08:00
case "json" :
2022-01-06 22:28:05 +08:00
return func ( w io . Writer ) gokitlog . Logger {
return gokitlog . NewJSONLogger ( gokitlog . NewSyncWriter ( w ) )
}
2016-06-08 14:48:46 +08:00
default :
2022-01-06 22:28:05 +08:00
return func ( w io . Writer ) gokitlog . Logger {
2022-06-23 19:24:26 +08:00
return text . NewTextLogger ( w )
2022-01-06 22:28:05 +08:00
}
}
}
// this is for file logger only
func Close ( ) error {
var err error
for _ , logger := range loggersToClose {
if e := logger . Close ( ) ; e != nil && err == nil {
err = e
}
2016-06-08 14:48:46 +08:00
}
2022-01-06 22:28:05 +08:00
loggersToClose = make ( [ ] DisposableHandler , 0 )
return err
}
// Reload reloads all loggers.
func Reload ( ) error {
for _ , logger := range loggersToReload {
if err := logger . Reload ( ) ; err != nil {
return err
}
}
return nil
2016-06-08 14:48:46 +08:00
}
2022-02-07 23:00:08 +08:00
type logWithFilters struct {
val gokitlog . Logger
filters map [ string ] level . Option
maxLevel level . Option
}
2019-12-02 22:40:32 +08:00
func ReadLoggingConfig ( modes [ ] string , logsPath string , cfg * ini . File ) error {
2020-12-15 16:32:06 +08:00
if err := Close ( ) ; err != nil {
return err
}
2014-10-04 19:33:20 +08:00
2022-05-18 23:04:52 +08:00
logEnabled := cfg . Section ( "log" ) . Key ( "enabled" ) . MustBool ( true )
if ! logEnabled {
return nil
}
2016-06-08 14:48:46 +08:00
defaultLevelName , _ := getLogLevelFromConfig ( "log" , "info" , cfg )
2017-04-25 15:14:29 +08:00
defaultFilters := getFilters ( util . SplitString ( cfg . Section ( "log" ) . Key ( "filters" ) . String ( ) ) )
2016-06-07 18:11:41 +08:00
2022-02-07 23:00:08 +08:00
var configLoggers [ ] logWithFilters
2016-06-07 05:06:44 +08:00
for _ , mode := range modes {
mode = strings . TrimSpace ( mode )
sec , err := cfg . GetSection ( "log." + mode )
if err != nil {
2022-02-03 23:20:02 +08:00
_ = level . Error ( root ) . Log ( "Unknown log mode" , "mode" , mode )
2022-06-07 04:30:31 +08:00
return fmt . Errorf ( "failed to get config section log. %s: %w" , mode , err )
2014-10-04 19:33:20 +08:00
}
2016-06-07 05:06:44 +08:00
// Log level.
2022-01-06 22:28:05 +08:00
_ , leveloption := getLogLevelFromConfig ( "log." + mode , defaultLevelName , cfg )
2019-03-06 18:58:27 +08:00
modeFilters := getFilters ( util . SplitString ( sec . Key ( "filters" ) . String ( ) ) )
2022-01-06 22:28:05 +08:00
2016-06-08 14:48:46 +08:00
format := getLogFormat ( sec . Key ( "format" ) . MustString ( "" ) )
2016-06-07 18:11:41 +08:00
2022-02-07 23:00:08 +08:00
var handler logWithFilters
2016-06-07 05:06:44 +08:00
switch mode {
case "console" :
2022-01-06 22:28:05 +08:00
handler . val = format ( os . Stdout )
2016-06-07 05:06:44 +08:00
case "file" :
fileName := sec . Key ( "file_name" ) . MustString ( filepath . Join ( logsPath , "grafana.log" ) )
2019-10-10 22:42:11 +08:00
dpath := filepath . Dir ( fileName )
if err := os . MkdirAll ( dpath , os . ModePerm ) ; err != nil {
2022-02-03 23:20:02 +08:00
_ = level . Error ( root ) . Log ( "Failed to create directory" , "dpath" , dpath , "err" , err )
2022-02-04 01:17:25 +08:00
continue
2019-10-10 22:42:11 +08:00
}
2016-06-07 05:06:44 +08:00
fileHandler := NewFileWriter ( )
fileHandler . Filename = fileName
2016-06-08 14:48:46 +08:00
fileHandler . Format = format
2016-06-07 05:06:44 +08:00
fileHandler . Rotate = sec . Key ( "log_rotate" ) . MustBool ( true )
fileHandler . Maxlines = sec . Key ( "max_lines" ) . MustInt ( 1000000 )
fileHandler . Maxsize = 1 << uint ( sec . Key ( "max_size_shift" ) . MustInt ( 28 ) )
fileHandler . Daily = sec . Key ( "daily_rotate" ) . MustBool ( true )
fileHandler . Maxdays = sec . Key ( "max_days" ) . MustInt64 ( 7 )
2019-10-10 22:42:11 +08:00
if err := fileHandler . Init ( ) ; err != nil {
2022-02-03 23:20:02 +08:00
_ = level . Error ( root ) . Log ( "Failed to initialize file handler" , "dpath" , dpath , "err" , err )
2022-02-04 01:17:25 +08:00
continue
2019-10-10 22:42:11 +08:00
}
2016-06-07 05:06:44 +08:00
loggersToClose = append ( loggersToClose , fileHandler )
2018-09-04 16:31:41 +08:00
loggersToReload = append ( loggersToReload , fileHandler )
2022-01-06 22:28:05 +08:00
handler . val = fileHandler
2016-06-08 14:09:29 +08:00
case "syslog" :
2016-06-17 00:21:12 +08:00
sysLogHandler := NewSyslog ( sec , format )
2016-06-08 14:09:29 +08:00
loggersToClose = append ( loggersToClose , sysLogHandler )
2022-01-06 22:28:05 +08:00
handler . val = sysLogHandler . logger
2016-06-07 05:06:44 +08:00
}
2022-01-06 22:28:05 +08:00
if handler . val == nil {
2019-12-02 22:40:32 +08:00
panic ( fmt . Sprintf ( "Handler is uninitialized for mode %q" , mode ) )
}
2016-06-07 18:11:41 +08:00
2022-01-06 22:28:05 +08:00
// join default filters and mode filters together
2016-06-07 18:11:41 +08:00
for key , value := range defaultFilters {
2019-03-06 18:58:27 +08:00
if _ , exist := modeFilters [ key ] ; ! exist {
modeFilters [ key ] = value
}
}
2022-01-06 22:28:05 +08:00
handler . filters = modeFilters
handler . maxLevel = leveloption
configLoggers = append ( configLoggers , handler )
}
if len ( configLoggers ) > 0 {
2022-02-03 23:20:02 +08:00
root . initialize ( configLoggers )
2016-02-01 12:49:37 +08:00
}
2022-02-03 23:20:02 +08:00
2019-12-02 22:40:32 +08:00
return nil
2014-10-04 19:33:20 +08:00
}
2024-03-19 01:25:30 +08:00
// SetupConsoleLogger setup Grafana console logger with provided level.
func SetupConsoleLogger ( level string ) error {
iniFile := ini . Empty ( )
sLog , err := iniFile . NewSection ( "log" )
if err != nil {
return err
}
_ , err = sLog . NewKey ( "level" , level )
if err != nil {
return err
}
sLogConsole , err := iniFile . NewSection ( "log.console" )
if err != nil {
return err
}
_ , err = sLogConsole . NewKey ( "format" , "console" )
if err != nil {
return err
}
err = ReadLoggingConfig ( [ ] string { "console" } , "" , iniFile )
if err != nil {
return err
}
return nil
}