mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-10-31 10:37:24 -04: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
					
				| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user