Crate slog_extlog
source ·Expand description
External logging and statistics tracking API for slog
.
This crate adds support for two features to the slog ecosystem.
Generating “external” logs
External logs are logs that form an API and so must not be modified or removed without agreeing as a spec change. New logs can always safely be added.
The real advantage of external logs is that the log itself becomes a type, therefore guaranteeing that required fields must always be provided and giving compile-time checking of log generation.
When using this crate, slog loggers can be used in two ways.
- External logs can be defined using this crate, and then logged using
a
StatisticsLogger
. They can also be used as triggers for statistics generation. - For internal, low-level logging, the usual slog macros (
info!
,debug!
,trace!
etc) can be used.
Any object can be made into an external log by implementing ExtLoggable
. In nearly all
cases this trait should be automatically derived using the
slog-extlog-derive
crate.
Log objects
To use this crate to define external logs:
- Add
slog-extlog
with thederive
feature enabled to yourCargo.toml
.
To make a new external log using this crate:
- Define a structure with appropriate fields to act as the log.
- Define a constant string named
CRATE_LOG_NAME
which uniquely identifies this crate in log identifiers. This must uniquely identify your crate. use slog_extlog_derive::ExtLoggable
and derive theExtLoggable
trait for this object.- If your structure is overly complex or unusual, manually implement
ExtLoggable
.
- If your structure is overly complex or unusual, manually implement
- Early in your program or libary, obtain or create a
Logger
of the correct format and wrap it in a [’StatisticsLogger`].
Unless you want to support statistics tracking, then the easiest way to obtain an
appropriate logger is to create a DefaultLogger
.
You can then call the [slog_extlog::xlog!()
] macro, passing in the StatisticsLogger
and
an instance of your structure, and it will be logged according to the Logger’s associated Drain
as usual.
Structure parameters will be added as key-value pairs, but with the bonus that you get
type checking.
You can continue to make developer logs simply using slog
as normal:
- Add
slog
to yourCargo.toml
. - Use the usual
slog
macros, e.g.,slog::debug!
.
Parameters
Parameters to external logs must implement slog::Value
.
For types you own, you can also derive slog::Value
using #[derive SlogValue]
from the
slog-extlog-derive
crate.
For types you do not own, you can define a wrapper type that implements Value
using
impl_value_wrapper
.
Statistics tracking
ExtLoggable
objects can automatically trigger changes to statistics tracked by the
associated [StatsLogger
].
To make this work, the following approach is required.
- Create a static set of statistic definitions using the
define_stats
macro. - Add
StatTrigger
attributes to each external log that explains which statistics the log should update.
The automatic derivation code then takes care of updating the statistics as and when required.
Example
An example of a simple program that defines and produces some basic logs.
use serde::Serialize;
use slog_extlog::{stats::DefaultStatisticsLogFormatter, stats::StatsLoggerBuilder, define_stats, xlog};
use slog_extlog_derive::{ExtLoggable, SlogValue};
use slog::{Drain, debug, info, o};
use std::sync::Mutex;
#[derive(Clone, Serialize, ExtLoggable)]
#[LogDetails(Id="101", Text="Foo Request received", Level="Info")]
struct FooReqRcvd;
#[derive(Clone, Serialize, ExtLoggable)]
#[LogDetails(Id="103", Text="Foo response sent", Level="Info")]
struct FooRspSent(FooRspCode);
#[derive(Clone, Serialize, SlogValue)]
enum FooRspCode {
Success,
InvalidUser,
}
#[derive(Clone, Serialize, SlogValue)]
enum FooMethod {
GET,
PATCH,
POST,
PUT,
}
#[derive(Clone, Serialize, SlogValue)]
struct FooContext {
id: String,
method: FooMethod,
}
const CRATE_LOG_NAME: &'static str = "FOO";
#[tokio::main]
async fn main() {
// Use a basic logger with some context.
let logger = slog::Logger::root(
Mutex::new(slog_json::Json::default(std::io::stdout())).map(slog::Fuse),
o!());
let logger = logger.new(o!("cxt" => FooContext {
id: "123456789".to_string(),
method: FooMethod::POST,
}));
let foo_logger = StatsLoggerBuilder::default().fuse(logger);
// Now make some logs...
xlog!(foo_logger, FooReqRcvd);
debug!(foo_logger, "Some debug info");
xlog!(foo_logger, FooRspSent(FooRspCode::Success));
let count = 1;
info!(foo_logger, "New counter value"; "count" => count);
}
Re-exports
pub use erased_serde;
Modules
- Copyright 2017 Metaswitch Networks
- Statistics generator for
slog
.
Macros
- A macro to define the statistics that can be tracked by the logger. Use of this macro requires
StatDefinition
to be in scope. - Generate a
slog::Value
trait implementation for a type we don’t own but which implementsstd::fmt::Display
orstd::fmt::Debug
. - Log an external log through an
slog::Logger
.
Traits
- An object that can be logged.
- A trait that defines requirements to be automatically derivable.
Type Aliases
- The default logger type.