Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify the server logs and the gokit logging. #870

Merged
merged 4 commits into from
Jul 25, 2018
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
533 changes: 483 additions & 50 deletions Gopkg.lock

Large diffs are not rendered by default.

5 changes: 2 additions & 3 deletions cmd/alertmanager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,11 @@ func main() {
},
}
alertmanagerConfig alertmanager.MultitenantAlertmanagerConfig
logLevel util.LogLevel
)
util.RegisterFlags(&serverConfig, &alertmanagerConfig, &logLevel)
util.RegisterFlags(&serverConfig, &alertmanagerConfig)
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

multiAM, err := alertmanager.NewMultitenantAlertmanager(&alertmanagerConfig)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/configs/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ func main() {
},
}
dbConfig db.Config
logLevel util.LogLevel
)
util.RegisterFlags(&serverConfig, &dbConfig, &logLevel)
util.RegisterFlags(&serverConfig, &dbConfig)
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

db, err := db.New(dbConfig)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/distributor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,11 @@ func main() {
}
ringConfig ring.Config
distributorConfig distributor.Config
logLevel util.LogLevel
)
util.RegisterFlags(&serverConfig, &ringConfig, &distributorConfig, &logLevel)
util.RegisterFlags(&serverConfig, &ringConfig, &distributorConfig)
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

// Setting the environment variable JAEGER_AGENT_HOST enables tracing
trace := tracing.NewFromEnv("distributor")
Expand Down
5 changes: 2 additions & 3 deletions cmd/ingester/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ func main() {
schemaConfig chunk.SchemaConfig
storageConfig storage.Config
ingesterConfig ingester.Config
logLevel util.LogLevel
eventSampleRate int
maxStreams uint
)
Expand All @@ -45,12 +44,12 @@ func main() {
// Ingester needs to know our gRPC listen port.
ingesterConfig.LifecyclerConfig.ListenPort = &serverConfig.GRPCListenPort
util.RegisterFlags(&serverConfig, &chunkStoreConfig, &storageConfig,
&schemaConfig, &ingesterConfig, &logLevel)
&schemaConfig, &ingesterConfig)
flag.UintVar(&maxStreams, "ingester.max-concurrent-streams", 1000, "Limit on the number of concurrent streams for gRPC calls (0 = unlimited)")
flag.IntVar(&eventSampleRate, "event.sample-rate", 0, "How often to sample observability events (0 = never).")
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)
util.InitEvents(eventSampleRate)

if maxStreams > 0 {
Expand Down
5 changes: 2 additions & 3 deletions cmd/lite/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,13 @@ func main() {
rulerConfig ruler.Config
schemaConfig chunk.SchemaConfig
storageConfig storage.Config
logLevel util.LogLevel

unauthenticated bool
)
// Ingester needs to know our gRPC listen port.
ingesterConfig.LifecyclerConfig.ListenPort = &serverConfig.GRPCListenPort
util.RegisterFlags(&serverConfig, &chunkStoreConfig, &distributorConfig, &querierConfig,
&ingesterConfig, &configStoreConfig, &rulerConfig, &storageConfig, &schemaConfig, &logLevel)
&ingesterConfig, &configStoreConfig, &rulerConfig, &storageConfig, &schemaConfig)
flag.BoolVar(&unauthenticated, "unauthenticated", false, "Set to true to disable multitenancy.")
flag.Parse()
ingesterConfig.SetClientConfig(distributorConfig.IngesterClientConfig)
Expand All @@ -63,7 +62,7 @@ func main() {
trace := tracing.NewFromEnv("ingester")
defer trace.Close()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

server, err := server.New(serverConfig)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/querier/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,16 @@ func main() {
chunkStoreConfig chunk.StoreConfig
schemaConfig chunk.SchemaConfig
storageConfig storage.Config
logLevel util.LogLevel
)
util.RegisterFlags(&serverConfig, &ringConfig, &distributorConfig, &querierConfig,
&chunkStoreConfig, &schemaConfig, &storageConfig, &logLevel)
&chunkStoreConfig, &schemaConfig, &storageConfig)
flag.Parse()

