xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: David Scott <dave.scott@eu.citrix.com>
To: xen-devel@lists.xen.org
Cc: David Scott <dave.scott@eu.citrix.com>
Subject: [PATCH 2/3] oxenstored: enable logging via syslog, if specified in the config file.
Date: Wed, 20 Mar 2013 10:32:44 +0000	[thread overview]
Message-ID: <1363775565-4367-3-git-send-email-dave.scott@eu.citrix.com> (raw)
In-Reply-To: <1363775565-4367-1-git-send-email-dave.scott@eu.citrix.com>

To log to files the config file should contain:
   xenstored-log-file = /var/log/xenstored.log
   access-log-file = /var/log/xenstored-access.log

(These two files are still the built-in defaults. The log format is
unchanged.)

To log to syslog the config file should contain:
   xenstored-log-file = syslog:<facility>
   access-log-file = syslog:<facility>

where <facility> is the syslog facility to use (e.g. 'daemon' 'local2')

Signed-off-by: David Scott <dave.scott@eu.citrix.com>
---
 tools/ocaml/xenstored/logging.ml   | 124 +++++++++++++++++++++++++++----------
 tools/ocaml/xenstored/xenstored.ml |   4 +-
 2 files changed, 94 insertions(+), 34 deletions(-)

diff --git a/tools/ocaml/xenstored/logging.ml b/tools/ocaml/xenstored/logging.ml
index bc3a2ea..e26f804 100644
--- a/tools/ocaml/xenstored/logging.ml
+++ b/tools/ocaml/xenstored/logging.ml
@@ -20,11 +20,42 @@ open Printf
 
 (* Logger common *)
 
+type log_destination =
+	| File of string
+	| Syslog of Syslog.facility
+
+let log_destination_of_string s =
+	let prefix = "syslog:" in
+	let len_prefix = String.length prefix in
+	let len = String.length s in
+	if String.startswith prefix s
+	then Syslog(Syslog.facility_of_string (String.sub s len_prefix (len - len_prefix)))
+	else File s
+
+(* The prefix of a log line depends on the log destination *)
+let prefix log_destination ?level ?key date = match log_destination with
+	| File _ ->
+		let level = match level with
+			| Some x -> Printf.sprintf "|%5s" x
+			| None -> "" in
+		let key = match key with
+			| Some x -> "|" ^ x
+			| None -> "" in
+		Printf.sprintf "[%s%s%s] " date level key
+	| Syslog _ ->
+		let key = match key with
+			| Some x -> "[" ^ x ^ "] "
+			| None -> "" in
+		(* Syslog handles the date and level internally *)
+		key
+
+type level = Debug | Info | Warn | Error | Null
+
 type logger =
 		{ stop: unit -> unit;
 		  restart: unit -> unit;
 		  rotate: unit -> unit;
-		  write: 'a. ('a, unit, string, unit) format4 -> 'a }
+		  write: ?level:level -> string -> unit }
 
 let truncate_line nb_chars line = 
 	if String.length line > nb_chars - 1 then
@@ -54,7 +85,7 @@ let log_rotate ref_ch log_file log_nb_files =
 	close_out !ref_ch;
 	ref_ch := open_out log_file
 
-let make_logger log_file log_nb_files log_nb_lines log_nb_chars post_rotate =
+let make_file_logger log_file log_nb_files log_nb_lines log_nb_chars post_rotate =
 	let channel = ref (open_out_gen [Open_append; Open_creat] 0o644 log_file) in
 	let counter = ref 0 in
 	let stop() =
@@ -67,22 +98,17 @@ let make_logger log_file log_nb_files log_nb_lines log_nb_chars post_rotate =
 		log_rotate channel log_file log_nb_files;
 		(post_rotate (): unit);
 		counter := 0 in
-	let output s =
+	let write ?level s =
 		let s = if log_nb_chars > 0 then truncate_line log_nb_chars s else s in
 		let s = s ^ "\n" in
 		output_string !channel s;
 		flush !channel;
 		incr counter;
 		if !counter > log_nb_lines then rotate() in
