ticklog 0.1.2

A fast, minimal logging library for Rust, designed for performance-critical applications, e.g. high-frequency trading.
Documentation
# Changelog

All notable changes to this project are documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.1.2] - 2026-09-11

### Added

- Thread metadata in every record: the id and name of the thread that logged it.
  Both are selectable in a log-line pattern with `{thread_id}` and
  `{thread_name}`.
- A `format` key in `configure!` for custom log-line patterns. The available
  placeholders are `{timestamp}`, `{level}`, `{file}`, `{line}`, `{thread_id}`,
  `{thread_name}`, and `{message}`. Every placeholder accepts an optional format
  spec except `{timestamp}` and `{message}`, which take none. The default
  pattern is `{timestamp} {level} {file}:{line} {message}`.

### Changed

- The default log line separates the timestamp and the level with one space
  rather than two:

  ```text
  2026-09-11T15:06:42.808227159Z INFO src/main.rs:12 listening
  ```

- Thread names are no longer optional and default to `<unnamed>`.
- A log-line pattern no longer needs a `'static` lifetime.

### Fixed

- A log-line pattern that repeats the `{message}` placeholder is rejected.
- Truncating an over-long thread name no longer splits a multi-byte UTF-8
  character.
- Optional record sections are written only when their header flag is set, so a
  record with no source location is no longer misparsed.

## [0.1.1] - 2026-07-26

### Added

- `configure!`, a macro that reads the logger configuration at compile time:

  ```rust
  let _guard = ticklog::configure! {
      sink: ConsoleSink::stderr(),
      max_level: Level::Trace,
  }
  .unwrap();
  ```

### Removed

- `builder()`, `Builder`, and `init()`, replaced by `configure!`. Configuration
  is no longer assembled at runtime.

### Changed

- Relicensed from MIT to `MIT OR Apache-2.0`.

### Performance

- Records are written directly into the ring buffer, removing an intermediate
  copy on the calling thread.
- The timestamp is acquired after a ring buffer slot is reserved, rather than
  before.

### Fixed

- A record whose declared total size does not match its header is rejected when
  draining, instead of being parsed past its end.
- Ring buffer pointers are reconstructed with strict provenance.

## [0.1.0] - 2026-07-15

### Added

- Initial release. `trace!`, `debug!`, `info!`, `warn!`, and `error!` encode a
  record and hand it to a per-thread ring buffer, with no allocation,
  formatting, or I/O on the calling thread. A background drain thread decodes
  records and writes formatted lines to a sink.
- `ConsoleSink`, `FileSink`, and `WriterSink` write to stdout, stderr, files,
  and any `io::Write`. `FanOut` dispatches one record to several sinks, and
  `with_max_level` filters a sink by level. Custom destinations implement the
  `LogSink` trait.
- `Level` sets the level ceiling and `Backpressure` sets what a logging thread
  does when its buffer is full.
- `pin_thread` pins the calling thread to a set of logical CPUs and `warm_up`
  pre-allocates a thread's buffer, keeping the first log call off a
  latency-sensitive path.

[Unreleased]: https://github.com/tensorbinge/ticklog/compare/v0.1.2...HEAD
[0.1.2]: https://github.com/tensorbinge/ticklog/compare/v0.1.1...v0.1.2
[0.1.1]: https://github.com/tensorbinge/ticklog/compare/v0.1.0...v0.1.1
[0.1.0]: https://github.com/tensorbinge/ticklog/releases/tag/v0.1.0