Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/clippy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# We use `actions-rs` for most of our actions
on: [push, pull_request]
name: Clippy

env:
CARGO_TERM_COLOR: always
# has a history of occasional bugs (especially on old versions)
#
# the ci is free so we might as well use it ;)
CARGO_INCREMENTAL: 0


jobs:
clippy:
# Only run on PRs if the source branch is on someone else's repo
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
rust:
# in hardcoded versions, warnings will fail the build
- 1.89
# in auto-updated versions, warnings will not fail the build
- stable
- nightly

steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
components: clippy
- name: Clippy
run: |
cargo clippy --all --all-targets --verbose --all-features -- -D warnings
# When using hardcoded/pinned versions, warnings are forbidden.
#
# On automatically updated versions of rust (both stable & nightly) we allow clippy to fail.
# This is because automatic updates can introduce new lints or change existing lints.
continue-on-error: ${{ !contains(matrix.rust, '1.') }}
24 changes: 24 additions & 0 deletions .github/workflows/rustfmt.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# The file is the workflow for rustfmt
#
# It runs `cargo fmt --check`
#
# It will fail if there are formatting problems.
on: [push, pull_request]
name: rustfmt

env:
CARGO_TERM_COLOR: always

jobs:
rustfmt:
# Only run on PRs if the source branch is on someone else's repo
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- shell: bash
run: |
cargo fmt -- --check
20 changes: 20 additions & 0 deletions .github/workflows/spellcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Checks spelling with typos
# This has very few false positives, only checking for known misspellings (similar to codespell).
# This action is based on https://github.com/crate-ci/typos/blob/master/docs/github-action.md
name: Check Spelling
on: [push, pull_request]

env:
CLICOLOR: 1

permissions:
contents: read

jobs:
typos:
name: Check spelling with typos
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run typos (pinned version)
uses: crate-ci/[email protected]
18 changes: 14 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ jobs:
strategy:
fail-fast: false # Even if one job fails we still want to see the other ones
matrix:
# 1.59 is MSRV
rust: [1.59, stable, nightly]
# 1.61 is MSRV
rust: [1.61, stable, nightly]
# NOTE: Features to test must be specified manually. They are applied to all versions separately.
#
# This has the advantage of being more flexibile and thorough
# This has the disadvantage of being more vebrose
# This has the advantage of being more flexible and thorough
# This has the disadvantage of being more verbose
#
# Specific feature combos can be overridden per-version with 'include' and 'ecclude'
features: ["", "nested-values", "dynamic-keys", "nested-values dynamic-keys"]
Expand All @@ -43,6 +43,16 @@ jobs:
with:
toolchain: ${{ matrix.rust }}
override: true
- name: Cache Cargo Registry
id: cache-index
uses: actions/cache@v4
with:
path:
# Before the sparse index, updating the registry took forever
~/.cargo/registry/index/
key: ${{ runner.os }}-cargo-${{ matrix.rust }}
restore-keys: |
${{ runner.os }}-cargo-
- name: Check
# A failing `cargo check` always ends the build
run: |
Expand Down
13 changes: 13 additions & 0 deletions .typos.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[default]
extend-ignore-re = [
# support spellchecker directives (ideally this would be builtin)
"(?Rm)^.*(#|//)\\s*spellchecker:ignore$",
"(?s)(#|//)\\s*spellchecker:off.*?\\n\\s*(#|//)\\s*spellchecker:on",
]

[files]
ignore-hidden = false
extend-exclude = [
".git", # needed because we set 'ignore-hidden'
]

5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

* Define minimum supported rust version.
* Update to Rust 2018. Does not affect compatibility with crates still using Rust 2015.
* Bump MSRV to 1.61 (first time officially defined)
* Unconditionally support 128-bit integers.
* Fix all clippy warnings
* Setup Github Actions.
* Fixup some minor typos in CHANGELOG.md, including an incorrect release date for 2.8.0.

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ documentation = "https://docs.rs/slog-async"
homepage = "https://github.com/slog-rs/slog"
repository = "https://github.com/slog-rs/async"
readme = "README.md"
rust-version = "1.59.0"
rust-version = "1.61"
edition = "2021"

[features]
nested-values = ["slog/nested-values"]
Expand Down
53 changes: 0 additions & 53 deletions build.rs

This file was deleted.

67 changes: 40 additions & 27 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,24 @@

// {{{ Imports & meta
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate crossbeam_channel;
extern crate take_mut;
extern crate thread_local;
#![warn(
rust_2018_idioms,
rust_2018_compatibility,
rust_2021_compatibility,
future_incompatible
)]
#![allow(
// covered by mismatched_lifetime_syntaxes
elided_lifetimes_in_paths,
)]

use crossbeam_channel::Sender;

use slog::Drain;
use slog::{b, o, record};
use slog::{BorrowedKV, Level, Record, RecordStatic, SingleKV, KV};
use slog::{Key, OwnedKVList, Serializer};

