github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/libs/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/franono/tendermint/libs/autofile"
    12  	tmos "github.com/franono/tendermint/libs/os"
    13  )
    14  
    15  const Version = "0.0.1"
    16  const readBufferSize = 1024 // 1KB at a time
    17  
    18  // Parse command-line options
    19  func parseFlags() (headPath string, chopSize int64, limitSize int64, version bool) {
    20  	var flagSet = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
    21  	var chopSizeStr, limitSizeStr string
    22  	flagSet.StringVar(&headPath, "head", "logjack.out", "Destination (head) file.")
    23  	flagSet.StringVar(&chopSizeStr, "chop", "100M", "Move file if greater than this")
    24  	flagSet.StringVar(&limitSizeStr, "limit", "10G", "Only keep this much (for each specified file). Remove old files.")
    25  	flagSet.BoolVar(&version, "version", false, "Version")
    26  	flagSet.Parse(os.Args[1:])
    27  	chopSize = parseBytesize(chopSizeStr)
    28  	limitSize = parseBytesize(limitSizeStr)
    29  	return
    30  }
    31  
    32  type fmtLogger struct{}
    33  
    34  func (fmtLogger) Info(msg string, keyvals ...interface{}) {
    35  	strs := make([]string, len(keyvals))
    36  	for i, kv := range keyvals {
    37  		strs[i] = fmt.Sprintf("%v", kv)
    38  	}
    39  	fmt.Printf("%s %s\n", msg, strings.Join(strs, ","))
    40  }
    41  
    42  func main() {
    43  	// Stop upon receiving SIGTERM or CTRL-C.
    44  	tmos.TrapSignal(fmtLogger{}, func() {
    45  		fmt.Println("logjack shutting down")
    46  	})
    47  
    48  	// Read options
    49  	headPath, chopSize, limitSize, version := parseFlags()
    50  	if version {
    51  		fmt.Printf("logjack version %v\n", Version)
    52  		return
    53  	}
    54  
    55  	// Open Group
    56  	group, err := auto.OpenGroup(headPath, auto.GroupHeadSizeLimit(chopSize), auto.GroupTotalSizeLimit(limitSize))
    57  	if err != nil {
    58  		fmt.Printf("logjack couldn't create output file %v\n", headPath)
    59  		os.Exit(1)
    60  	}
    61  
    62  	err = group.Start()
    63  	if err != nil {
    64  		fmt.Printf("logjack couldn't start with file %v\n", headPath)
    65  		os.Exit(1)
    66  	}
    67  
    68  	// Forever read from stdin and write to AutoFile.
    69  	buf := make([]byte, readBufferSize)
    70  	for {
    71  		n, err := os.Stdin.Read(buf)
    72  		group.Write(buf[:n])
    73  		group.FlushAndSync()
    74  		if err != nil {
    75  			group.Stop()
    76  			if err == io.EOF {
    77  				os.Exit(0)
    78  			} else {
    79  				fmt.Println("logjack errored")
    80  				os.Exit(1)
    81  			}
    82  		}
    83  	}
    84  }
    85  
    86  func parseBytesize(chopSize string) int64 {
    87  	// Handle suffix multiplier
    88  	var multiplier int64 = 1
    89  	if strings.HasSuffix(chopSize, "T") {
    90  		multiplier = 1042 * 1024 * 1024 * 1024
    91  		chopSize = chopSize[:len(chopSize)-1]
    92  	}
    93  	if strings.HasSuffix(chopSize, "G") {
    94  		multiplier = 1042 * 1024 * 1024
    95  		chopSize = chopSize[:len(chopSize)-1]
    96  	}
    97  	if strings.HasSuffix(chopSize, "M") {
    98  		multiplier = 1042 * 1024
    99  		chopSize = chopSize[:len(chopSize)-1]
   100  	}
   101  	if strings.HasSuffix(chopSize, "K") {
   102  		multiplier = 1042
   103  		chopSize = chopSize[:len(chopSize)-1]
   104  	}
   105  
   106  	// Parse the numeric part
   107  	chopSizeInt, err := strconv.Atoi(chopSize)
   108  	if err != nil {
   109  		panic(err)
   110  	}
   111  
   112  	return int64(chopSizeInt) * multiplier
   113  }