mirror of
https://github.com/caddyserver/caddy.git
synced 2024-11-30 04:33:48 +08:00
a798e0c951
- Server types no longer need to store their own contexts; they are stored on the caddy.Instance, which means each context will be properly GC'ed when the instance is stopped. Server types should use type assertions to convert from caddy.Context to their concrete context type when they need to use it. - Pass the entire context into httpserver.GetConfig instead of only the Key field. - caddy.NewTestController now requires a server type string so it can create a controller with the proper concrete context associated with that server type. Tests still need more attention so that we can test the proper creation of startup functions, etc.
132 lines
2.8 KiB
Go
132 lines
2.8 KiB
Go
package log
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"os"
|
|
|
|
"github.com/hashicorp/go-syslog"
|
|
"github.com/mholt/caddy"
|
|
"github.com/mholt/caddy/caddyhttp/httpserver"
|
|
)
|
|
|
|
// setup sets up the logging middleware.
|
|
func setup(c *caddy.Controller) error {
|
|
rules, err := logParse(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Open the log files for writing when the server starts
|
|
c.OnStartup(func() error {
|
|
for i := 0; i < len(rules); i++ {
|
|
var err error
|
|
var writer io.Writer
|
|
|
|
if rules[i].OutputFile == "stdout" {
|
|
writer = os.Stdout
|
|
} else if rules[i].OutputFile == "stderr" {
|
|
writer = os.Stderr
|
|
} else if rules[i].OutputFile == "syslog" {
|
|
writer, err = gsyslog.NewLogger(gsyslog.LOG_INFO, "LOCAL0", "caddy")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
} else {
|
|
var file *os.File
|
|
file, err = os.OpenFile(rules[i].OutputFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if rules[i].Roller != nil {
|
|
file.Close()
|
|
rules[i].Roller.Filename = rules[i].OutputFile
|
|
writer = rules[i].Roller.GetLogWriter()
|
|
} else {
|
|
writer = file
|
|
}
|
|
}
|
|
|
|
rules[i].Log = log.New(writer, "", 0)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
|
|
return Logger{Next: next, Rules: rules, ErrorFunc: httpserver.DefaultErrorFunc}
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func logParse(c *caddy.Controller) ([]Rule, error) {
|
|
var rules []Rule
|
|
|
|
for c.Next() {
|
|
args := c.RemainingArgs()
|
|
|
|
var logRoller *httpserver.LogRoller
|
|
if c.NextBlock() {
|
|
if c.Val() == "rotate" {
|
|
if c.NextArg() {
|
|
if c.Val() == "{" {
|
|
var err error
|
|
logRoller, err = httpserver.ParseRoller(c)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// This part doesn't allow having something after the rotate block
|
|
if c.Next() {
|
|
if c.Val() != "}" {
|
|
return nil, c.ArgErr()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if len(args) == 0 {
|
|
// Nothing specified; use defaults
|
|
rules = append(rules, Rule{
|
|
PathScope: "/",
|
|
OutputFile: DefaultLogFilename,
|
|
Format: DefaultLogFormat,
|
|
Roller: logRoller,
|
|
})
|
|
} else if len(args) == 1 {
|
|
// Only an output file specified
|
|
rules = append(rules, Rule{
|
|
PathScope: "/",
|
|
OutputFile: args[0],
|
|
Format: DefaultLogFormat,
|
|
Roller: logRoller,
|
|
})
|
|
} else {
|
|
// Path scope, output file, and maybe a format specified
|
|
|
|
format := DefaultLogFormat
|
|
|
|
if len(args) > 2 {
|
|
switch args[2] {
|
|
case "{common}":
|
|
format = CommonLogFormat
|
|
case "{combined}":
|
|
format = CombinedLogFormat
|
|
default:
|
|
format = args[2]
|
|
}
|
|
}
|
|
|
|
rules = append(rules, Rule{
|
|
PathScope: args[0],
|
|
OutputFile: args[1],
|
|
Format: format,
|
|
Roller: logRoller,
|
|
})
|
|
}
|
|
}
|
|
|
|
return rules, nil
|
|
}
|