Skip to content
Merged
17 changes: 17 additions & 0 deletions go/cmd/dolt/commands/sqlserver/command_line_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type commandLineServerConfig struct {
timeout uint64
readOnly bool
logLevel servercfg.LogLevel
logFormat servercfg.LogFormat
dataDir string
cfgDir string
autoCommit bool
Expand Down Expand Up @@ -68,6 +69,7 @@ func DefaultCommandLineServerConfig() *commandLineServerConfig {
timeout: servercfg.DefaultTimeout,
readOnly: servercfg.DefaultReadOnly,
logLevel: servercfg.DefaultLogLevel,
logFormat: servercfg.DefaultLogFormat,
autoCommit: servercfg.DefaultAutoCommit,
maxConnections: servercfg.DefaultMaxConnections,
dataDir: servercfg.DefaultDataDir,
Expand Down Expand Up @@ -143,6 +145,9 @@ func NewCommandLineConfig(creds *cli.UserPassword, apr *argparser.ArgParseResult
if logLevel, ok := apr.GetValue(logLevelFlag); ok {
config.withLogLevel(servercfg.LogLevel(strings.ToLower(logLevel)))
}
if logFormat, ok := apr.GetValue(logFormatFlag); ok {
config.withLogFormat(servercfg.LogFormat(strings.ToLower(logFormat)))
}

if dataDir, ok := apr.GetValue(commands.MultiDBDirFlag); ok {
config.withDataDir(dataDir)
Expand Down Expand Up @@ -232,6 +237,11 @@ func (cfg *commandLineServerConfig) LogLevel() servercfg.LogLevel {
return cfg.logLevel
}

// LogFormat returns the format of logging that the server will use.
func (cfg *commandLineServerConfig) LogFormat() servercfg.LogFormat {
return cfg.logFormat
}

// AutoCommit defines the value of the @@autocommit session variable used on every connection
func (cfg *commandLineServerConfig) AutoCommit() bool {
return cfg.autoCommit
Expand Down Expand Up @@ -400,6 +410,13 @@ func (cfg *commandLineServerConfig) withLogLevel(loglevel servercfg.LogLevel) *c
return cfg
}

// withLogFormat updates the log format and returns the called `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) withLogFormat(logformat servercfg.LogFormat) *commandLineServerConfig {
cfg.logFormat = logformat
cfg.valuesSet[servercfg.LogFormatKey] = struct{}{}
return cfg
}

// withMaxConnections updates the maximum number of concurrent connections and returns the called
// `*commandLineServerConfig`, which is useful for chaining calls.
func (cfg *commandLineServerConfig) withMaxConnections(maxConnections uint64) *commandLineServerConfig {
Expand Down
8 changes: 8 additions & 0 deletions go/cmd/dolt/commands/sqlserver/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ func ConfigureServices(
return err
}
logrus.SetLevel(level)
switch strings.ToLower(string(serverConfig.LogFormat())) {
case string(servercfg.LogFormat_JSON):
logrus.SetFormatter(&logrus.JSONFormatter{})
case string(servercfg.LogFormat_Text):
logrus.SetFormatter(&logrus.TextFormatter{})
default:
return fmt.Errorf("unknown log format: %s", serverConfig.LogFormat())
}

sql.SystemVariables.AddSystemVariables([]sql.SystemVariable{
&sql.MysqlSystemVariable{
Expand Down
4 changes: 4 additions & 0 deletions go/cmd/dolt/commands/sqlserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,8 @@ func TestServerGoodParams(t *testing.T) {
DefaultCommandLineServerConfig().withLogLevel(servercfg.LogLevel_Info).WithPort(15408),
DefaultCommandLineServerConfig().withReadOnly(true).WithPort(15409),
DefaultCommandLineServerConfig().withUser("testusernamE").withPassword("hunter2").withTimeout(4).WithPort(15410),
DefaultCommandLineServerConfig().withLogFormat(servercfg.LogFormat_Text).WithPort(15411),
DefaultCommandLineServerConfig().withLogFormat(servercfg.LogFormat_JSON).WithPort(15412),
DefaultCommandLineServerConfig().withAllowCleartextPasswords(true),
}

Expand Down Expand Up @@ -552,6 +554,8 @@ func TestGenerateYamlConfig(t *testing.T) {

# log_level: info

# log_format: text

# max_logged_query_len: 0

# encode_logged_query: false
Expand Down
2 changes: 2 additions & 0 deletions go/cmd/dolt/commands/sqlserver/sqlserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const (
timeoutFlag = "timeout"
readonlyFlag = "readonly"
logLevelFlag = "loglevel"
logFormatFlag = "logformat"
noAutoCommitFlag = "no-auto-commit"
configFileFlag = "config"
queryParallelismFlag = "query-parallelism"
Expand Down Expand Up @@ -167,6 +168,7 @@ func (cmd SqlServerCmd) ArgParserWithName(name string) *argparser.ArgParser {
ap.SupportsInt(timeoutFlag, "t", "connection timeout", fmt.Sprintf("Defines the timeout, in seconds, used for connections\nA value of `0` represents an infinite timeout. Defaults to `%v`.", serverConfig.ReadTimeout()))
ap.SupportsFlag(readonlyFlag, "r", "Disable modification of the database.")
ap.SupportsString(logLevelFlag, "l", "log level", fmt.Sprintf("Defines the level of logging provided\nOptions are: `trace`, `debug`, `info`, `warning`, `error`, `fatal`. Defaults to `%v`.", serverConfig.LogLevel()))
ap.SupportsString(logFormatFlag, "f", "log format", fmt.Sprintf("Defines the output format of the server log\nOptions are: `text`, `json`. Defaults to `%v`.", serverConfig.LogFormat()))
ap.SupportsString(commands.DataDirFlag, "", "directory", "Defines a directory to find databases to serve. Defaults to the current directory.")
ap.SupportsString(commands.MultiDBDirFlag, "", "directory", "Deprecated, use `--data-dir` instead.")
ap.SupportsString(commands.CfgDirFlag, "", "directory", "Defines a directory that contains non-database storage for dolt. Defaults to `$data-dir/.doltcfg`. Will be created automatically as needed.")
Expand Down
16 changes: 16 additions & 0 deletions go/libraries/doltcore/servercfg/serverconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ const (
LogLevel_Panic LogLevel = "panic"
)

type LogFormat string

const (
LogFormat_Text LogFormat = "text"
LogFormat_JSON LogFormat = "json"
)

const (
DefaultHost = "localhost"
DefaultPort = 3306
Expand All @@ -47,6 +54,7 @@ const (
DefaultTimeout = 8 * 60 * 60 * 1000 // 8 hours, same as MySQL
DefaultReadOnly = false
DefaultLogLevel = LogLevel_Info
DefaultLogFormat = LogFormat_Text
DefaultAutoCommit = true
DefaultAutoGCBehaviorEnable = false
DefaultDoltTransactionCommit = false
Expand Down Expand Up @@ -138,6 +146,8 @@ type ServerConfig interface {
ReadOnly() bool
// LogLevel returns the level of logging that the server will use.
LogLevel() LogLevel
// LogFormat returns the format of logging that the server will use.
LogFormat() LogFormat
// Autocommit defines the value of the @@autocommit session variable used on every connection
AutoCommit() bool
// DoltTransactionCommit defines the value of the @@dolt_transaction_commit session variable that enables Dolt
Expand Down Expand Up @@ -211,6 +221,7 @@ func DefaultServerConfig() ServerConfig {
func defaultServerConfigYAML() *YAMLConfig {
return &YAMLConfig{
LogLevelStr: ptr(string(DefaultLogLevel)),
LogFormatStr: ptr(string(DefaultLogFormat)),
MaxQueryLenInLogs: ptr(DefaultMaxLoggedQueryLen),
EncodeLoggedQuery: ptr(DefaultEncodeLoggedQuery),
BehaviorConfig: BehaviorYAMLConfig{
Expand Down Expand Up @@ -270,6 +281,10 @@ func ValidateConfig(config ServerConfig) error {
if config.LogLevel().String() == "unknown" {
return fmt.Errorf("loglevel is invalid: %v\n", string(config.LogLevel()))
}
if strings.ToLower(fmt.Sprintf("%v", config.LogFormat())) != string(LogFormat_Text) &&
strings.ToLower(fmt.Sprintf("%v", config.LogFormat())) != string(LogFormat_JSON) {
return fmt.Errorf("logformat is invalid: %v\n", config.LogFormat())
}
if config.RequireSecureTransport() && config.TLSCert() == "" && config.TLSKey() == "" {
return fmt.Errorf("require_secure_transport can only be `true` when a tls_key and tls_cert are provided.")
}
Expand All @@ -285,6 +300,7 @@ const (
WriteTimeoutKey = "net_write_timeout"
ReadOnlyKey = "read_only"
LogLevelKey = "log_level"
LogFormatKey = "log_format"
AutoCommitKey = "autocommit"
DoltTransactionCommitKey = "dolt_transaction_commit"
DataDirKey = "data_dir"
Expand Down
15 changes: 15 additions & 0 deletions go/libraries/doltcore/servercfg/yaml_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ type UserSessionVars struct {
// YAMLConfig is a ServerConfig implementation which is read from a yaml file
type YAMLConfig struct {
LogLevelStr *string `yaml:"log_level,omitempty"`
LogFormatStr *string `yaml:"log_format,omitempty" minver:"TBD"`
MaxQueryLenInLogs *int `yaml:"max_logged_query_len,omitempty"`
EncodeLoggedQuery *bool `yaml:"encode_logged_query,omitempty"`
BehaviorConfig BehaviorYAMLConfig `yaml:"behavior,omitempty"`
Expand Down Expand Up @@ -181,6 +182,7 @@ func ServerConfigAsYAMLConfig(cfg ServerConfig) *YAMLConfig {
autoGCBehavior := toAutoGCBehaviorYAML(cfg.AutoGCBehavior())
return &YAMLConfig{
LogLevelStr: ptr(string(cfg.LogLevel())),
LogFormatStr: ptr(string(cfg.LogFormat())),
MaxQueryLenInLogs: nillableIntPtr(cfg.MaxLoggedQueryLen()),
EncodeLoggedQuery: nillableBoolPtr(cfg.ShouldEncodeLoggedQuery()),
BehaviorConfig: BehaviorYAMLConfig{
Expand Down Expand Up @@ -251,6 +253,7 @@ func ServerConfigSetValuesAsYAMLConfig(cfg ServerConfig) *YAMLConfig {

return &YAMLConfig{
LogLevelStr: zeroIf(ptr(string(cfg.LogLevel())), !cfg.ValueSet(LogLevelKey)),
LogFormatStr: zeroIf(ptr(string(cfg.LogFormat())), !cfg.ValueSet(LogFormatKey)),
MaxQueryLenInLogs: zeroIf(ptr(cfg.MaxLoggedQueryLen()), !cfg.ValueSet(MaxLoggedQueryLenKey)),
EncodeLoggedQuery: zeroIf(ptr(cfg.ShouldEncodeLoggedQuery()), !cfg.ValueSet(ShouldEncodeLoggedQueryKey)),
BehaviorConfig: BehaviorYAMLConfig{
Expand Down Expand Up @@ -452,6 +455,9 @@ func (cfg YAMLConfig) withDefaultsFilledIn() YAMLConfig {
if withDefaults.LogLevelStr == nil {
withDefaults.LogLevelStr = defaults.LogLevelStr
}
if withDefaults.LogFormatStr == nil {
withDefaults.LogFormatStr = defaults.LogFormatStr
}
if withDefaults.MaxQueryLenInLogs == nil {
withDefaults.MaxQueryLenInLogs = defaults.MaxQueryLenInLogs
}
Expand Down Expand Up @@ -632,6 +638,15 @@ func (cfg YAMLConfig) LogLevel() LogLevel {
return LogLevel(*cfg.LogLevelStr)
}

// LogFormatStr returns the log format that the server will use.
func (cfg YAMLConfig) LogFormat() LogFormat {
if cfg.LogFormatStr == nil {
return DefaultLogFormat
}

return LogFormat(*cfg.LogFormatStr)
}

// MaxConnections returns the maximum number of simultaneous connections the server will allow. The default is 1
func (cfg YAMLConfig) MaxConnections() uint64 {
if cfg.ListenerConfig.MaxConnections == nil {
Expand Down
3 changes: 2 additions & 1 deletion go/libraries/doltcore/servercfg/yaml_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var trueValue = true
func TestUnmarshall(t *testing.T) {
testStr := `
log_level: info

log_format: text
behavior:
read_only: false
autocommit: true
Expand Down Expand Up @@ -329,6 +329,7 @@ func TestYAMLConfigDefaults(t *testing.T) {
assert.Equal(t, uint64(DefaultTimeout), cfg.ReadTimeout())
assert.Equal(t, DefaultReadOnly, cfg.ReadOnly())
assert.Equal(t, DefaultLogLevel, cfg.LogLevel())
assert.Equal(t, DefaultLogFormat, cfg.LogFormat())
assert.Equal(t, DefaultAutoCommit, cfg.AutoCommit())
assert.Equal(t, DefaultDoltTransactionCommit, cfg.DoltTransactionCommit())
assert.Equal(t, uint64(DefaultMaxConnections), cfg.MaxConnections())
Expand Down
38 changes: 38 additions & 0 deletions integration-tests/bats/sql-server.bats
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,44 @@ EOF
dolt sql -q "show databases;"
stop_sql_server
}
@test "sql-server: logformats are case insensitive" {
# assert that logformat on command line is not case sensitive
cd repo1
PORT=$( definePORT )
dolt sql-server --logformat jSon --port=$PORT --socket "dolt.$PORT.sock" > log.txt 2>&1 &
SERVER_PID=$!
wait_for_connection $PORT 8500
dolt sql -q "show databases;"
stop_sql_server

# assert that logformat in yaml config is not case sensitive
cat >config.yml <<EOF
log_format: teXt
behavior:
disable_client_multi_statements: true
listener:
host: "0.0.0.0"
port: $PORT
EOF
dolt sql-server --config ./config.yml --socket "dolt.$PORT.sock" &
SERVER_PID=$!
wait_for_connection $PORT 8500
dolt sql -q "show databases;"
stop_sql_server
}

@test "sql-server: logformat json functionality is working" {
cd repo1
PORT=$( definePORT )
dolt sql-server --logformat json --port=$PORT --socket "dolt.$PORT.sock" > log.txt 2>&1 &
SERVER_PID=$!
wait_for_connection $PORT 8500
dolt sql -q "show databases;"
stop_sql_server

# Assert that log is in JSON format (checking if logs contain `{...}`)
grep -q '^{.*}$' log.txt
}

@test "sql-server: server assumes existing user" {
cd repo1
Expand Down
Loading