mirror of
				https://github.com/caddyserver/caddy.git
				synced 2025-11-03 19:17:29 -05:00 
			
		
		
		
	I am not a lawyer, but according to the appendix of the license, these boilerplate notices should be included with every source file.
		
			
				
	
	
		
			139 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			139 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2015 Light Code Labs, LLC
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
package httpserver
 | 
						|
 | 
						|
import (
 | 
						|
	"errors"
 | 
						|
	"io"
 | 
						|
	"path/filepath"
 | 
						|
	"strconv"
 | 
						|
 | 
						|
	"gopkg.in/natefinch/lumberjack.v2"
 | 
						|
)
 | 
						|
 | 
						|
// LogRoller implements a type that provides a rolling logger.
 | 
						|
type LogRoller struct {
 | 
						|
	Filename   string
 | 
						|
	MaxSize    int
 | 
						|
	MaxAge     int
 | 
						|
	MaxBackups int
 | 
						|
	Compress   bool
 | 
						|
	LocalTime  bool
 | 
						|
}
 | 
						|
 | 
						|
// GetLogWriter returns an io.Writer that writes to a rolling logger.
 | 
						|
// This should be called only from the main goroutine (like during
 | 
						|
// server setup) because this method is not thread-safe; it is careful
 | 
						|
// to create only one log writer per log file, even if the log file
 | 
						|
// is shared by different sites or middlewares. This ensures that
 | 
						|
// rolling is synchronized, since a process (or multiple processes)
 | 
						|
// should not create more than one roller on the same file at the
 | 
						|
// same time. See issue #1363.
 | 
						|
func (l LogRoller) GetLogWriter() io.Writer {
 | 
						|
	absPath, err := filepath.Abs(l.Filename)
 | 
						|
	if err != nil {
 | 
						|
		absPath = l.Filename // oh well, hopefully they're consistent in how they specify the filename
 | 
						|
	}
 | 
						|
	lj, has := lumberjacks[absPath]
 | 
						|
	if !has {
 | 
						|
		lj = &lumberjack.Logger{
 | 
						|
			Filename:   l.Filename,
 | 
						|
			MaxSize:    l.MaxSize,
 | 
						|
			MaxAge:     l.MaxAge,
 | 
						|
			MaxBackups: l.MaxBackups,
 | 
						|
			Compress:   l.Compress,
 | 
						|
			LocalTime:  l.LocalTime,
 | 
						|
		}
 | 
						|
		lumberjacks[absPath] = lj
 | 
						|
	}
 | 
						|
	return lj
 | 
						|
}
 | 
						|
 | 
						|
// IsLogRollerSubdirective is true if the subdirective is for the log roller.
 | 
						|
func IsLogRollerSubdirective(subdir string) bool {
 | 
						|
	return subdir == directiveRotateSize ||
 | 
						|
		subdir == directiveRotateAge ||
 | 
						|
		subdir == directiveRotateKeep ||
 | 
						|
		subdir == directiveRotateCompress
 | 
						|
}
 | 
						|
 | 
						|
var invalidRollerParameterErr = errors.New("invalid roller parameter")
 | 
						|
 | 
						|
// ParseRoller parses roller contents out of c.
 | 
						|
func ParseRoller(l *LogRoller, what string, where ...string) error {
 | 
						|
	if l == nil {
 | 
						|
		l = DefaultLogRoller()
 | 
						|
	}
 | 
						|
 | 
						|
	// rotate_compress doesn't accept any parameters.
 | 
						|
	// others only accept one parameter
 | 
						|
	if (what == directiveRotateCompress && len(where) != 0) ||
 | 
						|
		(what != directiveRotateCompress && len(where) != 1) {
 | 
						|
		return invalidRollerParameterErr
 | 
						|
	}
 | 
						|
 | 
						|
	var (
 | 
						|
		value int
 | 
						|
		err   error
 | 
						|
	)
 | 
						|
	if what != directiveRotateCompress {
 | 
						|
		value, err = strconv.Atoi(where[0])
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	switch what {
 | 
						|
	case directiveRotateSize:
 | 
						|
		l.MaxSize = value
 | 
						|
	case directiveRotateAge:
 | 
						|
		l.MaxAge = value
 | 
						|
	case directiveRotateKeep:
 | 
						|
		l.MaxBackups = value
 | 
						|
	case directiveRotateCompress:
 | 
						|
		l.Compress = true
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
// DefaultLogRoller will roll logs by default.
 | 
						|
func DefaultLogRoller() *LogRoller {
 | 
						|
	return &LogRoller{
 | 
						|
		MaxSize:    defaultRotateSize,
 | 
						|
		MaxAge:     defaultRotateAge,
 | 
						|
		MaxBackups: defaultRotateKeep,
 | 
						|
		Compress:   false,
 | 
						|
		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"
 | 
						|
	directiveRotateCompress = "rotate_compress"
 | 
						|
)
 | 
						|
 | 
						|
// lumberjacks maps log filenames to the logger
 | 
						|
// that is being used to keep them rolled/maintained.
 | 
						|
var lumberjacks = make(map[string]*lumberjack.Logger)
 |