mirror of
https://github.com/caddyserver/caddy.git
synced 2025-02-05 16:48:27 +03:00
Roll all logs by default (#1379)
* Use new subdirectives and flatten rolling config * Set default rotate config * Set default rolling config (hopefully) errwhere * Make private * Flatten errors directive and remove c.IncrNest() * Don't skip first error log roller subdirective we see * Remove hadBlock * Try lumberjack import * Unname import
This commit is contained in:
parent
f32eed1912
commit
ce7d3db1be
6 changed files with 207 additions and 156 deletions
|
@ -120,12 +120,6 @@ func (d *Dispenser) NextBlock() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// IncrNest adds a level of nesting to the dispenser.
|
|
||||||
func (d *Dispenser) IncrNest() {
|
|
||||||
d.nesting++
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Val gets the text of the current token. If there is no token
|
// Val gets the text of the current token. If there is no token
|
||||||
// loaded, it returns empty string.
|
// loaded, it returns empty string.
|
||||||
func (d *Dispenser) Val() string {
|
func (d *Dispenser) Val() string {
|
||||||
|
|
|
@ -40,33 +40,20 @@ func errorsParse(c *caddy.Controller) (*ErrorHandler, error) {
|
||||||
|
|
||||||
cfg := httpserver.GetConfig(c)
|
cfg := httpserver.GetConfig(c)
|
||||||
|
|
||||||
optionalBlock := func() (bool, error) {
|
optionalBlock := func() error {
|
||||||
var hadBlock bool
|
|
||||||
|
|
||||||
for c.NextBlock() {
|
for c.NextBlock() {
|
||||||
hadBlock = true
|
|
||||||
|
|
||||||
what := c.Val()
|
what := c.Val()
|
||||||
if !c.NextArg() {
|
if !c.NextArg() {
|
||||||
return hadBlock, c.ArgErr()
|
return c.ArgErr()
|
||||||
}
|
}
|
||||||
where := c.Val()
|
where := c.Val()
|
||||||
|
|
||||||
if what == "log" {
|
if httpserver.IsLogRollerSubdirective(what) {
|
||||||
if where == "visible" {
|
var err error
|
||||||
handler.Debug = true
|
err = httpserver.ParseRoller(handler.Log.Roller, what, where)
|
||||||
} else {
|
if err != nil {
|
||||||
handler.Log.Output = where
|
return err
|
||||||
if c.NextArg() {
|
|
||||||
if c.Val() == "{" {
|
|
||||||
c.IncrNest()
|
|
||||||
logRoller, err := httpserver.ParseRoller(c)
|
|
||||||
if err != nil {
|
|
||||||
return hadBlock, err
|
|
||||||
}
|
|
||||||
handler.Log.Roller = logRoller
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Error page; ensure it exists
|
// Error page; ensure it exists
|
||||||
|
@ -82,24 +69,24 @@ func errorsParse(c *caddy.Controller) (*ErrorHandler, error) {
|
||||||
|
|
||||||
if what == "*" {
|
if what == "*" {
|
||||||
if handler.GenericErrorPage != "" {
|
if handler.GenericErrorPage != "" {
|
||||||
return hadBlock, c.Errf("Duplicate status code entry: %s", what)
|
return c.Errf("Duplicate status code entry: %s", what)
|
||||||
}
|
}
|
||||||
handler.GenericErrorPage = where
|
handler.GenericErrorPage = where
|
||||||
} else {
|
} else {
|
||||||
whatInt, err := strconv.Atoi(what)
|
whatInt, err := strconv.Atoi(what)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return hadBlock, c.Err("Expecting a numeric status code or '*', got '" + what + "'")
|
return c.Err("Expecting a numeric status code or '*', got '" + what + "'")
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := handler.ErrorPages[whatInt]; exists {
|
if _, exists := handler.ErrorPages[whatInt]; exists {
|
||||||
return hadBlock, c.Errf("Duplicate status code entry: %s", what)
|
return c.Errf("Duplicate status code entry: %s", what)
|
||||||
}
|
}
|
||||||
|
|
||||||
handler.ErrorPages[whatInt] = where
|
handler.ErrorPages[whatInt] = where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return hadBlock, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for c.Next() {
|
for c.Next() {
|
||||||
|
@ -107,21 +94,23 @@ func errorsParse(c *caddy.Controller) (*ErrorHandler, error) {
|
||||||
if c.Val() == "}" {
|
if c.Val() == "}" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Configuration may be in a block
|
|
||||||
hadBlock, err := optionalBlock()
|
args := c.RemainingArgs()
|
||||||
if err != nil {
|
|
||||||
return handler, err
|
if len(args) == 1 {
|
||||||
|
switch args[0] {
|
||||||
|
case "visible":
|
||||||
|
handler.Debug = true
|
||||||
|
default:
|
||||||
|
handler.Log.Output = args[0]
|
||||||
|
handler.Log.Roller = httpserver.DefaultLogRoller()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, the only argument would be an error log file name or 'visible'
|
// Configuration may be in a block
|
||||||
if !hadBlock {
|
err := optionalBlock()
|
||||||
if c.NextArg() {
|
if err != nil {
|
||||||
if c.Val() == "visible" {
|
return handler, err
|
||||||
handler.Debug = true
|
|
||||||
} else {
|
|
||||||
handler.Log.Output = c.Val()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,62 +62,70 @@ func TestErrorsParse(t *testing.T) {
|
||||||
}},
|
}},
|
||||||
{`errors errors.txt`, false, ErrorHandler{
|
{`errors errors.txt`, false, ErrorHandler{
|
||||||
ErrorPages: map[int]string{},
|
ErrorPages: map[int]string{},
|
||||||
Log: &httpserver.Logger{Output: "errors.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "errors.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
}},
|
}},
|
||||||
{`errors visible`, false, ErrorHandler{
|
{`errors visible`, false, ErrorHandler{
|
||||||
ErrorPages: map[int]string{},
|
ErrorPages: map[int]string{},
|
||||||
Debug: true,
|
Debug: true,
|
||||||
Log: &httpserver.Logger{},
|
Log: &httpserver.Logger{},
|
||||||
}},
|
}},
|
||||||
{`errors { log visible }`, false, ErrorHandler{
|
{`errors errors.txt {
|
||||||
ErrorPages: map[int]string{},
|
404 404.html
|
||||||
Debug: true,
|
500 500.html
|
||||||
Log: &httpserver.Logger{},
|
}`, false, ErrorHandler{
|
||||||
}},
|
|
||||||
{`errors { log errors.txt
|
|
||||||
404 404.html
|
|
||||||
500 500.html
|
|
||||||
}`, false, ErrorHandler{
|
|
||||||
ErrorPages: map[int]string{
|
ErrorPages: map[int]string{
|
||||||
404: "404.html",
|
404: "404.html",
|
||||||
500: "500.html",
|
500: "500.html",
|
||||||
},
|
},
|
||||||
Log: &httpserver.Logger{Output: "errors.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "errors.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
}},
|
}},
|
||||||
{`errors { log errors.txt { size 2 age 10 keep 3 } }`, false, ErrorHandler{
|
{`errors errors.txt { rotate_size 2 rotate_age 10 rotate_keep 3 }`, false, ErrorHandler{
|
||||||
ErrorPages: map[int]string{},
|
ErrorPages: map[int]string{},
|
||||||
Log: &httpserver.Logger{Output: "errors.txt", Roller: &httpserver.LogRoller{
|
Log: &httpserver.Logger{
|
||||||
MaxSize: 2,
|
Output: "errors.txt", Roller: &httpserver.LogRoller{
|
||||||
MaxAge: 10,
|
MaxSize: 2,
|
||||||
MaxBackups: 3,
|
MaxAge: 10,
|
||||||
LocalTime: true,
|
MaxBackups: 3,
|
||||||
}}},
|
LocalTime: true,
|
||||||
},
|
},
|
||||||
{`errors { log errors.txt {
|
},
|
||||||
size 3
|
}},
|
||||||
age 11
|
{`errors errors.txt {
|
||||||
keep 5
|
rotate_size 3
|
||||||
}
|
rotate_age 11
|
||||||
404 404.html
|
rotate_keep 5
|
||||||
503 503.html
|
404 404.html
|
||||||
}`, false, ErrorHandler{
|
503 503.html
|
||||||
|
}`, false, ErrorHandler{
|
||||||
ErrorPages: map[int]string{
|
ErrorPages: map[int]string{
|
||||||
404: "404.html",
|
404: "404.html",
|
||||||
503: "503.html",
|
503: "503.html",
|
||||||
},
|
},
|
||||||
Log: &httpserver.Logger{Output: "errors.txt", Roller: &httpserver.LogRoller{
|
Log: &httpserver.Logger{
|
||||||
MaxSize: 3,
|
Output: "errors.txt",
|
||||||
MaxAge: 11,
|
Roller: &httpserver.LogRoller{
|
||||||
MaxBackups: 5,
|
MaxSize: 3,
|
||||||
LocalTime: true,
|
MaxAge: 11,
|
||||||
|
MaxBackups: 5,
|
||||||
|
LocalTime: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{`errors errors.txt {
|
||||||
|
* generic_error.html
|
||||||
|
404 404.html
|
||||||
|
503 503.html
|
||||||
|
}`, false, ErrorHandler{
|
||||||
|
Log: &httpserver.Logger{
|
||||||
|
Output: "errors.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
},
|
},
|
||||||
}}},
|
|
||||||
{`errors { log errors.txt
|
|
||||||
* generic_error.html
|
|
||||||
404 404.html
|
|
||||||
503 503.html
|
|
||||||
}`, false, ErrorHandler{
|
|
||||||
Log: &httpserver.Logger{Output: "errors.txt"},
|
|
||||||
GenericErrorPage: "generic_error.html",
|
GenericErrorPage: "generic_error.html",
|
||||||
ErrorPages: map[int]string{
|
ErrorPages: map[int]string{
|
||||||
404: "404.html",
|
404: "404.html",
|
||||||
|
@ -158,7 +166,7 @@ func TestErrorsParse(t *testing.T) {
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(actualErrorsRule, &test.expectedErrorHandler) {
|
if !reflect.DeepEqual(actualErrorsRule, &test.expectedErrorHandler) {
|
||||||
t.Errorf("Test %d expect %v, but got %v", i,
|
t.Errorf("Test %d expect %v, but got %v", i,
|
||||||
actualErrorsRule, test.expectedErrorHandler)
|
test.expectedErrorHandler, actualErrorsRule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/mholt/caddy"
|
|
||||||
|
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
"gopkg.in/natefinch/lumberjack.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,40 +44,57 @@ func (l LogRoller) GetLogWriter() io.Writer {
|
||||||
return lj
|
return lj
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseRoller parses roller contents out of c.
|
// IsLogRollerSubdirective is true if the subdirective is for the log roller.
|
||||||
func ParseRoller(c *caddy.Controller) (*LogRoller, error) {
|
func IsLogRollerSubdirective(subdir string) bool {
|
||||||
var size, age, keep int
|
return subdir == directiveRotateSize ||
|
||||||
// This is kind of a hack to support nested blocks:
|
subdir == directiveRotateAge ||
|
||||||
// As we are already in a block: either log or errors,
|
subdir == directiveRotateKeep
|
||||||
// c.nesting > 0 but, as soon as c meets a }, it thinks
|
|
||||||
// the block is over and return false for c.NextBlock.
|
|
||||||
for c.NextBlock() {
|
|
||||||
what := c.Val()
|
|
||||||
if !c.NextArg() {
|
|
||||||
return nil, c.ArgErr()
|
|
||||||
}
|
|
||||||
value := c.Val()
|
|
||||||
var err error
|
|
||||||
switch what {
|
|
||||||
case "size":
|
|
||||||
size, err = strconv.Atoi(value)
|
|
||||||
case "age":
|
|
||||||
age, err = strconv.Atoi(value)
|
|
||||||
case "keep":
|
|
||||||
keep, err = strconv.Atoi(value)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &LogRoller{
|
|
||||||
MaxSize: size,
|
|
||||||
MaxAge: age,
|
|
||||||
MaxBackups: keep,
|
|
||||||
LocalTime: true,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseRoller parses roller contents out of c.
|
||||||
|
func ParseRoller(l *LogRoller, what string, where string) error {
|
||||||
|
if l == nil {
|
||||||
|
l = DefaultLogRoller()
|
||||||
|
}
|
||||||
|
var value int
|
||||||
|
var err error
|
||||||
|
value, err = strconv.Atoi(where)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
switch what {
|
||||||
|
case directiveRotateSize:
|
||||||
|
l.MaxSize = value
|
||||||
|
case directiveRotateAge:
|
||||||
|
l.MaxAge = value
|
||||||
|
case directiveRotateKeep:
|
||||||
|
l.MaxBackups = value
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultLogRoller will roll logs by default.
|
||||||
|
func DefaultLogRoller() *LogRoller {
|
||||||
|
return &LogRoller{
|
||||||
|
MaxSize: defaultRotateSize,
|
||||||
|
MaxAge: defaultRotateAge,
|
||||||
|
MaxBackups: defaultRotateKeep,
|
||||||
|
LocalTime: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// defaultRotateSize is 100 MB.
|
||||||
|
defaultRotateSize = 100
|
||||||
|
// defaultRotateAge is 14 days.
|
||||||
|
defaultRotateAge = 14
|
||||||
|
// defaultRotateKeep is 10 files.
|
||||||
|
defaultRotateKeep = 10
|
||||||
|
directiveRotateSize = "rotate_size"
|
||||||
|
directiveRotateAge = "rotate_age"
|
||||||
|
directiveRotateKeep = "rotate_keep"
|
||||||
|
)
|
||||||
|
|
||||||
// lumberjacks maps log filenames to the logger
|
// lumberjacks maps log filenames to the logger
|
||||||
// that is being used to keep them rolled/maintained.
|
// that is being used to keep them rolled/maintained.
|
||||||
var lumberjacks = make(map[string]*lumberjack.Logger)
|
var lumberjacks = make(map[string]*lumberjack.Logger)
|
||||||
|
|
|
@ -32,25 +32,24 @@ func logParse(c *caddy.Controller) ([]*Rule, error) {
|
||||||
args := c.RemainingArgs()
|
args := c.RemainingArgs()
|
||||||
|
|
||||||
var logRoller *httpserver.LogRoller
|
var logRoller *httpserver.LogRoller
|
||||||
if c.NextBlock() {
|
logRoller = httpserver.DefaultLogRoller()
|
||||||
if c.Val() == "rotate" {
|
|
||||||
if c.NextArg() {
|
for c.NextBlock() {
|
||||||
if c.Val() == "{" {
|
what := c.Val()
|
||||||
var err error
|
if !c.NextArg() {
|
||||||
logRoller, err = httpserver.ParseRoller(c)
|
return nil, c.ArgErr()
|
||||||
if err != nil {
|
}
|
||||||
return nil, err
|
where := c.Val()
|
||||||
}
|
|
||||||
// This part doesn't allow having something after the rotate block
|
if httpserver.IsLogRollerSubdirective(what) {
|
||||||
if c.Next() {
|
var err error
|
||||||
if c.Val() != "}" {
|
err = httpserver.ParseRoller(logRoller, what, where)
|
||||||
return nil, c.ArgErr()
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
// Nothing specified; use defaults
|
// Nothing specified; use defaults
|
||||||
rules = appendEntry(rules, "/", &Entry{
|
rules = appendEntry(rules, "/", &Entry{
|
||||||
|
|
|
@ -32,7 +32,10 @@ func TestSetup(t *testing.T) {
|
||||||
t.Errorf("Expected / as the default PathScope")
|
t.Errorf("Expected / as the default PathScope")
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedLogger := &httpserver.Logger{Output: DefaultLogFilename}
|
expectedLogger := &httpserver.Logger{
|
||||||
|
Output: DefaultLogFilename,
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(myHandler.Rules[0].Entries[0].Log, expectedLogger) {
|
if !reflect.DeepEqual(myHandler.Rules[0].Entries[0].Log, expectedLogger) {
|
||||||
t.Errorf("Expected %v as the default Log, got: %v", expectedLogger, myHandler.Rules[0].Entries[0].Log)
|
t.Errorf("Expected %v as the default Log, got: %v", expectedLogger, myHandler.Rules[0].Entries[0].Log)
|
||||||
|
@ -40,7 +43,6 @@ func TestSetup(t *testing.T) {
|
||||||
if myHandler.Rules[0].Entries[0].Format != DefaultLogFormat {
|
if myHandler.Rules[0].Entries[0].Format != DefaultLogFormat {
|
||||||
t.Errorf("Expected %s as the default Log Format", DefaultLogFormat)
|
t.Errorf("Expected %s as the default Log Format", DefaultLogFormat)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !httpserver.SameNext(myHandler.Next, httpserver.EmptyNext) {
|
if !httpserver.SameNext(myHandler.Next, httpserver.EmptyNext) {
|
||||||
t.Error("'Next' field of handler was not set properly")
|
t.Error("'Next' field of handler was not set properly")
|
||||||
}
|
}
|
||||||
|
@ -55,56 +57,80 @@ func TestLogParse(t *testing.T) {
|
||||||
{`log`, false, []Rule{{
|
{`log`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: DefaultLogFilename},
|
Log: &httpserver.Logger{
|
||||||
|
Output: DefaultLogFilename,
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log log.txt`, false, []Rule{{
|
{`log log.txt`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log syslog://127.0.0.1:5000`, false, []Rule{{
|
{`log syslog://127.0.0.1:5000`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "syslog://127.0.0.1:5000"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "syslog://127.0.0.1:5000",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log syslog+tcp://127.0.0.1:5000`, false, []Rule{{
|
{`log syslog+tcp://127.0.0.1:5000`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "syslog+tcp://127.0.0.1:5000"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "syslog+tcp://127.0.0.1:5000",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log /api log.txt`, false, []Rule{{
|
{`log /api log.txt`, false, []Rule{{
|
||||||
PathScope: "/api",
|
PathScope: "/api",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log /serve stdout`, false, []Rule{{
|
{`log /serve stdout`, false, []Rule{{
|
||||||
PathScope: "/serve",
|
PathScope: "/serve",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "stdout"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "stdout",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log /myapi log.txt {common}`, false, []Rule{{
|
{`log /myapi log.txt {common}`, false, []Rule{{
|
||||||
PathScope: "/myapi",
|
PathScope: "/myapi",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: CommonLogFormat,
|
Format: CommonLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log /test accesslog.txt {combined}`, false, []Rule{{
|
{`log /test accesslog.txt {combined}`, false, []Rule{{
|
||||||
PathScope: "/test",
|
PathScope: "/test",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "accesslog.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "accesslog.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: CombinedLogFormat,
|
Format: CombinedLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
|
@ -112,13 +138,19 @@ func TestLogParse(t *testing.T) {
|
||||||
log /api2 accesslog.txt {combined}`, false, []Rule{{
|
log /api2 accesslog.txt {combined}`, false, []Rule{{
|
||||||
PathScope: "/api1",
|
PathScope: "/api1",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
PathScope: "/api2",
|
PathScope: "/api2",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "accesslog.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "accesslog.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: CombinedLogFormat,
|
Format: CombinedLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
|
@ -126,25 +158,33 @@ func TestLogParse(t *testing.T) {
|
||||||
log /api4 log.txt {when}`, false, []Rule{{
|
log /api4 log.txt {when}`, false, []Rule{{
|
||||||
PathScope: "/api3",
|
PathScope: "/api3",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "stdout"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "stdout",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: "{host}",
|
Format: "{host}",
|
||||||
}},
|
}},
|
||||||
}, {
|
}, {
|
||||||
PathScope: "/api4",
|
PathScope: "/api4",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: "{when}",
|
Format: "{when}",
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
{`log access.log { rotate { size 2 age 10 keep 3 } }`, false, []Rule{{
|
{`log access.log { rotate_size 2 rotate_age 10 rotate_keep 3 }`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "access.log", Roller: &httpserver.LogRoller{
|
Log: &httpserver.Logger{
|
||||||
MaxSize: 2,
|
Output: "access.log",
|
||||||
MaxAge: 10,
|
Roller: &httpserver.LogRoller{
|
||||||
MaxBackups: 3,
|
MaxSize: 2,
|
||||||
LocalTime: true,
|
MaxAge: 10,
|
||||||
}},
|
MaxBackups: 3,
|
||||||
|
LocalTime: true,
|
||||||
|
}},
|
||||||
Format: DefaultLogFormat,
|
Format: DefaultLogFormat,
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
|
@ -152,10 +192,16 @@ func TestLogParse(t *testing.T) {
|
||||||
log / log.txt {when}`, false, []Rule{{
|
log / log.txt {when}`, false, []Rule{{
|
||||||
PathScope: "/",
|
PathScope: "/",
|
||||||
Entries: []*Entry{{
|
Entries: []*Entry{{
|
||||||
Log: &httpserver.Logger{Output: "stdout"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "stdout",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: "{host}",
|
Format: "{host}",
|
||||||
}, {
|
}, {
|
||||||
Log: &httpserver.Logger{Output: "log.txt"},
|
Log: &httpserver.Logger{
|
||||||
|
Output: "log.txt",
|
||||||
|
Roller: httpserver.DefaultLogRoller(),
|
||||||
|
},
|
||||||
Format: "{when}",
|
Format: "{when}",
|
||||||
}},
|
}},
|
||||||
}}},
|
}}},
|
||||||
|
|
Loading…
Reference in a new issue