github.com/IBM-Cloud/bluemix-go@v0.0.0-20240423071914-9e96525baef4/trace/trace.go (about) 1 package trace 2 3 import ( 4 "fmt" 5 "io" 6 "log" 7 "os" 8 "regexp" 9 "strings" 10 ) 11 12 //Printer ... 13 type Printer interface { 14 Print(v ...interface{}) 15 Printf(format string, v ...interface{}) 16 Println(v ...interface{}) 17 } 18 19 //Closer ... 20 type Closer interface { 21 Close() error 22 } 23 24 //PrinterCloser ... 25 type PrinterCloser interface { 26 Printer 27 Closer 28 } 29 30 //NullLogger ... 31 type NullLogger struct{} 32 33 func (l *NullLogger) Print(v ...interface{}) {} 34 func (l *NullLogger) Printf(format string, v ...interface{}) {} 35 func (l *NullLogger) Println(v ...interface{}) {} 36 37 type loggerImpl struct { 38 *log.Logger 39 c io.WriteCloser 40 } 41 42 func (loggerImpl *loggerImpl) Close() error { 43 if loggerImpl.c != nil { 44 return loggerImpl.c.Close() 45 } 46 return nil 47 } 48 49 var ( 50 stdout = os.Stdout 51 stderr = os.Stderr 52 ) 53 54 func newLoggerImpl(out io.Writer, prefix string, flag int) *loggerImpl { 55 l := log.New(out, prefix, flag) 56 c := out.(io.WriteCloser) 57 return &loggerImpl{ 58 Logger: l, 59 c: c, 60 } 61 } 62 63 //Logger is global logger 64 var Logger Printer = NewLogger("") 65 66 // NewLogger returns a printer for the given trace setting. 67 func NewLogger(bluemix_trace string) Printer { 68 switch strings.ToLower(bluemix_trace) { 69 case "", "false": 70 return new(NullLogger) 71 case "true": 72 return NewStdLogger() 73 default: 74 return NewFileLogger(bluemix_trace) 75 } 76 } 77 78 // NewStdLogger return a printer that writes to StdOut. 79 func NewStdLogger() PrinterCloser { 80 if os.Getenv("IBMCLOUD_BLUEMIX_GO_TRACE") != "" { 81 return newLoggerImpl(stdout, "", 0) 82 } 83 return newLoggerImpl(stderr, "", 0) 84 } 85 86 // NewFileLogger return a printer that writes to the given file path. 87 func NewFileLogger(path string) PrinterCloser { 88 file, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0644) 89 if err != nil { 90 logger := NewStdLogger() 91 logger.Printf("[ERROR] An error occurred when creating log file '%s':\n%v\n\n", path, err) 92 return logger 93 } 94 return newLoggerImpl(file, "", 0) 95 } 96 97 // Sanitize returns a clean string with sentive user data in the input 98 // replaced by PRIVATE_DATA_PLACEHOLDER. 99 func Sanitize(input string) string { 100 re := regexp.MustCompile(`(?m)^Authorization: .*`) 101 sanitized := re.ReplaceAllString(input, "Authorization: "+privateDataPlaceholder()) 102 103 re = regexp.MustCompile(`(?m)^X-Auth-Token: .*`) 104 sanitized = re.ReplaceAllString(sanitized, "X-Auth-Token: "+privateDataPlaceholder()) 105 106 re = regexp.MustCompile(`(?m)^X-Auth-Refresh-Token: .*`) 107 sanitized = re.ReplaceAllString(sanitized, "X-Auth-Refresh-Token: "+privateDataPlaceholder()) 108 109 re = regexp.MustCompile(`(?m)^X-Auth-Uaa-Token: .*`) 110 sanitized = re.ReplaceAllString(sanitized, "X-Auth-Uaa-Token: "+privateDataPlaceholder()) 111 112 re = regexp.MustCompile(`(?m)^X-Auth-User-Token: .*`) 113 sanitized = re.ReplaceAllString(sanitized, "X-Auth-User-Token: "+privateDataPlaceholder()) 114 115 re = regexp.MustCompile(`password=[^&]*&`) 116 sanitized = re.ReplaceAllString(sanitized, "password="+privateDataPlaceholder()+"&") 117 118 re = regexp.MustCompile(`refresh_token=[^&]*&`) 119 sanitized = re.ReplaceAllString(sanitized, "refresh_token="+privateDataPlaceholder()+"&") 120 121 re = regexp.MustCompile(`apikey=[^&]*&`) 122 sanitized = re.ReplaceAllString(sanitized, "apikey="+privateDataPlaceholder()+"&") 123 124 sanitized = sanitizeJSON("token", sanitized) 125 sanitized = sanitizeJSON("password", sanitized) 126 sanitized = sanitizeJSON("apikey", sanitized) 127 sanitized = sanitizeJSON("passcode", sanitized) 128 129 return sanitized 130 } 131 132 func sanitizeJSON(propertySubstring string, json string) string { 133 regex := regexp.MustCompile(fmt.Sprintf(`(?i)"([^"]*%s[^"]*)":\s*"[^\,]*"`, propertySubstring)) 134 return regex.ReplaceAllString(json, fmt.Sprintf(`"$1":"%s"`, privateDataPlaceholder())) 135 } 136 137 // privateDataPlaceholder returns the text to replace the sentive data. 138 func privateDataPlaceholder() string { 139 return "[PRIVATE DATA HIDDEN]" 140 }