From 5909dd71c54eec8060f788328effb5db613bf33a Mon Sep 17 00:00:00 2001 From: Sergey Mostovoy Date: Tue, 27 Dec 2016 12:18:49 +0200 Subject: [PATCH 1/2] Support %r - request id - output file pattern #381 --- output_file.go | 44 ++++++++++++++++++++++++++++---------------- output_file_test.go | 27 +++++++++++++++++++++++++++ settings.go | 2 +- 3 files changed, 56 insertions(+), 17 deletions(-) diff --git a/output_file.go b/output_file.go index a50b905..1ac00dc 100644 --- a/output_file.go +++ b/output_file.go @@ -16,14 +16,15 @@ import ( "time" ) -var dateFileNameFuncs = map[string]func() string{ - "%Y": func() string { return time.Now().Format("2006") }, - "%m": func() string { return time.Now().Format("01") }, - "%d": func() string { return time.Now().Format("02") }, - "%H": func() string { return time.Now().Format("15") }, - "%M": func() string { return time.Now().Format("04") }, - "%S": func() string { return time.Now().Format("05") }, - "%NS": func() string { return fmt.Sprint(time.Now().Nanosecond()) }, +var dateFileNameFuncs = map[string]func(*FileOutput) string{ + "%Y": func(o *FileOutput) string { return time.Now().Format("2006") }, + "%m": func(o *FileOutput) string { return time.Now().Format("01") }, + "%d": func(o *FileOutput) string { return time.Now().Format("02") }, + "%H": func(o *FileOutput) string { return time.Now().Format("15") }, + "%M": func(o *FileOutput) string { return time.Now().Format("04") }, + "%S": func(o *FileOutput) string { return time.Now().Format("05") }, + "%NS": func(o *FileOutput) string { return fmt.Sprint(time.Now().Nanosecond()) }, + "%r": func(o *FileOutput) string { return o.currentID }, } type FileOutputConfig struct { @@ -35,13 +36,15 @@ type FileOutputConfig struct { // FileOutput output plugin type FileOutput struct { - mu sync.Mutex - pathTemplate string - currentName string - file *os.File - queueLength int - chunkSize int - writer io.Writer + mu sync.Mutex + pathTemplate string + currentName string + file *os.File + queueLength int + chunkSize int + writer io.Writer + requestPerFile bool + currentID string config *FileOutputConfig } @@ -53,6 +56,10 @@ func NewFileOutput(pathTemplate string, config *FileOutputConfig) *FileOutput { o.config = config o.updateName() + if strings.Contains(pathTemplate, "%r") { + o.requestPerFile = true + } + go func() { for { time.Sleep(time.Second) @@ -123,7 +130,7 @@ func (o *FileOutput) filename() string { path := o.pathTemplate for name, fn := range dateFileNameFuncs { - path = strings.Replace(path, name, fn(), -1) + path = strings.Replace(path, name, fn(o), -1) } if !o.config.append { @@ -167,6 +174,11 @@ func (o *FileOutput) updateName() { } func (o *FileOutput) Write(data []byte) (n int, err error) { + if o.requestPerFile { + o.currentID = string(payloadMeta(data)[1]) + o.updateName() + } + if !isOriginPayload(data) { return len(data), nil } diff --git a/output_file_test.go b/output_file_test.go index 04601f8..22531a4 100644 --- a/output_file_test.go +++ b/output_file_test.go @@ -106,6 +106,33 @@ func TestFileOutputMultipleFiles(t *testing.T) { os.Remove(name3) } +func TestFileOutputFilePerRequest(t *testing.T) { + output := NewFileOutput("/tmp/log-%Y-%m-%d-%S-%r", &FileOutputConfig{append: true, flushInterval: time.Minute}) + + if output.file != nil { + t.Error("Should not initialize file if no writes") + } + + output.Write([]byte("1 1 1\ntest")) + name1 := output.file.Name() + + output.Write([]byte("1 2 1\ntest")) + name2 := output.file.Name() + + time.Sleep(time.Second) + output.updateName() + + output.Write([]byte("1 3 1\ntest")) + name3 := output.file.Name() + + if name3 == name2 || name2 == name1 || name3 == name1 { + t.Error("File name should change:", name1, name2, name3) + } + + os.Remove(name1) + os.Remove(name3) +} + func TestFileOutputCompression(t *testing.T) { output := NewFileOutput("/tmp/log-%Y-%m-%d-%S.gz", &FileOutputConfig{append: true, flushInterval: time.Minute}) diff --git a/settings.go b/settings.go index ac62f7c..f012867 100644 --- a/settings.go +++ b/settings.go @@ -96,7 +96,7 @@ func init() { flag.BoolVar(&Settings.inputFileLoop, "input-file-loop", false, "Loop input files, useful for performance testing.") flag.Var(&Settings.outputFile, "output-file", "Write incoming requests to file: \n\tgor --input-raw :80 --output-file ./requests.gor") - flag.DurationVar(&Settings.outputFileConfig.flushInterval, "output-file-flush-interval", time.Minute, "Interval for forcing buffer flush to the file, default: 60s.") + flag.DurationVar(&Settings.outputFileConfig.flushInterval, "output-file-flush-interval", time.Second, "Interval for forcing buffer flush to the file, default: 1s.") flag.BoolVar(&Settings.outputFileConfig.append, "output-file-append", false, "The flushed chunk is appended to existence file or not. ") // Set default From 826cc45d44438189401227366cfb4193d0dcaf62 Mon Sep 17 00:00:00 2001 From: Sergey Mostovoy Date: Tue, 27 Dec 2016 12:46:47 +0200 Subject: [PATCH 2/2] clean files in test [#381] --- output_file_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/output_file_test.go b/output_file_test.go index 22531a4..98e7e5f 100644 --- a/output_file_test.go +++ b/output_file_test.go @@ -107,7 +107,7 @@ func TestFileOutputMultipleFiles(t *testing.T) { } func TestFileOutputFilePerRequest(t *testing.T) { - output := NewFileOutput("/tmp/log-%Y-%m-%d-%S-%r", &FileOutputConfig{append: true, flushInterval: time.Minute}) + output := NewFileOutput("/tmp/log-%Y-%m-%d-%S-%r", &FileOutputConfig{append: true}) if output.file != nil { t.Error("Should not initialize file if no writes") @@ -130,6 +130,7 @@ func TestFileOutputFilePerRequest(t *testing.T) { } os.Remove(name1) + os.Remove(name2) os.Remove(name3) }