// Setting the environment variable JAEGER_AGENT_HOST enables tracing
trace := tracing.NewFromEnv("querier")
defer trace.Close()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

r, err := ring.New(ringConfig)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/ruler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ func main() {
storageConfig storage.Config
configStoreConfig ruler.ConfigStoreConfig
querierConfig querier.Config
logLevel util.LogLevel
)

// Setting the environment variable JAEGER_AGENT_HOST enables tracing
Expand All @@ -46,10 +45,10 @@ func main() {

util.RegisterFlags(&serverConfig, &ringConfig, &distributorConfig,
&rulerConfig, &chunkStoreConfig, &storageConfig, &schemaConfig, &configStoreConfig,
&querierConfig, &logLevel)
&querierConfig)
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

storageClient, err := storage.NewStorageClient(storageConfig, schemaConfig)
if err != nil {
Expand Down
5 changes: 2 additions & 3 deletions cmd/table-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ func main() {
ingesterConfig ingester.Config
storageConfig storage.Config
schemaConfig chunk.SchemaConfig
logLevel util.LogLevel
)
util.RegisterFlags(&ingesterConfig, &serverConfig, &storageConfig, &schemaConfig, &logLevel)
util.RegisterFlags(&ingesterConfig, &serverConfig, &storageConfig, &schemaConfig)
flag.Parse()

util.InitLogger(logLevel.AllowedLevel)
util.InitLogger(&serverConfig)

if (schemaConfig.ChunkTables.WriteScale.Enabled ||
schemaConfig.IndexTables.WriteScale.Enabled ||
Expand Down
146 changes: 63 additions & 83 deletions pkg/util/log.go
Original file line number Diff line number Diff line change
@@ -1,117 +1,74 @@
package util

import (
"flag"
"os"

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/prometheus/client_golang/prometheus"
"github.com/weaveworks/common/logging"
"github.com/weaveworks/common/server"
"github.com/weaveworks/common/user"
"golang.org/x/net/context"
)

// Logger is a shared go-kit logger.
// TODO: Change all components to take a non-global logger via their constructors.
var Logger = log.NewNopLogger()
var (
// Logger is a shared go-kit logger.
// TODO: Change all components to take a non-global logger via their constructors.
Logger = log.NewNopLogger()

// InitLogger initializes the global logger according to the allowed log level.
func InitLogger(level AllowedLevel) {
Logger = MustNewPrometheusLogger(level)
}
logMessages = prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "log_messages_total",
Help: "Total number of log messages.",
}, []string{"level"})

// LogLevel supports registering a flag for the desired log level.
type LogLevel struct {
AllowedLevel
}
supportedLevels = []level.Value{
level.DebugValue(),
level.InfoValue(),
level.WarnValue(),
level.ErrorValue(),
}
)

