mirror of
https://github.com/status-im/consul.git
synced 2025-01-09 21:35:52 +00:00
Adds a new command line flag -log-file for file based logging. (#4581)
* Added log-file flag to capture Consul logs in a user specified file * Refactored code. * Refactored code. Added flags to rotate logs based on bytes and duration * Added the flags for log file and log rotation on the webpage * Fixed TestSantize from failing due to the addition of 3 flags * Introduced changes : mutex, data-dir log writes, rotation logic * Added test for logfile and updated the default log destination for docs * Log name now uses UnixNano * TestLogFile is now uses t.Parallel() * Removed unnecessary int64Val function * Updated docs to reflect default log name for log-file * No longer writes to data-dir and adds .log if the filename has no extension
This commit is contained in:
parent
40e71f1b91
commit
ca35d04472
@ -717,6 +717,9 @@ func (b *Builder) Build() (rt RuntimeConfig, err error) {
|
|||||||
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
|
LeaveDrainTime: b.durationVal("performance.leave_drain_time", c.Performance.LeaveDrainTime),
|
||||||
LeaveOnTerm: leaveOnTerm,
|
LeaveOnTerm: leaveOnTerm,
|
||||||
LogLevel: b.stringVal(c.LogLevel),
|
LogLevel: b.stringVal(c.LogLevel),
|
||||||
|
LogFile: b.stringVal(c.LogFile),
|
||||||
|
LogRotateBytes: b.intVal(c.LogRotateBytes),
|
||||||
|
LogRotateDuration: b.durationVal("log_rotate_duration", c.LogRotateDuration),
|
||||||
NodeID: types.NodeID(b.stringVal(c.NodeID)),
|
NodeID: types.NodeID(b.stringVal(c.NodeID)),
|
||||||
NodeMeta: c.NodeMeta,
|
NodeMeta: c.NodeMeta,
|
||||||
NodeName: b.nodeName(c.NodeName),
|
NodeName: b.nodeName(c.NodeName),
|
||||||
|
@ -191,6 +191,9 @@ type Config struct {
|
|||||||
LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"`
|
LeaveOnTerm *bool `json:"leave_on_terminate,omitempty" hcl:"leave_on_terminate" mapstructure:"leave_on_terminate"`
|
||||||
Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"`
|
Limits Limits `json:"limits,omitempty" hcl:"limits" mapstructure:"limits"`
|
||||||
LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"`
|
LogLevel *string `json:"log_level,omitempty" hcl:"log_level" mapstructure:"log_level"`
|
||||||
|
LogFile *string `json:"log_file,omitempty" hcl:"log_file" mapstructure:"log_file"`
|
||||||
|
LogRotateDuration *string `json:"log_rotate_duration,omitempty" hcl:"log_rotate_duration" mapstructure:"log_rotate_duration"`
|
||||||
|
LogRotateBytes *int `json:"log_rotate_bytes,omitempty" hcl:"log_rotate_bytes" mapstructure:"log_rotate_bytes"`
|
||||||
NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"`
|
NodeID *string `json:"node_id,omitempty" hcl:"node_id" mapstructure:"node_id"`
|
||||||
NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"`
|
NodeMeta map[string]string `json:"node_meta,omitempty" hcl:"node_meta" mapstructure:"node_meta"`
|
||||||
NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"`
|
NodeName *string `json:"node_name,omitempty" hcl:"node_name" mapstructure:"node_name"`
|
||||||
|
@ -76,6 +76,9 @@ func AddFlags(fs *flag.FlagSet, f *Flags) {
|
|||||||
add(&f.Config.StartJoinAddrsLAN, "join", "Address of an agent to join at start time. Can be specified multiple times.")
|
add(&f.Config.StartJoinAddrsLAN, "join", "Address of an agent to join at start time. Can be specified multiple times.")
|
||||||
add(&f.Config.StartJoinAddrsWAN, "join-wan", "Address of an agent to join -wan at start time. Can be specified multiple times.")
|
add(&f.Config.StartJoinAddrsWAN, "join-wan", "Address of an agent to join -wan at start time. Can be specified multiple times.")
|
||||||
add(&f.Config.LogLevel, "log-level", "Log level of the agent.")
|
add(&f.Config.LogLevel, "log-level", "Log level of the agent.")
|
||||||
|
add(&f.Config.LogFile, "log-file", "Path to the file the logs get written to")
|
||||||
|
add(&f.Config.LogRotateBytes, "log-rotate-bytes", "Maximum number of bytes that should be written to a log file")
|
||||||
|
add(&f.Config.LogRotateDuration, "log-rotate-duration", "Time after which log rotation needs to be performed")
|
||||||
add(&f.Config.NodeName, "node", "Name of this node. Must be unique in the cluster.")
|
add(&f.Config.NodeName, "node", "Name of this node. Must be unique in the cluster.")
|
||||||
add(&f.Config.NodeID, "node-id", "A unique ID for this node across space and time. Defaults to a randomly-generated ID that persists in the data-dir.")
|
add(&f.Config.NodeID, "node-id", "A unique ID for this node across space and time. Defaults to a randomly-generated ID that persists in the data-dir.")
|
||||||
add(&f.Config.NodeMeta, "node-meta", "An arbitrary metadata key/value pair for this node, of the format `key:value`. Can be specified multiple times.")
|
add(&f.Config.NodeMeta, "node-meta", "An arbitrary metadata key/value pair for this node, of the format `key:value`. Can be specified multiple times.")
|
||||||
|
@ -720,6 +720,24 @@ type RuntimeConfig struct {
|
|||||||
// hcl: log_level = string
|
// hcl: log_level = string
|
||||||
LogLevel string
|
LogLevel string
|
||||||
|
|
||||||
|
// LogFile is the path to the file where the logs get written to. Defaults to empty string.
|
||||||
|
//
|
||||||
|
// hcl: log_file = string
|
||||||
|
// flags: -log-file string
|
||||||
|
LogFile string
|
||||||
|
|
||||||
|
// LogRotateDuration is the time configured to rotate logs based on time
|
||||||
|
//
|
||||||
|
// hcl: log_rotate_duration = string
|
||||||
|
// flags: -log-rotate-duration string
|
||||||
|
LogRotateDuration time.Duration
|
||||||
|
|
||||||
|
// LogRotateBytes is the time configured to rotate logs based on bytes written
|
||||||
|
//
|
||||||
|
// hcl: log_rotate_bytes = int
|
||||||
|
// flags: -log-rotate-bytes int
|
||||||
|
LogRotateBytes int
|
||||||
|
|
||||||
// Node ID is a unique ID for this node across space and time. Defaults
|
// Node ID is a unique ID for this node across space and time. Defaults
|
||||||
// to a randomly-generated ID that persists in the data-dir.
|
// to a randomly-generated ID that persists in the data-dir.
|
||||||
//
|
//
|
||||||
|
@ -4366,8 +4366,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"CheckDeregisterIntervalMin": "0s",
|
"CheckDeregisterIntervalMin": "0s",
|
||||||
"CheckReapInterval": "0s",
|
"CheckReapInterval": "0s",
|
||||||
"CheckUpdateInterval": "0s",
|
"CheckUpdateInterval": "0s",
|
||||||
"Checks": [
|
"Checks": [{
|
||||||
{
|
|
||||||
"AliasNode": "",
|
"AliasNode": "",
|
||||||
"AliasService": "",
|
"AliasService": "",
|
||||||
"DeregisterCriticalServiceAfter": "0s",
|
"DeregisterCriticalServiceAfter": "0s",
|
||||||
@ -4390,8 +4389,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"TTL": "0s",
|
"TTL": "0s",
|
||||||
"Timeout": "0s",
|
"Timeout": "0s",
|
||||||
"Token": "hidden"
|
"Token": "hidden"
|
||||||
}
|
}],
|
||||||
],
|
|
||||||
"ClientAddrs": [],
|
"ClientAddrs": [],
|
||||||
"ConnectCAConfig": {},
|
"ConnectCAConfig": {},
|
||||||
"ConnectCAProvider": "",
|
"ConnectCAProvider": "",
|
||||||
@ -4476,6 +4474,9 @@ func TestSanitize(t *testing.T) {
|
|||||||
"LeaveDrainTime": "0s",
|
"LeaveDrainTime": "0s",
|
||||||
"LeaveOnTerm": false,
|
"LeaveOnTerm": false,
|
||||||
"LogLevel": "",
|
"LogLevel": "",
|
||||||
|
"LogFile": "",
|
||||||
|
"LogRotateBytes": 0,
|
||||||
|
"LogRotateDuration": "0s",
|
||||||
"NodeID": "",
|
"NodeID": "",
|
||||||
"NodeMeta": {},
|
"NodeMeta": {},
|
||||||
"NodeName": "",
|
"NodeName": "",
|
||||||
@ -4517,8 +4518,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"ServerMode": false,
|
"ServerMode": false,
|
||||||
"ServerName": "",
|
"ServerName": "",
|
||||||
"ServerPort": 0,
|
"ServerPort": 0,
|
||||||
"Services": [
|
"Services": [{
|
||||||
{
|
|
||||||
"Address": "",
|
"Address": "",
|
||||||
"Check": {
|
"Check": {
|
||||||
"AliasNode": "",
|
"AliasNode": "",
|
||||||
@ -4553,8 +4553,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"ProxyDestination": "",
|
"ProxyDestination": "",
|
||||||
"Tags": [],
|
"Tags": [],
|
||||||
"Token": "hidden"
|
"Token": "hidden"
|
||||||
}
|
}],
|
||||||
],
|
|
||||||
"SessionTTLMin": "0s",
|
"SessionTTLMin": "0s",
|
||||||
"SkipLeaveOnInt": false,
|
"SkipLeaveOnInt": false,
|
||||||
"StartJoinAddrsLAN": [],
|
"StartJoinAddrsLAN": [],
|
||||||
@ -4566,7 +4565,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"TLSMinVersion": "",
|
"TLSMinVersion": "",
|
||||||
"TLSPreferServerCipherSuites": false,
|
"TLSPreferServerCipherSuites": false,
|
||||||
"TaggedAddresses": {},
|
"TaggedAddresses": {},
|
||||||
"Telemetry":{
|
"Telemetry": {
|
||||||
"AllowedPrefixes": [],
|
"AllowedPrefixes": [],
|
||||||
"BlockedPrefixes": [],
|
"BlockedPrefixes": [],
|
||||||
"CirconusAPIApp": "",
|
"CirconusAPIApp": "",
|
||||||
@ -4604,8 +4603,7 @@ func TestSanitize(t *testing.T) {
|
|||||||
"Version": "",
|
"Version": "",
|
||||||
"VersionPrerelease": "",
|
"VersionPrerelease": "",
|
||||||
"Watches": []
|
"Watches": []
|
||||||
}`
|
}`
|
||||||
|
|
||||||
b, err := json.MarshalIndent(rt.Sanitized(), "", " ")
|
b, err := json.MarshalIndent(rt.Sanitized(), "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -190,6 +190,9 @@ func (c *cmd) run(args []string) int {
|
|||||||
LogLevel: config.LogLevel,
|
LogLevel: config.LogLevel,
|
||||||
EnableSyslog: config.EnableSyslog,
|
EnableSyslog: config.EnableSyslog,
|
||||||
SyslogFacility: config.SyslogFacility,
|
SyslogFacility: config.SyslogFacility,
|
||||||
|
LogFilePath: config.LogFile,
|
||||||
|
LogRotateDuration: config.LogRotateDuration,
|
||||||
|
LogRotateBytes: config.LogRotateBytes,
|
||||||
}
|
}
|
||||||
logFilter, logGate, logWriter, logOutput, ok := logger.Setup(logConfig, c.UI)
|
logFilter, logGate, logWriter, logOutput, ok := logger.Setup(logConfig, c.UI)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
94
logger/logfile.go
Normal file
94
logger/logfile.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
now = time.Now
|
||||||
|
)
|
||||||
|
|
||||||
|
//LogFile is used to setup a file based logger that also performs log rotation
|
||||||
|
type LogFile struct {
|
||||||
|
//Name of the log file
|
||||||
|
fileName string
|
||||||
|
|
||||||
|
//Path to the log file
|
||||||
|
logPath string
|
||||||
|
|
||||||
|
//Duration between each file rotation operation
|
||||||
|
duration time.Duration
|
||||||
|
|
||||||
|
//LastCreated represents the creation time of the latest log
|
||||||
|
LastCreated time.Time
|
||||||
|
|
||||||
|
//FileInfo is the pointer to the current file being written to
|
||||||
|
FileInfo *os.File
|
||||||
|
|
||||||
|
//MaxBytes is the maximum number of desired bytes for a log file
|
||||||
|
MaxBytes int
|
||||||
|
|
||||||
|
//BytesWritten is the number of bytes written in the current log file
|
||||||
|
BytesWritten int64
|
||||||
|
|
||||||
|
//acquire is the mutex utilized to ensure we have no concurrency issues
|
||||||
|
acquire sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogFile) openNew() error {
|
||||||
|
// Extract the file extention
|
||||||
|
fileExt := filepath.Ext(l.fileName)
|
||||||
|
// If we have no file extension we append .log
|
||||||
|
if fileExt == "" {
|
||||||
|
fileExt = ".log"
|
||||||
|
}
|
||||||
|
// Remove the file extention from the filename
|
||||||
|
fileName := strings.TrimSuffix(l.fileName, fileExt)
|
||||||
|
// New file name has the format : filename-timestamp.extension
|
||||||
|
createTime := now()
|
||||||
|
newfileName := fileName + "-" + strconv.FormatInt(createTime.UnixNano(), 10) + fileExt
|
||||||
|
newfilePath := filepath.Join(l.logPath, newfileName)
|
||||||
|
// Try creating a file. We truncate the file because we are the only authority to write the logs
|
||||||
|
filePointer, err := os.OpenFile(newfilePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 640)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
l.FileInfo = filePointer
|
||||||
|
// New file, new bytes tracker, new creation time :)
|
||||||
|
l.LastCreated = createTime
|
||||||
|
l.BytesWritten = 0
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogFile) rotate() error {
|
||||||
|
// Get the time from the last point of contact
|
||||||
|
timeElapsed := time.Since(l.LastCreated)
|
||||||
|
// Rotate if we hit the byte file limit or the time limit
|
||||||
|
if (l.BytesWritten >= int64(l.MaxBytes) && (l.MaxBytes > 0)) || timeElapsed >= l.duration {
|
||||||
|
l.FileInfo.Close()
|
||||||
|
return l.openNew()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogFile) Write(b []byte) (n int, err error) {
|
||||||
|
l.acquire.Lock()
|
||||||
|
defer l.acquire.Unlock()
|
||||||
|
//Create a new file if we have no file to write to
|
||||||
|
if l.FileInfo == nil {
|
||||||
|
if err := l.openNew(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for the last contact and rotate if necessary
|
||||||
|
if err := l.rotate(); err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
l.BytesWritten += int64(len(b))
|
||||||
|
return l.FileInfo.Write(b)
|
||||||
|
}
|
44
logger/logfile_test.go
Normal file
44
logger/logfile_test.go
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/consul/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testFileName = "Consul.log"
|
||||||
|
testDuration = 2 * time.Second
|
||||||
|
testBytes = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLogFile_timeRotation(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tempDir := testutil.TempDir(t, "LogWriterTime")
|
||||||
|
defer os.Remove(tempDir)
|
||||||
|
logFile := LogFile{fileName: testFileName, logPath: tempDir, duration: testDuration}
|
||||||
|
logFile.Write([]byte("Hello World"))
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
logFile.Write([]byte("Second File"))
|
||||||
|
want := 2
|
||||||
|
if got, _ := ioutil.ReadDir(tempDir); len(got) != want {
|
||||||
|
t.Errorf("Expected %d files, got %v file(s)", want, len(got))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLogFile_byteRotation(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
tempDir := testutil.TempDir(t, "LogWriterBytes")
|
||||||
|
defer os.Remove(tempDir)
|
||||||
|
logFile := LogFile{fileName: testFileName, logPath: tempDir, MaxBytes: testBytes, duration: 24 * time.Hour}
|
||||||
|
logFile.Write([]byte("Hello World"))
|
||||||
|
logFile.Write([]byte("Second File"))
|
||||||
|
want := 2
|
||||||
|
tempFiles, _ := ioutil.ReadDir(tempDir)
|
||||||
|
if got := tempFiles; len(got) != want {
|
||||||
|
t.Errorf("Expected %d files, got %v file(s)", want, len(got))
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ package logger
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -21,8 +22,27 @@ type Config struct {
|
|||||||
|
|
||||||
// SyslogFacility is the destination for syslog forwarding.
|
// SyslogFacility is the destination for syslog forwarding.
|
||||||
SyslogFacility string
|
SyslogFacility string
|
||||||
|
|
||||||
|
//LogFilePath is the path to write the logs to the user specified file.
|
||||||
|
LogFilePath string
|
||||||
|
|
||||||
|
//LogRotateDuration is the user specified time to rotate logs
|
||||||
|
LogRotateDuration time.Duration
|
||||||
|
|
||||||
|
//LogRotateBytes is the user specified byte limit to rotate logs
|
||||||
|
LogRotateBytes int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultRotateDuration is the default time taken by the agent to rotate logs
|
||||||
|
defaultRotateDuration = 24 * time.Hour
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
logRotateDuration time.Duration
|
||||||
|
logRotateBytes int
|
||||||
|
)
|
||||||
|
|
||||||
// Setup is used to perform setup of several logging objects:
|
// Setup is used to perform setup of several logging objects:
|
||||||
//
|
//
|
||||||
// * A LevelFilter is used to perform filtering by log level.
|
// * A LevelFilter is used to perform filtering by log level.
|
||||||
@ -76,14 +96,37 @@ func Setup(config *Config, ui cli.Ui) (*logutils.LevelFilter, *GatedWriter, *Log
|
|||||||
time.Sleep(delay)
|
time.Sleep(delay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a log writer, and wrap a logOutput around it
|
// Create a log writer, and wrap a logOutput around it
|
||||||
logWriter := NewLogWriter(512)
|
logWriter := NewLogWriter(512)
|
||||||
|
writers := []io.Writer{logFilter, logWriter}
|
||||||
|
|
||||||
var logOutput io.Writer
|
var logOutput io.Writer
|
||||||
if syslog != nil {
|
if syslog != nil {
|
||||||
logOutput = io.MultiWriter(logFilter, logWriter, syslog)
|
writers = append(writers, syslog)
|
||||||
} else {
|
|
||||||
logOutput = io.MultiWriter(logFilter, logWriter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a file logger if the user has specified the path to the log file
|
||||||
|
if config.LogFilePath != "" {
|
||||||
|
dir, fileName := filepath.Split(config.LogFilePath)
|
||||||
|
// If a path is provided but has no fileName a default is provided.
|
||||||
|
if fileName == "" {
|
||||||
|
fileName = "consul.log"
|
||||||
|
}
|
||||||
|
// Try to enter the user specified log rotation duration first
|
||||||
|
if config.LogRotateDuration != 0 {
|
||||||
|
logRotateDuration = config.LogRotateDuration
|
||||||
|
} else {
|
||||||
|
// Default to 24 hrs if no rotation period is specified
|
||||||
|
logRotateDuration = defaultRotateDuration
|
||||||
|
}
|
||||||
|
// User specified byte limit for log rotation if one is provided
|
||||||
|
if config.LogRotateBytes != 0 {
|
||||||
|
logRotateBytes = config.LogRotateBytes
|
||||||
|
}
|
||||||
|
logFile := &LogFile{fileName: fileName, logPath: dir, duration: logRotateDuration, MaxBytes: logRotateBytes}
|
||||||
|
writers = append(writers, logFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
logOutput = io.MultiWriter(writers...)
|
||||||
return logFilter, logGate, logWriter, logOutput, true
|
return logFilter, logGate, logWriter, logOutput, true
|
||||||
}
|
}
|
||||||
|
@ -225,6 +225,11 @@ will exit with an error at startup.
|
|||||||
This overrides the default port 8500. This option is very useful when deploying Consul
|
This overrides the default port 8500. This option is very useful when deploying Consul
|
||||||
to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing
|
to an environment which communicates the HTTP port through the environment e.g. PaaS like CloudFoundry, allowing
|
||||||
you to set the port directly via a Procfile.
|
you to set the port directly via a Procfile.
|
||||||
|
* <a name="_log_file"></a><a href="#_log_file">`-log-file`</a> - to redirect all the Consul agent log messages to a file. This can be specified with the complete path along with the name of the log. In case the path doesn't have the filename, the filename defaults to Consul-timestamp.log . Can be combined with <a href="#_log_rotate_bytes"> -log-rotate-bytes</a> and <a href="#_log_rotate_duration"> -log-rotate-duration </a> for a fine-grained log rotation experience.
|
||||||
|
|
||||||
|
* <a name="_log_rotate_bytes"></a><a href="#_log_rotate_bytes">`-log-rotate-bytes`</a> - to specify the number of bytes that should be written to a log before it needs to be rotated. Unless specified, there is no limit to the number of bytes that can be written to a log file.
|
||||||
|
|
||||||
|
* <a name="_log_rotate_duration"></a><a href="#_log_rotate_rotation">`-log-rotate-rotation`</a> - to specify the maximum duration a log should be written to before it needs to be rotated. Unless specified, logs are rotated on a daily basis (24 hrs).
|
||||||
|
|
||||||
* <a name="_join"></a><a href="#_join">`-join`</a> - Address of another agent
|
* <a name="_join"></a><a href="#_join">`-join`</a> - Address of another agent
|
||||||
to join upon starting up. This can be
|
to join upon starting up. This can be
|
||||||
|
Loading…
x
Reference in New Issue
Block a user