Skip to content
This repository has been archived by the owner on Jun 8, 2024. It is now read-only.

Commit

Permalink
document some types in emit
Browse files Browse the repository at this point in the history
  • Loading branch information
KodrAus committed May 22, 2024
1 parent 0527131 commit de82230
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 84 deletions.
77 changes: 69 additions & 8 deletions src/kind.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*!
The [`Kind`] type.
*/

use core::{fmt, str::FromStr};

use emit_core::{
Expand All @@ -8,10 +12,46 @@ use emit_core::{
well_known::{EVENT_KIND_METRIC, EVENT_KIND_SPAN, KEY_EVENT_KIND},
};

/**
A kind of specialized diagnostic event.
If a [`crate::Event`] has a kind associated with it, it can be pulled from its props:
```
# use emit::{Event, Props};
# fn with_event(evt: impl emit::event::ToEvent) {
# let evt = evt.to_event();
match evt.props().pull::<emit::Kind, _>(emit::well_known::KEY_EVENT_KIND) {
Some(emit::Kind::Span) => {
// The event is a span
}
Some(emit::Kind::Metric) => {
// The event is a metric
}
Some(_) => {
// The event is an unknown kind
}
None => {
// The event doesn't have a specific kind
}
}
# }
```
*/
#[non_exhaustive]
#[derive(PartialEq, Eq, Hash, Clone, Copy)]
pub enum Kind {
/**
The event is a span in a distributed trace.
This variant is equal to [`EVENT_KIND_SPAN`]. See the [`mod@crate::span`] module for details.
*/
Span,
/**
The event is a metric sample.
This variant is equal to [`EVENT_KIND_METRIC`]. See the [`mod@crate::metric`] module for details.
*/
Metric,
}

Expand Down Expand Up @@ -61,25 +101,46 @@ impl FromStr for Kind {
}
}

/**
An error attempting to parse a [`Kind`] from text.
*/
pub struct ParseKindError {}

pub struct IsKind(Kind);
/**
A [`Filter`] that matches events with a specific [`Kind`].
impl IsKind {
The kind to match is pulled from the [`KEY_EVENT_KIND`] well-known property. Events that don't carry any kind are not matched.
*/
pub struct KindFilter(Kind);

impl KindFilter {
/**
Create a filter that only matches events carrying the same kind.
*/
pub fn new(kind: Kind) -> Self {
IsKind(kind)
KindFilter(kind)
}
}