// RegisterFlags adds the log level flag to the provided flagset.
func (l *LogLevel) RegisterFlags(f *flag.FlagSet) {
l.Set("info")
f.Var(
&l.AllowedLevel,
"log.level",
"Only log messages with the given severity or above. Valid levels: [debug, info, warn, error, fatal]",
)
func init() {
prometheus.MustRegister(logMessages)
}

// WithContext returns a Logger that has information about the current user in
// its details.
//
// e.g.
// log := util.WithContext(ctx)
// log.Errorf("Could not chunk chunks: %v", err)
func WithContext(ctx context.Context, l log.Logger) log.Logger {
// Weaveworks uses "orgs" and "orgID" to represent Cortex users,
// even though the code-base generally uses `userID` to refer to the same thing.
userID, err := user.ExtractOrgID(ctx)
// InitLogger initialises the global gokit logger (util.Logger) and overrides the
// default logger for the server.
func InitLogger(cfg *server.Config) {
l, err := NewPrometheusLogger(cfg.LogLevel)
if err != nil {
return l
panic(err)
}
return WithUserID(userID, l)
}

// WithUserID returns a Logger that has information about the current user in
// its details.
func WithUserID(userID string, l log.Logger) log.Logger {
// See note in WithContext.
return log.With(l, "org_id", userID)
Logger = l
cfg.Log = logging.GoKit(l)
}

// PrometheusLogger exposes Prometheus counters for each of go-kit's log levels.
type PrometheusLogger struct {
counterVec *prometheus.CounterVec
logger log.Logger
logger log.Logger
}

var supportedLevels = []level.Value{level.DebugValue(), level.InfoValue(), level.WarnValue(), level.ErrorValue()}

// NewPrometheusLogger creates a new instance of PrometheusLogger which exposes Prometheus counters for various log levels.
// Contrarily to MustNewPrometheusLogger, it returns an error to the caller in case of issue.
// Use NewPrometheusLogger if you want more control. Use MustNewPrometheusLogger if you want a less verbose logger creation.
func NewPrometheusLogger(al AllowedLevel) (log.Logger, error) {
// This code copy-pasted from prometheus/common/promlog.New()
l := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
l = al.Filter(l)
// NewPrometheusLogger creates a new instance of PrometheusLogger which exposes
// Prometheus counters for various log levels.
func NewPrometheusLogger(l logging.Level) (log.Logger, error) {
logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = level.NewFilter(logger, l.Gokit)

counterVec := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "log_messages",
Help: "Total number of log messages.",
}, []string{"level"})
// Initialise counters for all supported levels:
for _, level := range supportedLevels {
counterVec.WithLabelValues(level.String())
}
err := prometheus.Register(counterVec)
// If another library already registered the same metric, use it
if err != nil {
ar, ok := err.(prometheus.AlreadyRegisteredError)
if !ok {
return nil, err
}
counterVec, ok = ar.ExistingCollector.(*prometheus.CounterVec)
if !ok {
return nil, err
}
}
l = &PrometheusLogger{
counterVec: counterVec,
logger: l,
logMessages.WithLabelValues(level.String())
}
// DefaultCaller must be the last wrapper
l = log.With(l, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
return l, nil
}

// MustNewPrometheusLogger creates a new instance of PrometheusLogger which exposes Prometheus counters for various log levels.
// Contrarily to NewPrometheusLogger, it does not return any error to the caller, but panics instead.
// Use MustNewPrometheusLogger if you want a less verbose logger creation. Use NewPrometheusLogger if you want more control.
func MustNewPrometheusLogger(al AllowedLevel) log.Logger {
logger, err := NewPrometheusLogger(al)
if err != nil {
panic(err)
logger = &PrometheusLogger{
logger: logger,
}
return logger

// DefaultCaller must be the last wrapper
logger = log.With(logger, "ts", log.DefaultTimestampUTC, "caller", log.DefaultCaller)
return logger, nil
}

// Log increments the appropriate Prometheus counter depending on the log level.
Expand All @@ -124,6 +81,29 @@ func (pl *PrometheusLogger) Log(kv ...interface{}) error {
break
}
}
pl.counterVec.WithLabelValues(l).Inc()
logMessages.WithLabelValues(l).Inc()
return nil
}

// WithContext returns a Logger that has information about the current user in
// its details.
//
// e.g.
// log := util.WithContext(ctx)
// log.Errorf("Could not chunk chunks: %v", err)
func WithContext(ctx context.Context, l log.Logger) log.Logger {
// Weaveworks uses "orgs" and "orgID" to represent Cortex users,
// even though the code-base generally uses `userID` to refer to the same thing.
userID, err := user.ExtractOrgID(ctx)
if err != nil {
return l
}
return WithUserID(userID, l)
}

// WithUserID returns a Logger that has information about the current user in
// its details.
func WithUserID(userID string, l log.Logger) log.Logger {
// See note in WithContext.
return log.With(l, "org_id", userID)
}
Loading