github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/util/ui/request_logger_file_writer.go (about) 1 package ui 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "os" 8 "path/filepath" 9 "regexp" 10 "sync" 11 "time" 12 ) 13 14 type RequestLoggerFileWriter struct { 15 ui *UI 16 lock *sync.Mutex 17 filePaths []string 18 logFiles []*os.File 19 dumpSanitizer *regexp.Regexp 20 } 21 22 func newRequestLoggerFileWriter(ui *UI, lock *sync.Mutex, filePaths []string) *RequestLoggerFileWriter { 23 return &RequestLoggerFileWriter{ 24 ui: ui, 25 lock: lock, 26 filePaths: filePaths, 27 logFiles: []*os.File{}, 28 dumpSanitizer: regexp.MustCompile(tokenRegexp), 29 } 30 } 31 32 func (display *RequestLoggerFileWriter) DisplayBody([]byte) error { 33 for _, logFile := range display.logFiles { 34 _, err := logFile.WriteString(RedactedValue) 35 if err != nil { 36 return err 37 } 38 } 39 return nil 40 } 41 42 func (display *RequestLoggerFileWriter) DisplayDump(dump string) error { 43 sanitized := display.dumpSanitizer.ReplaceAllString(dump, RedactedValue) 44 for _, logFile := range display.logFiles { 45 _, err := logFile.WriteString(sanitized) 46 if err != nil { 47 return err 48 } 49 } 50 return nil 51 } 52 53 func (display *RequestLoggerFileWriter) DisplayHeader(name string, value string) error { 54 return display.DisplayMessage(fmt.Sprintf("%s: %s", name, value)) 55 } 56 57 func (display *RequestLoggerFileWriter) DisplayHost(name string) error { 58 return display.DisplayMessage(fmt.Sprintf("Host: %s", name)) 59 } 60 61 func (display *RequestLoggerFileWriter) DisplayJSONBody(body []byte) error { 62 if body == nil || len(body) == 0 { 63 return nil 64 } 65 66 sanitized, err := SanitizeJSON(body) 67 if err != nil { 68 return display.DisplayMessage(string(body)) 69 } 70 71 buff := new(bytes.Buffer) 72 encoder := json.NewEncoder(buff) 73 encoder.SetEscapeHTML(false) 74 encoder.SetIndent("", " ") 75 err = encoder.Encode(sanitized) 76 if err != nil { 77 return err 78 } 79 80 for _, logFile := range display.logFiles { 81 _, err = logFile.Write(buff.Bytes()) 82 if err != nil { 83 return err 84 } 85 } 86 return nil 87 } 88 89 func (display *RequestLoggerFileWriter) DisplayMessage(msg string) error { 90 for _, logFile := range display.logFiles { 91 _, err := logFile.WriteString(fmt.Sprintf("%s\n", msg)) 92 if err != nil { 93 return err 94 } 95 } 96 return nil 97 } 98 99 func (display *RequestLoggerFileWriter) DisplayRequestHeader(method string, uri string, httpProtocol string) error { 100 return display.DisplayMessage(fmt.Sprintf("%s %s %s", method, uri, httpProtocol)) 101 } 102 103 func (display *RequestLoggerFileWriter) DisplayResponseHeader(httpProtocol string, status string) error { 104 return display.DisplayMessage(fmt.Sprintf("%s %s", httpProtocol, status)) 105 } 106 107 func (display *RequestLoggerFileWriter) DisplayType(name string, requestDate time.Time) error { 108 return display.DisplayMessage(fmt.Sprintf("%s: [%s]", name, requestDate.Format(time.RFC3339))) 109 } 110 111 func (display *RequestLoggerFileWriter) HandleInternalError(err error) { 112 display.ui.DisplayWarning(err.Error()) 113 } 114 115 func (display *RequestLoggerFileWriter) Start() error { 116 display.lock.Lock() 117 for _, filePath := range display.filePaths { 118 err := os.MkdirAll(filepath.Dir(filePath), os.ModeDir|os.ModePerm) 119 if err != nil { 120 return err 121 } 122 123 logFile, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600) 124 if err != nil { 125 return err 126 } 127 128 display.logFiles = append(display.logFiles, logFile) 129 } 130 return nil 131 } 132 133 func (display *RequestLoggerFileWriter) Stop() error { 134 var err error 135 136 for _, logFile := range display.logFiles { 137 _, lastLineErr := logFile.WriteString("\n") 138 closeErr := logFile.Close() 139 switch { 140 case closeErr != nil: 141 err = closeErr 142 case lastLineErr != nil: 143 err = lastLineErr 144 } 145 } 146 display.logFiles = []*os.File{} 147 display.lock.Unlock() 148 return err 149 }