-	{ stop=stop; restart=restart; rotate=rotate; write = fun fmt -> Printf.ksprintf output fmt }
-
-
-(* Xenstored logger *) 
+	{ stop=stop; restart=restart; rotate=rotate; write=write }
 
 exception Unknown_level of string
 
-type level = Debug | Info | Warn | Error | Null
-
 let int_of_level = function
 	| Debug -> 0 | Info -> 1 | Warn -> 2
 	| Error -> 3 | Null -> max_int
@@ -104,30 +130,56 @@ let string_of_date () =
 		tm.Unix.tm_hour tm.Unix.tm_min tm.Unix.tm_sec
 		(int_of_float (1000.0 *. msec))
 
-let xenstored_log_file = ref "/var/log/xenstored.log"
+let make_syslog_logger facility =
+	(* We defer to syslog for log management *)
+	let nothing () = () in
+	let write ?level s =
+		let level = match level with
+			| Some Error -> Syslog.Err
+			| Some Warn -> Syslog.Warning
+			| Some Info -> Syslog.Info
+			| Some Debug -> Syslog.Debug
+			| Some Null -> Syslog.Debug
+			| None -> Syslog.Debug in
+		(* Syslog handles the date and level internally *)
+		Syslog.log facility level s in
+	{ stop = nothing; restart = nothing; rotate = nothing; write=write }
+
+let xenstored_log_destination = ref (File "/var/log/xenstored.log")
 let xenstored_log_level = ref Warn
 let xenstored_log_nb_files = ref 10
 let xenstored_log_nb_lines = ref 13215
 let xenstored_log_nb_chars = ref (-1)
 let xenstored_logger = ref (None: logger option)
 
-let init_xenstored_log () =
-	if !xenstored_log_level <> Null && !xenstored_log_nb_files > 0 then
-		let logger =
-			make_logger 
-				!xenstored_log_file !xenstored_log_nb_files !xenstored_log_nb_lines
-				!xenstored_log_nb_chars ignore in
-		let date = string_of_date() in
-		logger.write ("[%s|%5s|%s] Xen Storage Daemon, version %d.%d") date "" "startup"
-		  Define.xenstored_major Define.xenstored_minor;
-		xenstored_logger := Some logger
+let set_xenstored_log_destination s =
+	xenstored_log_destination := log_destination_of_string s
+
+let set_xenstored_logger logger =
+	xenstored_logger := Some logger;
+	logger.write ~level:Info (Printf.sprintf "Xen Storage Daemon, version %d.%d"
+	Define.xenstored_major Define.xenstored_minor)
+
+
+let init_xenstored_log () = match !xenstored_log_destination with
+	| File file ->
+		if !xenstored_log_level <> Null && !xenstored_log_nb_files > 0 then
+			let logger =
+				make_file_logger 
+					file !xenstored_log_nb_files !xenstored_log_nb_lines
+					!xenstored_log_nb_chars ignore in
+			set_xenstored_logger logger
+	| Syslog facility ->
+		set_xenstored_logger (make_syslog_logger facility)
+
 
 let xenstored_logging level key (fmt: (_,_,_,_) format4) =
 	match !xenstored_logger with
 	| Some logger when int_of_level level >= int_of_level !xenstored_log_level ->
 			let date = string_of_date() in
-			let level = string_of_level level in
-			logger.write ("[%s|%5s|%s] " ^^ fmt) date level key
+			let level' = string_of_level level in
+			let prefix = prefix !xenstored_log_destination ~level:level' ~key date in
+			Printf.ksprintf (fun s -> logger.write ~level (prefix ^ s)) fmt
 	| _ -> Printf.ksprintf ignore fmt
 
 let debug key = xenstored_logging Debug key
@@ -200,7 +252,7 @@ let sanitize_data data =
 	String.escaped data
 
 let activate_access_log = ref true