pub fn is_span_filter() -> IsKind {
IsKind::new(Kind::Span)
/**
Only match events that are spans in a distributed trace.
Events that match must carry a [`Kind::Span`].
*/
pub fn is_span_filter() -> KindFilter {
KindFilter::new(Kind::Span)
}

pub fn is_metric_filter() -> IsKind {
IsKind::new(Kind::Metric)
/**
Only match events that are metric samples.
Events that match must carry a [`Kind::Metric`].
*/
pub fn is_metric_filter() -> KindFilter {
KindFilter::new(Kind::Metric)
}

impl Filter for IsKind {
impl Filter for KindFilter {
fn matches<E: ToEvent>(&self, evt: E) -> bool {
evt.to_event().props().pull::<Kind, _>(KEY_EVENT_KIND) == Some(self.0)
}
Expand Down
128 changes: 107 additions & 21 deletions src/level.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/*!
The [`Level`] type.
*/

use emit_core::{
event::ToEvent,
filter::Filter,
Expand All @@ -10,14 +14,68 @@ use emit_core::{
use crate::value::{ToValue, Value};
use core::{fmt, str::FromStr};

/**
A severity level for a diagnostic event.
If a [`crate::Event`] has a level associated with it, it can be pulled from its props:
```
# use emit::{Event, Props};
# fn with_event(evt: impl emit::event::ToEvent) {
# let evt = evt.to_event();
match evt.props().pull::<emit::Level, _>(emit::well_known::KEY_LVL).unwrap_or_default() {
emit::Level::Debug => {
// The event is at the debug level
}
emit::Level::Info => {
// The event is at the info level
}
emit::Level::Warn => {
// The event is at the warn level
}
emit::Level::Error => {
// The event is at the error level
}
}
# }
```
The default level is [`Level::Info`].
*/
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Level {
/**
The event is weakly informative.
This variant is equal to [`LVL_DEBUG`].
*/
Debug,
/**
The event is informative.
This variant is equal to [`LVL_INFO`].
*/
Info,
/**
The event is weakly erroneous.
This variant is equal to [`LVL_WARN`].
*/
Warn,
/**
The event is erroneous.
This variant is equal to [`LVL_ERROR`].
*/
Error,
}

impl Default for Level {
fn default() -> Self {
Level::Info
}
}

impl fmt::Debug for Level {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "\"{}\"", self)
Expand Down Expand Up @@ -83,15 +141,12 @@ fn parse(
Ok(ok)
}

/**
An error attempting to parse a [`Level`] from text.
*/
#[derive(Debug)]
pub struct ParseLevelError {}

impl Default for Level {
fn default() -> Self {
Level::Info
}
}

impl ToValue for Level {
fn to_value(&self) -> Value {
Value::capture_display(self)
Expand All @@ -107,36 +162,50 @@ impl<'v> FromValue<'v> for Level {
}
}

pub fn min_filter(min: Level) -> MinLevel {
MinLevel::new(min)
/**
Only match events that carry the given [`Level`].
*/
pub fn min_filter(min: Level) -> MinLevelFilter {
MinLevelFilter::new(min)
}

pub struct MinLevel {
/**
A [`Filter`] that matches events with a specific [`Level`].
The level to match is pulled from the [`KEY_LVL`] well-known property. Events that don't carry any specific level are treated as carrying a default one, as set by [`MinLevelFilter::treat_unleveled_as`].
*/
pub struct MinLevelFilter {
min: Level,
default: Level,
}

impl From<Level> for MinLevel {
impl From<Level> for MinLevelFilter {
fn from(min: Level) -> Self {
MinLevel::new(min)
MinLevelFilter::new(min)
}
}

impl MinLevel {
pub const fn new(min: Level) -> MinLevel {
MinLevel {
impl MinLevelFilter {
/**
Construct a new [`MinLevelFilter`], treating unleveled events as [`Level::default`].
*/
pub const fn new(min: Level) -> MinLevelFilter {
MinLevelFilter {
min,
default: Level::Debug,
default: Level::Info,
}
}

/**
Treat events without an explicit level as having `default` when evaluating against the filter.
*/
pub fn treat_unleveled_as(mut self, default: Level) -> Self {
self.default = default;
self
}
}

impl Filter for MinLevel {
impl Filter for MinLevelFilter {
fn matches<E: ToEvent>(&self, evt: E) -> bool {
evt.to_event()
.props()
Expand All @@ -146,7 +215,7 @@ impl Filter for MinLevel {
}
}

impl InternalFilter for MinLevel {}
impl InternalFilter for MinLevelFilter {}

#[cfg(feature = "alloc")]
mod alloc_support {
Expand All @@ -156,25 +225,42 @@ mod alloc_support {

use emit_core::path::Path;

pub fn min_by_path_filter<P: Into<Path<'static>>, L: Into<MinLevel>>(
/**
Construct a set of [`MinLevelFilter`]s that are applied based on the module of an event.
*/
pub fn min_by_path_filter<P: Into<Path<'static>>, L: Into<MinLevelFilter>>(
levels: impl IntoIterator<Item = (P, L)>,
) -> MinLevelPathMap {
MinLevelPathMap::from_iter(levels)
}

/**
A filter that applies a [`MinLevelFilter`] based on the module of an event.
This type allows different modules to apply different level filters. In particular, modules generating a lot of diagnostic noise can be silenced without affecting other modules.
Event modules are matched based on [`Path::is_child_of`]. If an event's module is a child of one in the map then its [`MinLevelFilter`] will be checked against it. If an event's module doesn't match any in the map then it will pass the filter.
*/
pub struct MinLevelPathMap {
paths: Vec<(Path<'static>, MinLevel)>,
// TODO: Ensure more specific paths apply ahead of less specific ones
paths: Vec<(Path<'static>, MinLevelFilter)>,
}

impl MinLevelPathMap {
/**
Create an empty map.
*/
pub const fn new() -> Self {
MinLevelPathMap { paths: Vec::new() }
}

/**
Specify the minimum level for a module and its children.
*/
pub fn min_level(
&mut self,
path: impl Into<Path<'static>>,
min_level: impl Into<MinLevel>,
min_level: impl Into<MinLevelFilter>,
) {
let path = path.into();

Expand Down Expand Up @@ -211,7 +297,7 @@ mod alloc_support {

impl InternalFilter for MinLevelPathMap {}

impl<P: Into<Path<'static>>, L: Into<MinLevel>> FromIterator<(P, L)> for MinLevelPathMap {
impl<P: Into<Path<'static>>, L: Into<MinLevelFilter>> FromIterator<(P, L)> for MinLevelPathMap {
fn from_iter<T: IntoIterator<Item = (P, L)>>(iter: T) -> Self {
let mut map = MinLevelPathMap::new();

Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -505,8 +505,9 @@ impl emit::Emitter for MyEmitter {
println!("{}", evt.to_event().msg());
}
fn blocking_flush(&self, _: std::time::Duration) {
fn blocking_flush(&self, _: std::time::Duration) -> bool {
// Nothing to flush
true
}
}
Expand Down
Loading

0 comments on commit de82230

Please sign in to comment.