# Log Standard

## Summary

This document stipulates unified log format and best practices to be used across all DBaaS services.

## Log Format
We use [TiDB Log Format](https://github.com/tikv/rfcs/blob/master/text/2018-12-19-unified-log-format.md).

Example:

```
[2020/10/14 10:23:09.171 +00:00] [INFO] [tenant.go:94] ["migrate central database"]
[2020/10/14 10:03:08.965 +00:00] [INFO] [teardown.go:30] ["tearing down cluster"] [tenantID=1304352932073836544] [model=cluster] [clusterID=1311842118066507776]
```

## Log level
- DEBUG
- INFO
- WARN
- ERROR
- FATAL

You could set log level of central service by pulumi config, debug by default.

```
pulumi config set logLevel info
```

## Log package

```
import github.com/pingcap/log
import go.uber.org/zap
```

Example:

```
log.Info("failed to fetch URL",
  zap.String("url", "http://example.com"),
  zap.Int("attempt", 3),
  zap.Duration("backoff", time.Second),
)
```

We use `zap.Logger`. It's even faster than the `zap.SugaredLogger` and allocates far less, but it only supports strongly-typed, structured logging. In general, you could use functions of `github.com/pingcap/log` pkg directly. For example, [func Info](https://godoc.org/github.com/pingcap/log#Info) logs a message at InfoLevel, it wraps the global Logger.

```

```

You could use `logutil.InitZapLogger` to initializes the global Logger with cfg. For example, set the log level.

```
func setupLogger() error {
	loggerCfg := &zaplog.Config{
		Level: conf.GetConf().ServerConfig.LogLevel,
	}
	return logutil.InitZapLogger(loggerCfg)
}
```

You could use `logutil.Logger()` to get global `*zap.Logger`. Sometimes yor want to create a child logger and adds structured context to it, like `tenantID`. You could use [`func (*Logger) With`](https://godoc.org/go.uber.org/zap#Logger.With).

Example:
```
logger := logutil.Logger().With(zap.Int64("tenantID", tenantID))
```
logger has its corresponding [Info](https://godoc.org/go.uber.org/zap#Logger.Info), Error and other methods.
