I was going through the syslog
crate, and from my function, I wanted to return a logger object which I believe is of a generic struct syslog::Logger
. Most of the below piece is taken from the crate documentation except for the return part and unwrap().
extern crate syslog;
use syslog::{Facility, Error, Formatter3164};
pub fn get_logger() -> syslog::Logger{
let formatter = Formatter3164 {
facility: Facility::LOG_USER,
hostname: None,
process: "myprogram".into(),
pid: 0,
};
syslog::unix(formatter).unwrap()
}
However I am seeing
pub fn get_logger() -> syslog::Logger{
^^^^^^^^^^^^^^ expected 3 type arguments
The signature of syslog::Logger
struct is
pub struct Logger<Backend: Write, T, Formatter: LogFormat<T>>
and the signature of syslog::unix
is
pub fn unix<U: Display, F: Clone+LogFormat<U>>(formatter: F) -> Result<Logger<LoggerBackend, U, F>> {
where Display
is std::fmt::Display
and LogFormat
is a trait defined in syslog
crate with the following definition.
pub trait LogFormat<T> {
fn format<W: Write>(&self, w: &mut W, severity: Severity, message: T) -> Result<()>;
fn emerg<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_EMERG, message)
}
fn alert<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_ALERT, message)
}
fn crit<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_CRIT, message)
}
fn err<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_ERR, message)
}
fn warning<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_WARNING, message)
}
fn notice<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_NOTICE, message)
}
fn info<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_INFO, message)
}
fn debug<W: Write>(&mut self, w: &mut W, message: T) -> Result<()> {
self.format(w, Severity::LOG_DEBUG, message)
}
}
This is a generic struct, so what would be the type's signature that I should return if I want to return a logger object from my function?
The only optional parameter here is T
. This is the type of the message you want when you are logging. E.g. in the below example, the log message type is a &str
:
let mut logger = get_logger();
logger.info("This is a log message");
You can either choose the type inside get_logger
, and put it in its signature, or make get_logger
generic, and have the call site decide.
The first approach looks like this:
extern crate syslog;
use syslog::{Facility, Error, Formatter3164, LoggerBackend};
fn get_logger<'a>() -> syslog::Logger<LoggerBackend, &'a str, Formatter3164>{
let formatter = Formatter3164 {
facility: Facility::LOG_USER,
hostname: None,
process: "myprogram".into(),
pid: 0,
};
syslog::unix(formatter).unwrap()
}
pub fn main(){
let mut logger = get_logger();
logger.info("This is a log message");
}
And the generic approach looks like this.
extern crate syslog;
use syslog::{Facility, Error, Formatter3164, LoggerBackend};
pub fn get_logger<T: std::fmt::Display>() -> syslog::Logger<LoggerBackend, T, Formatter3164>{
let formatter = Formatter3164 {
facility: Facility::LOG_USER,
hostname: None,
process: "myprogram".into(),
pid: 0,
};
syslog::unix(formatter).unwrap()
}
pub fn main(){
let mut logger = get_logger();
logger.info("This is a log message");
}