github.com/minio/console@v1.4.1/pkg/logger/logonce.go (about) 1 // This file is part of MinIO Console Server 2 // Copyright (c) 2022 MinIO, Inc. 3 // 4 // This program is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Affero General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // This program is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 17 package logger 18 19 import ( 20 "context" 21 "errors" 22 "net/http" 23 "sync" 24 "time" 25 ) 26 27 // Holds a map of recently logged errors. 28 type logOnceType struct { 29 IDMap map[interface{}]error 30 sync.Mutex 31 } 32 33 // One log message per errors. 34 func (l *logOnceType) logOnceIf(ctx context.Context, err error, id interface{}, errKind ...interface{}) { 35 if err == nil { 36 return 37 } 38 l.Lock() 39 shouldLog := false 40 prevErr := l.IDMap[id] 41 if prevErr == nil { 42 l.IDMap[id] = err 43 shouldLog = true 44 } else if prevErr.Error() != err.Error() { 45 l.IDMap[id] = err 46 shouldLog = true 47 } 48 l.Unlock() 49 50 if shouldLog { 51 LogIf(ctx, err, errKind...) 52 } 53 } 54 55 // Cleanup the map every 30 minutes so that the log message is printed again for the user to notice. 56 func (l *logOnceType) cleanupRoutine() { 57 for { 58 l.Lock() 59 l.IDMap = make(map[interface{}]error) 60 l.Unlock() 61 62 time.Sleep(30 * time.Minute) 63 } 64 } 65 66 // Returns logOnceType 67 func newLogOnceType() *logOnceType { 68 l := &logOnceType{IDMap: make(map[interface{}]error)} 69 go l.cleanupRoutine() 70 return l 71 } 72 73 var logOnce = newLogOnceType() 74 75 // LogOnceIf - Logs notification errors - once per errors. 76 // id is a unique identifier for related log messages, refer to cmd/notification.go 77 // on how it is used. 78 func LogOnceIf(ctx context.Context, err error, id interface{}, errKind ...interface{}) { 79 if err == nil { 80 return 81 } 82 83 if errors.Is(err, context.Canceled) { 84 return 85 } 86 87 if err.Error() == http.ErrServerClosed.Error() || err.Error() == "disk not found" { 88 return 89 } 90 91 logOnce.logOnceIf(ctx, err, id, errKind...) 92 }