use slog::Drain;
use std::fmt;
use std::sync;
use std::{io, thread};
Expand Down Expand Up @@ -147,12 +152,10 @@ impl Serializer for ToSendSerializer {
take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val))));
Ok(())
}
#[cfg(integer128)]
fn emit_u128(&mut self, key: Key, val: u128) -> slog::Result {
take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val))));
Ok(())
}
#[cfg(integer128)]
fn emit_i128(&mut self, key: Key, val: i128) -> slog::Result {
take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val))));
Ok(())
Expand Down Expand Up @@ -184,7 +187,7 @@ impl Serializer for ToSendSerializer {
fn emit_serde(
&mut self,
key: Key,
value: &slog::SerdeValue,
value: &dyn slog::SerdeValue,
) -> slog::Result {
let val = value.to_sendable();
take(&mut self.kv, |kv| Box::new((kv, SingleKV(key, val))));
Expand Down Expand Up @@ -443,7 +446,7 @@ impl AsyncCore {
) -> Result<
&crossbeam_channel::Sender<AsyncMsg>,
std::sync::PoisonError<
sync::MutexGuard<crossbeam_channel::Sender<AsyncMsg>>,
sync::MutexGuard<'_, crossbeam_channel::Sender<AsyncMsg>>,
>,
> {
self.tl_sender.get_or_try(|| Ok(self.ref_sender.clone()))
Expand Down Expand Up @@ -508,7 +511,7 @@ impl AsyncRecord {
/// Writes the record to a `Drain`.
pub fn log_to<D: Drain>(self, drain: &D) -> Result<D::Ok, D::Err> {
let rs = RecordStatic {
location: &*self.location,
location: &self.location,
level: self.level,
tag: &self.tag,
};
Expand All @@ -526,7 +529,7 @@ impl AsyncRecord {
/// Deconstruct this `AsyncRecord` into a record and `OwnedKVList`.
pub fn as_record_values(&self, mut f: impl FnMut(&Record, &OwnedKVList)) {
let rs = RecordStatic {
location: &*self.location,
location: &self.location,
level: self.level,
tag: &self.tag,
};
Expand Down Expand Up @@ -582,6 +585,7 @@ impl Drop for AsyncCore {
///
/// More variants may be added in the future, without considering it a breaking change.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
#[non_exhaustive]
pub enum OverflowStrategy {
/// The message gets dropped and a message with number of dropped is produced once there's
/// space.
Expand All @@ -595,8 +599,6 @@ pub enum OverflowStrategy {
Drop,
/// The caller is blocked until there's enough space.
Block,
#[doc(hidden)]
DoNotMatchAgainstThisAndReadTheDocs,
}

/// `Async` builder
Expand Down Expand Up @@ -638,9 +640,6 @@ where
OverflowStrategy::Block => (true, false),
OverflowStrategy::Drop => (false, false),
OverflowStrategy::DropAndReport => (false, true),
OverflowStrategy::DoNotMatchAgainstThisAndReadTheDocs => {
panic!("Invalid variant")
}
};
AsyncBuilder {
core: self.core.blocking(block),
Expand Down Expand Up @@ -739,6 +738,7 @@ impl Async {
/// The wrapped drain must handle all results (`Drain<Ok=(),Error=Never>`)
/// since there's no way to return it back. See `slog::DrainExt::fuse()` and
/// `slog::DrainExt::ignore_res()` for typical error handling strategies.
#[allow(clippy::new_ret_no_self)] // would break compat
pub fn new<D: slog::Drain<Err = slog::Never, Ok = ()> + Send + 'static>(
drain: D,
) -> AsyncBuilder<D> {
Expand Down Expand Up @@ -806,26 +806,31 @@ impl Drop for Async {

// }}}


#[cfg(test)]
mod test {
use super::*;
use slog::{info, warn};
use std::sync::mpsc;

#[test]
fn integration_test() {
let (mock_drain, mock_drain_rx) = MockDrain::new();
let async_drain = AsyncBuilder::new(mock_drain)
.build();
let slog = slog::Logger::root(async_drain.fuse(), o!("field1" => "value1"));
let async_drain = AsyncBuilder::new(mock_drain).build();
let slog =
slog::Logger::root(async_drain.fuse(), o!("field1" => "value1"));

info!(slog, "Message 1"; "field2" => "value2");
warn!(slog, "Message 2"; "field3" => "value3");
assert_eq!(mock_drain_rx.recv().unwrap(), r#"INFO Message 1: [("field1", "value1"), ("field2", "value2")]"#);
assert_eq!(mock_drain_rx.recv().unwrap(), r#"WARN Message 2: [("field1", "value1"), ("field3", "value3")]"#);
assert_eq!(
mock_drain_rx.recv().unwrap(),
r#"INFO Message 1: [("field1", "value1"), ("field2", "value2")]"#
);
assert_eq!(
mock_drain_rx.recv().unwrap(),
r#"WARN Message 2: [("field1", "value1"), ("field3", "value3")]"#
);
}


/// Test-helper drain
#[derive(Debug)]
struct MockDrain {
Expand All @@ -843,7 +848,11 @@ mod test {
type Ok = ();
type Err = slog::Never;

fn log(&self, record: &Record, logger_kv: &OwnedKVList) -> Result<Self::Ok, Self::Err> {
fn log(
&self,
record: &Record,
logger_kv: &OwnedKVList,
) -> Result<Self::Ok, Self::Err> {
let mut serializer = MockSerializer::default();
logger_kv.serialize(record, &mut serializer).unwrap();
record.kv().serialize(record, &mut serializer).unwrap();
Expand All @@ -861,7 +870,11 @@ mod test {
}

impl slog::Serializer for MockSerializer {
fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> Result<(), slog::Error> {
fn emit_arguments(
&mut self,
key: Key,
val: &fmt::Arguments,
) -> Result<(), slog::Error> {
self.kvs.push((key.to_string(), val.to_string()));
Ok(())
}
Expand Down
Loading