Add log file close and reopen on receipt of SIGUSR1
This commit is contained in:
parent
64b8fc52c3
commit
4e5fcac9cb
12 changed files with 343 additions and 25 deletions
|
@ -78,14 +78,7 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
|||
for i, line := range lines {
|
||||
if len(line) > 0 {
|
||||
count++
|
||||
tokens, err := shellwords.Parse(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(tokens, checker.HasLen, 14)
|
||||
c.Assert(tokens[6], checker.Matches, `^\d{3}$`)
|
||||
c.Assert(tokens[10], checker.Equals, fmt.Sprintf("%d", i+1))
|
||||
c.Assert(tokens[11], checker.HasPrefix, "frontend")
|
||||
c.Assert(tokens[12], checker.HasPrefix, "http://127.0.0.1:808")
|
||||
c.Assert(tokens[13], checker.Matches, `^\d+ms$`)
|
||||
CheckAccessLogFormat(c, line, i)
|
||||
}
|
||||
}
|
||||
c.Assert(count, checker.GreaterOrEqualThan, 3)
|
||||
|
@ -99,6 +92,17 @@ func (s *AccessLogSuite) TestAccessLog(c *check.C) {
|
|||
}
|
||||
}
|
||||
|
||||
func CheckAccessLogFormat(c *check.C, line string, i int) {
|
||||
tokens, err := shellwords.Parse(line)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(tokens, checker.HasLen, 14)
|
||||
c.Assert(tokens[6], checker.Matches, `^\d{3}$`)
|
||||
c.Assert(tokens[10], checker.Equals, fmt.Sprintf("%d", i+1))
|
||||
c.Assert(tokens[11], checker.HasPrefix, "frontend")
|
||||
c.Assert(tokens[12], checker.HasPrefix, "http://127.0.0.1:808")
|
||||
c.Assert(tokens[13], checker.Matches, `^\d+ms$`)
|
||||
}
|
||||
|
||||
func startAccessLogServer(port int) (ts *httptest.Server) {
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
fmt.Fprintf(w, "Received query %s!\n", r.URL.Path[1:])
|
||||
|
|
34
integration/fixtures/log_rotation_config.toml
Normal file
34
integration/fixtures/log_rotation_config.toml
Normal file
|
@ -0,0 +1,34 @@
|
|||
################################################################
|
||||
# Global configuration
|
||||
################################################################
|
||||
traefikLogsFile = "traefik.log"
|
||||
accessLogsFile = "access.log"
|
||||
logLevel = "ERROR"
|
||||
defaultEntryPoints = ["http"]
|
||||
[entryPoints]
|
||||
[entryPoints.http]
|
||||
address = ":8000"
|
||||
|
||||
################################################################
|
||||
# Web configuration backend
|
||||
################################################################
|
||||
[web]
|
||||
address = ":7888"
|
||||
|
||||
################################################################
|
||||
# File configuration backend
|
||||
################################################################
|
||||
[file]
|
||||
|
||||
################################################################
|
||||
# rules
|
||||
################################################################
|
||||
[backends]
|
||||
[backends.backend1]
|
||||
[backends.backend1.servers.server1]
|
||||
url = "http://127.0.0.1:8081"
|
||||
[frontends]
|
||||
[frontends.frontend1]
|
||||
backend = "backend1"
|
||||
[frontends.frontend1.routes.test_1]
|
||||
rule = "Path: /test1"
|
11
integration/fixtures/traefik_log_config.toml
Normal file
11
integration/fixtures/traefik_log_config.toml
Normal file
|
@ -0,0 +1,11 @@
|
|||
################################################################
|
||||
# Global configuration
|
||||
################################################################
|
||||
traefikLogsFile = "traefik.log"
|
||||
accessLogsFile = "access.log"
|
||||
logLevel = "DEBUG"
|
||||
checkNewVersion = false
|
||||
defaultEntryPoints = ["http"]
|
||||
[entryPoints]
|
||||
[entryPoints.http]
|
||||
address = ":8000"
|
|
@ -40,6 +40,7 @@ func init() {
|
|||
check.Suite(&ErrorPagesSuite{})
|
||||
check.Suite(&WebsocketSuite{})
|
||||
check.Suite(&GRPCSuite{})
|
||||
check.Suite(&LogRotationSuite{})
|
||||
}
|
||||
|
||||
var traefikBinary = "../dist/traefik"
|
||||
|
|
141
integration/log_rotation_test.go
Normal file
141
integration/log_rotation_test.go
Normal file
|
@ -0,0 +1,141 @@
|
|||
// +build !windows
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containous/traefik/integration/try"
|
||||
"github.com/go-check/check"
|
||||
checker "github.com/vdemeester/shakers"
|
||||
)
|
||||
|
||||
// Log rotation integration test suite
|
||||
type LogRotationSuite struct{ BaseSuite }
|
||||
|
||||
func (s *LogRotationSuite) TestAccessLogRotation(c *check.C) {
|
||||
// Start Traefik
|
||||
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/access_log_config.toml"))
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
defer os.Remove(traefikTestAccessLogFile)
|
||||
defer os.Remove(traefikTestLogFile)
|
||||
|
||||
// Verify Traefik started ok
|
||||
verifyEmptyErrorLog(c, "traefik.log")
|
||||
|
||||
// Start test servers
|
||||
ts1 := startAccessLogServer(8081)
|
||||
defer ts1.Close()
|
||||
|
||||
// Allow time to startup
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Make some requests
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test1", 500*time.Millisecond)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Rename access log
|
||||
err = os.Rename(traefikTestAccessLogFile, traefikTestAccessLogFile+".rotated")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// in the midst of the requests, issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// continue issuing requests
|
||||
_, err = http.Get("http://127.0.0.1:8000/test1")
|
||||
c.Assert(err, checker.IsNil)
|
||||
_, err = http.Get("http://127.0.0.1:8000/test1")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Verify access.log.rotated output as expected
|
||||
lineCount := verifyLogLines(c, traefikTestAccessLogFile+".rotated", 0, true)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 1)
|
||||
|
||||
// Verify access.log output as expected
|
||||
lineCount = verifyLogLines(c, traefikTestAccessLogFile, lineCount, true)
|
||||
c.Assert(lineCount, checker.Equals, 3)
|
||||
|
||||
verifyEmptyErrorLog(c, traefikTestLogFile)
|
||||
}
|
||||
|
||||
func (s *LogRotationSuite) TestTraefikLogRotation(c *check.C) {
|
||||
// Start Traefik
|
||||
cmd, _ := s.cmdTraefik(withConfigFile("fixtures/traefik_log_config.toml"))
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer cmd.Process.Kill()
|
||||
defer os.Remove(traefikTestAccessLogFile)
|
||||
defer os.Remove(traefikTestLogFile)
|
||||
|
||||
// Ensure Traefik has started
|
||||
err = try.GetRequest("http://127.0.0.1:8000/test1", 500*time.Millisecond)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Rename traefik log
|
||||
err = os.Rename(traefikTestLogFile, traefikTestLogFile+".rotated")
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// issue SIGUSR1 signal to server process
|
||||
err = cmd.Process.Signal(syscall.SIGUSR1)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
err = cmd.Process.Signal(syscall.SIGTERM)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Allow time for switch to be processed
|
||||
err = try.Do(3*time.Second, func() error {
|
||||
_, err = os.Stat(traefikTestLogFile)
|
||||
return err
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// we have at least 6 lines in traefik.log.rotated
|
||||
lineCount := verifyLogLines(c, traefikTestLogFile+".rotated", 0, false)
|
||||
|
||||
// GreaterOrEqualThan used to ensure test doesn't break
|
||||
// If more log entries are output on startup
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 6)
|
||||
|
||||
//Verify traefik.log output as expected
|
||||
lineCount = verifyLogLines(c, traefikTestLogFile, lineCount, false)
|
||||
c.Assert(lineCount, checker.GreaterOrEqualThan, 7)
|
||||
}
|
||||
|
||||
func verifyEmptyErrorLog(c *check.C, name string) {
|
||||
err := try.Do(5*time.Second, func() error {
|
||||
traefikLog, e2 := ioutil.ReadFile(name)
|
||||
if e2 != nil {
|
||||
return e2
|
||||
}
|
||||
c.Assert(traefikLog, checker.HasLen, 0)
|
||||
return nil
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func verifyLogLines(c *check.C, fileName string, countInit int, accessLog bool) int {
|
||||
rotated, err := os.Open(fileName)
|
||||
c.Assert(err, checker.IsNil)
|
||||
rotatedLog := bufio.NewScanner(rotated)
|
||||
count := countInit
|
||||
for rotatedLog.Scan() {
|
||||
line := rotatedLog.Text()
|
||||
c.Log(line)
|
||||
if accessLog {
|
||||
if len(line) > 0 {
|
||||
CheckAccessLogFormat(c, line, count)
|
||||
}
|
||||
}
|
||||
count++
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue