scm: add support for logging

Add functions debug, info, warning, critical which log to the mu logging
facilities.
This commit is contained in:
Dirk-Jan C. Binnema
2025-08-24 17:19:00 +03:00
parent a69e6fad1d
commit d66a29cf5e
6 changed files with 119 additions and 5 deletions

View File

@ -21,6 +21,7 @@
;; after printing UNIX-CONNECT:<socket-file>\n on stdout
(let ((socket-path (getenv "MU_SCM_SOCKET_PATH")))
(when socket-path
(info "listening on domain socket ~a" socket-path)
(format #t "~a\n" socket-path)
(run-server
(make-unix-domain-server-socket #:path socket-path))))

View File

@ -127,7 +127,8 @@ to_sort_field_id(SCM field, const char *func, int pos)
const auto sym{from_scm<std::string>(scm_symbol_to_string(field), func, pos)};
if (const auto field_opt{field_from_name(sym)}; !field_opt) {
throw ScmError{ScmError::Id::WrongType, func, pos, field, "sort-field-symbol"};
throw ScmError{ScmError::Id::WrongType, func, pos, field,
"sort-field-symbol"};
} else
return field_opt->id;
}
@ -144,7 +145,8 @@ subr_cc_store_mfind(SCM store_scm, SCM query_scm, SCM related_scm, SCM skip_dups
const auto skip_dups(from_scm<bool>(skip_dups_scm, func, 4));
if (!scm_is_false(sort_field_scm) && !scm_is_symbol(sort_field_scm))
throw ScmError{ScmError::Id::WrongType, func, 5, sort_field_scm, "#f or sort-field-symbol"};
throw ScmError{ScmError::Id::WrongType, func, 5, sort_field_scm,
"#f or sort-field-symbol"};
const auto sort_field_id = to_sort_field_id(sort_field_scm, func, 5);
const auto reverse(from_scm<bool>(reverse_scm, func, 6));

View File

@ -64,6 +64,46 @@ init_options(const Options& opts)
scm_c_define("%options", scm_opts);
}
static void
init_misc()
{
scm_define(make_symbol("level-critical"), to_scm(G_LOG_LEVEL_CRITICAL));
scm_define(make_symbol("level-warning"), to_scm(G_LOG_LEVEL_WARNING));
scm_define(make_symbol("level-info"), to_scm(G_LOG_LEVEL_INFO));
scm_define(make_symbol("level-debug"), to_scm(G_LOG_LEVEL_DEBUG));
}
static SCM
subr_cc_log(SCM level_scm, SCM str_scm) try {
constexpr auto func{"cc-log"};
const auto level{static_cast<GLogLevelFlags>(from_scm<int>(level_scm, func, 1))};
if (level != G_LOG_LEVEL_CRITICAL && level != G_LOG_LEVEL_WARNING &&
level != G_LOG_LEVEL_INFO && level != G_LOG_LEVEL_DEBUG)
throw ScmError{ScmError::Id::WrongType, func, 1, level_scm, "level"};
const auto str{from_scm<std::string>(str_scm, func, 2)};
g_log("mu-scm", level, "%s", str.c_str());
return SCM_UNSPECIFIED;
} catch (const ScmError& err) {
err.throw_scm();
}
static void
init_subrs()
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
scm_c_define_gsubr("cc-log", 2/*req*/, 0/*opt*/, 0/*rst*/,
reinterpret_cast<scm_t_subr>(subr_cc_log));
#pragma GCC diagnostic pop
}
static const Result<std::string>
make_mu_scm_path(const std::string& fname) {
@ -157,8 +197,6 @@ maybe_remove_socket_path()
}
}
static void
prepare_shell(const Options& opts, StrVec& args)
{
@ -186,6 +224,9 @@ init_module_mu(void* data)
const ModMuData& conf{*reinterpret_cast<ModMuData*>(data)};
init_options(conf.opts);
init_misc();
init_subrs();
init_store(conf.store);
init_message();
init_mime();

View File

@ -227,6 +227,10 @@ namespace Mu::Scm {
return scm_from_bool(val);
else if constexpr (std::is_same_v<Type, size_t>)
return scm_from_size_t(val);
else if constexpr (std::is_same_v<Type, int>)
return scm_from_int(val);
else if constexpr (std::is_same_v<Type, GLogLevelFlags>)
return scm_from_int(static_cast<int>(val));
else if constexpr (std::is_same_v<Type, int64_t>)
return scm_from_int64(val);
else if constexpr (std::is_same_v<Type, uint64_t>)

View File

@ -21,6 +21,7 @@
:use-module (system foreign)
:use-module (rnrs bytevectors)
:use-module (ice-9 optargs)
:use-module (ice-9 format)
:use-module (ice-9 binary-ports)
#:export (
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -100,11 +101,16 @@
%options
;; %preferences
;; logging
debug
info
warning
critical
;; helpers
string->time
time->string))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Helpers
@ -637,3 +643,43 @@ UTC time.
(let ((t (if utc? (gmtime time-t) (localtime time-t))))
(strftime format t))
#f)))
;; Logging to mu's log
(define (mlog level frmstr . args)
"Log to the mu logger.
LEVEL is the logging-level, a symbol one of:
debug, info, warning, critical
FRMSTR is a format string like `(format)', and the ARGS are the parameters for
that format string."
(let ((msg (if (null? args)
frmstr
(apply format #f frmstr args))))
(cc-log level msg)))
(define (info frm . args)
"Log a message at info level to the mu logger.
FRM is the format string and ARGS are its arguments, see `(format)' for details
on the precise format."
(apply mlog level-info frm args))
(define (warning frm . args)
"Log a message at warning level to the mu logger.
FRM is the format string and ARGS are its arguments, see `(format)' for details
on the precise format."
(apply mlog level-warning frm args))
(define (critical frm . args)
"Log a message at critical level to the mu logger.
FRM is the format string and ARGS are its arguments, see `(format)' for details
on the precise format."
(apply mlog level-critical frm args))
(define (debug frm . args)
"Log a message at debug level to the mu logger.
FRM is the format string and ARGS are its arguments, see `(format)' for details
on the precise format."
(apply mlog level-debug frm args))

View File

@ -939,6 +939,26 @@ their default values.
@node Helpers
@section Helpers
@deffn {Scheme Procedure} debug frm . args
@end deffn
@deffn {Scheme Procedure} info frm . args
@end deffn
@deffn {Scheme Procedure} warning frm . args
@end deffn
@deffn {Scheme Procedure} critical frm . args
@end deffn
Log using @t{mu}'s logging facilities at the given level (debug, info, warning
or critical). @code{frm} and @code{args} are expected to be a format string and
its arguments, respectively, according to Guile's @code{format} function.
Note: where the log output exactly appears (i.e., log-file, journal, console,
nowhere) dependis on the particulars of the system and how mu was started; see
the @t{mu (1)} man-page for details on the latter.
@deffn {Scheme Procedure} string->time timestr [#:utc? (assoc-ref %preferences 'utc?)]
@end deffn
Convert some ISO-8601-style time-string to a seconds-since-epoch @t{time_t}