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