github.com/tendermint/tmlibs@v0.9.0/autofile/cmd/logjack.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"strconv"
     9  	"strings"
    10  
    11  	auto "github.com/tendermint/tmlibs/autofile"
    12  	cmn "github.com/tendermint/tmlibs/common"
    13  )
    14  
    15  const Version = "0.0.1"
    16  const sleepSeconds = 1      // Every second
    17  const readBufferSize = 1024 // 1KB at a time
    18  
    19  // Parse command-line options
    20  func parseFlags() (headPath string, chopSize int64, limitSize int64, version bool) {
    21  	var flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
    22  	var chopSizeStr, limitSizeStr string
    23  	flagSet.StringVar(&headPath, "head", "logjack.out", "Destination (head) file.")
    24  	flagSet.StringVar(&chopSizeStr, "chop", "100M", "Move file if greater than this")
    25  	flagSet.StringVar(&limitSizeStr, "limit", "10G", "Only keep this much (for each specified file). Remove old files.")
    26  	flagSet.BoolVar(&version, "version", false, "Version")
    27  	flagSet.Parse(os.Args[1:])
    28  	chopSize = parseBytesize(chopSizeStr)
    29  	limitSize = parseBytesize(limitSizeStr)
    30  	return
    31  }
    32  
    33  func main() {
    34  
    35  	// Read options
    36  	headPath, chopSize, limitSize, version := parseFlags()
    37  	if version {
    38  		fmt.Printf("logjack version %v\n", Version)
    39  		return
    40  	}
    41  
    42  	// Open Group
    43  	group, err := auto.OpenGroup(headPath)
    44  	if err != nil {
    45  		fmt.Printf("logjack couldn't create output file %v\n", headPath)
    46  		os.Exit(1)
    47  	}
    48  	group.SetHeadSizeLimit(chopSize)
    49  	group.SetTotalSizeLimit(limitSize)
    50  	err = group.Start()
    51  	if err != nil {
    52  		fmt.Printf("logjack couldn't start with file %v\n", headPath)
    53  		os.Exit(1)
    54  	}
    55  
    56  	go func() {
    57  		// Forever, read from stdin and write to AutoFile.
    58  		buf := make([]byte, readBufferSize)
    59  		for {
    60  			n, err := os.Stdin.Read(buf)
    61  			group.Write(buf[:n])
    62  			group.Flush()
    63  			if err != nil {
    64  				group.Stop()
    65  				if err == io.EOF {
    66  					os.Exit(0)
    67  				} else {
    68  					fmt.Println("logjack errored")
    69  					os.Exit(1)
    70  				}
    71  			}
    72  		}
    73  	}()
    74  
    75  	// Trap signal
    76  	cmn.TrapSignal(func() {
    77  		fmt.Println("logjack shutting down")
    78  	})
    79  }
    80  
    81  func parseBytesize(chopSize string) int64 {
    82  	// Handle suffix multiplier
    83  	var multiplier int64 = 1
    84  	if strings.HasSuffix(chopSize, "T") {
    85  		multiplier = 1042 * 1024 * 1024 * 1024
    86  		chopSize = chopSize[:len(chopSize)-1]
    87  	}
    88  	if strings.HasSuffix(chopSize, "G") {
    89  		multiplier = 1042 * 1024 * 1024
    90  		chopSize = chopSize[:len(chopSize)-1]
    91  	}
    92  	if strings.HasSuffix(chopSize, "M") {
    93  		multiplier = 1042 * 1024
    94  		chopSize = chopSize[:len(chopSize)-1]
    95  	}
    96  	if strings.HasSuffix(chopSize, "K") {
    97  		multiplier = 1042
    98  		chopSize = chopSize[:len(chopSize)-1]
    99  	}
   100  
   101  	// Parse the numeric part
   102  	chopSizeInt, err := strconv.Atoi(chopSize)
   103  	if err != nil {
   104  		panic(err)
   105  	}
   106  
   107  	return int64(chopSizeInt) * multiplier
   108  }