systemd-ml/lib_xlog/systemd_xlog.ml

84 lines
2.5 KiB
OCaml
Raw Normal View History

2024-09-24 08:23:56 +00:00
open Xlog
let default_socket_path = "/run/systemd/journal/socket"
type t = {
mutex : Mutex.t;
sock_fd : Eio_unix.Fd.t;
buf : Buffer.t;
}
let add_field dgram key value =
if String.contains value '\n' then
begin
Buffer.add_string dgram key;
Buffer.add_char dgram '\n';
Buffer.add_int64_le dgram (Int64.of_int (String.length value));
Buffer.add_string dgram value;
Buffer.add_char dgram '\n';
end
else
Printf.bprintf dgram "%s=%s\n" key value
let syslog_priority = function
| TRACE
| DEBUG -> "7" (* LOG_DEBUG *)
| INFO -> "6" (* LOG_INFO *)
| WARN -> "4" (* LOG_WARNING *)
| ERROR -> "3" (* LOG_ERR *)
external unix_code_of_unix_error : Unix.error -> int = "ocaml_systemd_unix_code_of_unix_error"
let get_errno errno exn =
if errno != 0 then
errno
else
match exn with
| Some ((Unix.Unix_error (err, _, _)), _) -> unix_code_of_unix_error err
| _ -> 0
let writer t ~ts ~ns ~filename ~lineno ~func ~errno ~exn ~lvl msg =
Mutex.lock t.mutex;
let dgram =
Buffer.clear t.buf;
ignore ts;
let maybe_exn = match exn with
| Some (exn, bt) ->
Printf.sprintf "\nException: %s\n%s" (Printexc.to_string exn)
(Printexc.raw_backtrace_to_string bt)
| None -> ""
in
add_field t.buf "MESSAGE" (Printf.sprintf "%s: %s%s" ns msg maybe_exn);
add_field t.buf "PRIORITY" (syslog_priority lvl);
begin if not (filename = "") then
add_field t.buf "CODE_FILE" filename;
add_field t.buf "CODE_LINE" (Printf.sprintf "%d" lineno)
end;
begin if not (func = "") then
add_field t.buf "CODE_FUNC" func
end;
let errno = get_errno errno exn in
begin if errno != 0 then
add_field t.buf "ERRNO" (Printf.sprintf "%d" errno)
end;
Buffer.to_bytes t.buf
in
Mutex.unlock t.mutex;
let buf = [(Cstruct.of_bytes dgram)] in
let sent = Eio_linux.Low_level.send_msg t.sock_fd buf in
assert (sent = Cstruct.lenv buf)
let make_writer ~sw ~env =
if (Eio.Stdenv.backend_id env <> "linux") then failwith "Backend must be Eio_linux";
let sock = Unix.socket ~cloexec:true Unix.PF_UNIX Unix.SOCK_DGRAM 0 in
let sock = Eio_unix.Fd.of_unix ~sw ~seekable:false ~close_unix:true sock in
(* this path isn't configurable in libsystemd, so i don't see a reason to take an argument for
it here *)
Eio_linux.Low_level.connect sock (Unix.ADDR_UNIX default_socket_path);
writer {
mutex = Mutex.create ();
sock_fd = sock;
buf = Buffer.create 256;
}