logger.go (2793B)
1 // This file is part of taler-cashless2ecash. 2 // Copyright (C) 2024 Joel Häberli 3 // 4 // taler-cashless2ecash is free software: you can redistribute it and/or modify it 5 // under the terms of the GNU Affero General Public License as published 6 // by the Free Software Foundation, either version 3 of the License, 7 // or (at your option) any later version. 8 // 9 // taler-cashless2ecash is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // 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 // SPDX-License-Identifier: AGPL3.0-or-later 18 19 package internal_utils 20 21 import ( 22 "fmt" 23 "net/http" 24 "os" 25 "time" 26 ) 27 28 const LOG_PATH = "c2ec-log.txt" 29 30 // LEVEL | TIME | SRC | MESSAGE 31 const LOG_PATTERN = "level=%d | time=%s | src=%s | %s" 32 const TIME_FORMAT = "yyyy-MM-dd hh:mm:ss" 33 34 type LogLevel int 35 36 const ( 37 INFO LogLevel = iota 38 WARN 39 ERROR 40 ) 41 42 var lastResponseStatus = 0 43 44 func LoggingHandler(next http.Handler) http.Handler { 45 46 return http.HandlerFunc( 47 func(w http.ResponseWriter, r *http.Request) { 48 49 LogRequest("http-logger", r) 50 51 next.ServeHTTP(w, r) 52 53 LogResponse("http-logger", r) 54 }, 55 ) 56 } 57 58 func SetLastResponseCodeForLogger(s int) { 59 lastResponseStatus = s 60 } 61 62 func LogRequest(src string, req *http.Request) { 63 64 LogInfo(src, fmt.Sprintf("%s - %s (origin=%s)", req.Method, req.URL, req.RemoteAddr)) 65 } 66 67 func LogResponse(src string, req *http.Request) { 68 69 LogInfo(src, fmt.Sprintf("code=%d: responding to %s (destination=%s)", lastResponseStatus, req.RequestURI, req.RemoteAddr)) 70 } 71 72 func LogError(src string, err error) { 73 74 go logAppendError(src, ERROR, err) 75 } 76 77 func LogWarn(src string, msg string) { 78 79 go logAppend(src, WARN, msg) 80 } 81 82 func LogInfo(src string, msg string) { 83 84 go logAppend(src, INFO, msg) 85 } 86 87 func logAppendError(src string, level LogLevel, err error) { 88 89 if err == nil { 90 fmt.Println("wanted to log from " + src + " but err was nil") 91 return 92 } 93 logAppend(src, level, err.Error()) 94 } 95 96 func logAppend(src string, level LogLevel, msg string) { 97 98 openAppendClose(fmt.Sprintf(LOG_PATTERN, level, time.Now().Format(time.UnixDate), src, msg)) 99 } 100 101 func openAppendClose(s string) { 102 103 // first try opening only append 104 f, err := os.OpenFile(LOG_PATH, os.O_APPEND|os.O_WRONLY, 0600) 105 if err != nil || f == nil { 106 // if file does not yet exist, open with create flag. 107 f, err = os.OpenFile(LOG_PATH, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) 108 if err != nil || f == nil { 109 fmt.Println("error: ", err.Error()) 110 panic("failed opening or creating log file") 111 } 112 } 113 f.WriteString(s + "\n") 114 f.Close() 115 }