-let access_log_file = ref "/var/log/xenstored-access.log"
+let access_log_destination = ref (File "/var/log/xenstored-access.log")
 let access_log_nb_files = ref 20
 let access_log_nb_lines = ref 13215
 let access_log_nb_chars = ref 180
@@ -209,14 +261,20 @@ let access_log_transaction_ops = ref false
 let access_log_special_ops = ref false
 let access_logger = ref None
 
-let init_access_log post_rotate =
-	if !access_log_nb_files > 0 then
-		let logger =
-			make_logger
-				!access_log_file !access_log_nb_files !access_log_nb_lines
-				!access_log_nb_chars post_rotate in
-		access_logger := Some logger
- 
+let set_access_log_destination s =
+	access_log_destination := log_destination_of_string s
+
+let init_access_log post_rotate = match !access_log_destination with
+	| File file ->
+		if !access_log_nb_files > 0 then
+			let logger =
+				make_file_logger
+					file !access_log_nb_files !access_log_nb_lines
+					!access_log_nb_chars post_rotate in
+			access_logger := Some logger
+	| Syslog facility ->
+		access_logger := Some (make_syslog_logger facility)
+
 let access_logging ~con ~tid ?(data="") access_type =
         try
 		maybe
@@ -225,7 +283,9 @@ let access_logging ~con ~tid ?(data="") access_type =
 				let tid = string_of_tid ~con tid in
 				let access_type = string_of_access_type access_type in
 				let data = sanitize_data data in
-				logger.write "[%s] %s %s %s" date tid access_type data)
+				let prefix = prefix !access_log_destination date in
+				let msg = Printf.sprintf "%s %s %s %s" prefix tid access_type data in
+				logger.write msg)
 			!access_logger
 	with _ -> ()
 
diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml
index 64cc106..3416666 100644
--- a/tools/ocaml/xenstored/xenstored.ml
+++ b/tools/ocaml/xenstored/xenstored.ml
@@ -87,13 +87,13 @@ let parse_config filename =
 		("quota-maxsize", Config.Set_int Quota.maxsize);
 		("test-eagain", Config.Set_bool Transaction.test_eagain);
 		("persistent", Config.Set_bool Disk.enable);
-		("xenstored-log-file", Config.Set_string Logging.xenstored_log_file);
+		("xenstored-log-file", Config.String Logging.set_xenstored_log_destination);
 		("xenstored-log-level", Config.String
 			(fun s -> Logging.xenstored_log_level := Logging.level_of_string s));
 		("xenstored-log-nb-files", Config.Set_int Logging.xenstored_log_nb_files);
 		("xenstored-log-nb-lines", Config.Set_int Logging.xenstored_log_nb_lines);
 		("xenstored-log-nb-chars", Config.Set_int Logging.xenstored_log_nb_chars);
-		("access-log-file", Config.Set_string Logging.access_log_file);
+		("access-log-file", Config.String Logging.set_access_log_destination);
 		("access-log-nb-files", Config.Set_int Logging.access_log_nb_files);
 		("access-log-nb-lines", Config.Set_int Logging.access_log_nb_lines);
 		("access-log-nb-chars", Config.Set_int Logging.access_log_nb_chars);
-- 
1.8.1.2

  parent reply	other threads:[~2013-03-20 10:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-20 10:32 oxenstored: Add support for logging via syslog David Scott
2013-03-20 10:32 ` [PATCH 1/3] oxenstored: Re-add ocaml syslog binding David Scott
2013-03-20 10:32 ` David Scott [this message]
2013-03-20 10:32 ` [PATCH 3/3] oxenstored: Allow oxenstored to use syslog at levels other than Debug David Scott
2013-04-11 11:16 ` oxenstored: Add support for logging via syslog Ian Campbell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1363775565-4367-3-git-send-email-dave.scott@eu.citrix.com \
    --to=dave.scott@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).