diff options
Diffstat (limited to 'src/log.lisp')
| -rw-r--r-- | src/log.lisp | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/log.lisp b/src/log.lisp new file mode 100644 index 0000000..e6e8661 --- /dev/null +++ b/src/log.lisp | |||
| @@ -0,0 +1,85 @@ | |||
| 1 | ;; SPDX-License-Identifier: EUPL-1.2 | ||
| 2 | ;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com> | ||
| 3 | (defpackage :ukkoclot/log | ||
| 4 | (:use :c2cl) | ||
| 5 | (:export :*output* :deflevel :log-error :log-warn :log-info :log-debug)) | ||
| 6 | (in-package :ukkoclot/log) | ||
| 7 | |||
| 8 | (defparameter *output* *error-output*) | ||
| 9 | |||
| 10 | (defvar *max-name-length* 8) | ||
| 11 | (defvar *max-level-length* 4) | ||
| 12 | |||
| 13 | (defvar *levels* nil) | ||
| 14 | |||
| 15 | (defun get-levels () | ||
| 16 | (unless *levels* | ||
| 17 | (setf *levels* (make-hash-table :test #'eq))) | ||
| 18 | *levels*) | ||
| 19 | |||
| 20 | (defun register-level (level value) | ||
| 21 | (setf (gethash level (get-levels)) value) | ||
| 22 | (let ((l (length (symbol-name level)))) | ||
| 23 | (when (> l *max-level-length*) | ||
| 24 | (setf *max-level-length* l)))) | ||
| 25 | |||
| 26 | (defun level-value (level) | ||
| 27 | (let ((value (gethash level (get-levels)))) | ||
| 28 | (if value | ||
| 29 | value | ||
| 30 | (progn | ||
| 31 | (format *output* "UKKOLOG INTERNAL WARN: UNKNOWN LEVEL ~A" level) | ||
| 32 | 1000)))) | ||
| 33 | |||
| 34 | (defun level< (lhs rhs) | ||
| 35 | (< (level-value lhs) (level-value rhs))) | ||
| 36 | |||
| 37 | (defstruct (logger (:constructor make-logger%)) | ||
| 38 | (name (error "No value given for NAME") :type keyword :read-only t) | ||
| 39 | (min-level :debug :type keyword)) ;TODO: Make this :info and make it configurable | ||
| 40 | |||
| 41 | (defun make-logger (name) | ||
| 42 | (let ((l (length (symbol-name name)))) | ||
| 43 | (when (> l *max-name-length*) | ||
| 44 | (setf *max-name-length* l))) | ||
| 45 | (make-logger% :name name)) | ||
| 46 | |||
| 47 | (defvar *package-loggers* nil) | ||
| 48 | |||
| 49 | (defun get-package-loggers () | ||
| 50 | (unless *package-loggers* | ||
| 51 | (setf *package-loggers* (make-hash-table :test #'eq))) | ||
| 52 | *package-loggers*) | ||
| 53 | |||
| 54 | (defun get-package-logger (package) | ||
| 55 | (let* ((name (package-name package)) | ||
| 56 | (name-sym (intern name :keyword)) | ||
| 57 | (loggers (get-package-loggers)) | ||
| 58 | (logger (gethash name-sym loggers))) | ||
| 59 | (unless logger | ||
| 60 | (setf logger (make-logger name-sym)) | ||
| 61 | (setf (gethash name-sym loggers) logger)) | ||
| 62 | logger)) | ||
| 63 | |||
| 64 | (defun perform-log (package level fmt-str &rest args) | ||
| 65 | (let ((logger (get-package-logger package))) | ||
| 66 | (unless (level< level (logger-min-level logger)) | ||
| 67 | (apply #'format *output* | ||
| 68 | (concatenate 'string "~&~v@A: ~v@A: " fmt-str "~%") | ||
| 69 | *max-name-length* (logger-name logger) | ||
| 70 | *max-level-length* level | ||
| 71 | args)))) | ||
| 72 | |||
| 73 | (defmacro p (level fmt-str &rest args) | ||
| 74 | `(perform-log ,*package* ,level ,fmt-str ,@args)) | ||
| 75 | |||
| 76 | (defmacro deflevel (name value) | ||
| 77 | `(progn | ||
| 78 | (register-level ,name ,value) | ||
| 79 | (defmacro ,(intern (concatenate 'string "LOG-" (symbol-name name))) (fmt-str &rest args) | ||
| 80 | `(p ,,name ,fmt-str ,@args)))) | ||
| 81 | |||
| 82 | (deflevel :error 700) | ||
| 83 | (deflevel :warn 600) | ||
| 84 | (deflevel :info 500) | ||
| 85 | (deflevel :debug 400) | ||