Skip to content
Merged
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
4 changes: 3 additions & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -962,7 +962,9 @@ INPUT = ./include \
./docs/OtlpHttpLogger.md \
./docs/PrometheusLogger.md \
./docs/TaskExecutor.md \
./docs/backpressure.md
./docs/backpressure.md \
./docs/future-plans.md \
./docs/adr

# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
Expand Down
2 changes: 2 additions & 0 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ scope-замер.
- [`docs/PrometheusLogger.md`](docs/PrometheusLogger.md) — payload/server-бэкенды, registry, scrape и ограничения.
- [`docs/TaskExecutor.md`](docs/TaskExecutor.md) — варианты очереди, политики переполнения, hot resize и lifecycle.
- [`docs/backpressure.md`](docs/backpressure.md) — настройка очереди и счётчики отброшенных задач.
- [`docs/future-plans.md`](docs/future-plans.md) — чеклист roadmap с разделением готовых, планируемых и отложенных задач.
- [`docs/adr/README.md`](docs/adr/README.md) — архитектурные решения, границы публичного API и записи о совместимости.

## Примеры макросов

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ Detailed guides and documentation map:
- [`docs/PrometheusLogger.md`](docs/PrometheusLogger.md) — payload/server backends, registry metrics, scrape configuration, and limitations.
- [`docs/TaskExecutor.md`](docs/TaskExecutor.md) — queue variants, overflow policies, hot resize, and lifecycle guarantees.
- [`docs/backpressure.md`](docs/backpressure.md) — application-facing queue tuning and drop counters.
- [`docs/future-plans.md`](docs/future-plans.md) — checked roadmap separating delivered, planned, and deferred work.
- [`docs/adr/README.md`](docs/adr/README.md) — architecture decisions, public-boundary rationale, and compatibility records.

## Macro Examples

Expand Down
24 changes: 24 additions & 0 deletions docs/adr/0000-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ADR NNNN: Short decision title

- Status: Proposed
- Date: YYYY-MM-DD

## Context

What problem, constraint, or repeated failure mode requires a decision?

## Decision

State the chosen approach and its public contract precisely.

## Consequences

Describe benefits, costs, compatibility impact, and operational trade-offs.

## Alternatives considered

List the credible alternatives and why they were not selected.

## References

Link the implementation, tests, documentation, issues, or superseding ADRs.
31 changes: 31 additions & 0 deletions docs/adr/0001-aggregate-first-public-headers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ADR 0001: Aggregate-first public headers and API boundary

- Status: Accepted
- Date: 2026-09-14

## Context

The library has many historical leaf headers, including
`logit/log_macros.hpp`. Treating every header as independently includable made
include order accidental and made internal implementation details look public.

## Decision

`<logit.hpp>` is the supported application entry point. The module umbrellas
`<logit/utils.hpp>`, `<logit/formatter.hpp>`, and `<logit/loggers.hpp>` are
supported focused entry points. Leaf headers are standalone only when their
documentation and include-contract test explicitly say so. `logit/log_macros.hpp`
is an aggregate-owned implementation header and has no standalone-inclusion
guarantee. Public aliases, including `logit::QueuePolicy`, are consumed through
the umbrella or the relevant module umbrella.

## Consequences

The include contract is predictable and can evolve without promising every
historical file as an API boundary. Documentation and tests must use the
nearest supported umbrella, while implementation headers remain free to change.

## Alternatives considered

Making every leaf header self-contained would increase compile cost and freeze
implementation structure without adding value for normal application code.
25 changes: 25 additions & 0 deletions docs/adr/0002-async-executor-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ADR 0002: Shared and dedicated asynchronous executors

- Status: Accepted
- Date: 2026-09-14

## Context

Using one shared asynchronous executor is efficient for the default case, but
a slow backend can delay unrelated backends. A separate worker per backend
improves isolation at the cost of a thread and queue per opted-in backend.

## Decision

The shared `TaskExecutor` remains the default. Backends that support it expose
`Config::use_dedicated_executor`; when enabled for an asynchronous backend, it
owns a `SingleThreadExecutor` with its own queue, policy, wait, and shutdown
lifecycle. Platform-specific backends that cannot provide this behavior keep
their documented limitations.

## Consequences

Applications can choose throughput/resource sharing or isolation per backend.
The feature is already tested for lifecycle, mixed shared/dedicated operation,
and macro configuration. Changing the default is a separate compatibility and
resource-usage decision.
25 changes: 25 additions & 0 deletions docs/adr/0003-immutable-registry-snapshots.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ADR 0003: Immutable logger registry snapshots

- Status: Accepted
- Date: 2026-09-14

## Context

Copying the mutable logger registry under a read lock on every log call made
the normal dispatch path pay synchronization and allocation costs. Logger
registry mutations and reconfiguration are infrequent compared with logging.

## Decision

Publish an immutable copy-on-write strategy-list snapshot on registry changes.
The hot path reads it with an atomic `shared_ptr` load. Mutable `enabled` and
`single_mode` state is atomic. The per-strategy execution mutex remains around
formatter/backend invocation because custom formatters and backends do not
have a universal concurrent-invocation contract.

## Consequences

Normal dispatch avoids the registry mutex and temporary vector copy while
preserving safe lifetime and mutation semantics. A future lock-elision path
requires an explicit capability contract and separate regression coverage; a
benchmark sink alone is not evidence that arbitrary backends are thread-safe.
25 changes: 25 additions & 0 deletions docs/adr/0004-timeshield-compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# ADR 0004: TimeShield compatibility and dependency reuse

- Status: Accepted
- Date: 2026-09-14

## Context

The current TimeShield release is `v2.0.0`, whose CMake package uses
`SameMinorVersion` compatibility. Consumers may provide dependency targets
from a parent project or sibling build instead of installing another package
configuration.

## Decision

Pin the bundled submodule to the `v2.0.0` release and request
`TimeShield 2.0.0`, which expresses the supported `2.0.x` line. Before package
discovery, reuse an existing `time_shield::time_shield` target; installed
dependency discovery follows the same target-reuse rule for optional packages.

## Consequences

Build-tree and installed-package consumers remain composable, while the
minimum supported TimeShield API is explicit. Moving to another minor line or
changing the compatibility policy requires a new compatibility review and
release note.
27 changes: 27 additions & 0 deletions docs/adr/0005-benchmark-methodology.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# ADR 0005: Benchmark evidence and comparison methodology

- Status: Accepted
- Date: 2026-09-14

## Context

Prepared records, the public macro path, formatted output, and external
library adapters measure different work. Mixing them into one number produces
misleading claims, and short CI runners are not a substitute for a fixed
publication machine.

## Decision

Keep separate scenarios for prepared-record dispatch, the real public
`LOGIT_INFO(...)` path, formatting, and external-library comparisons. The
public macro smoke benchmark may use a passthrough formatter when it is
explicitly documented as record-construction/dispatch coverage. Report
absolute timings only with compiler, platform, commit, queue, producer, and
flush settings; treat CI runs as regression smoke unless the environment is
fixed.

## Consequences

Benchmark documentation remains comparable and honest across changes. New
scenarios require their own workload contract and should not silently replace
historical measurements.
30 changes: 30 additions & 0 deletions docs/adr/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Architecture Decision Records

Architecture Decision Records (ADRs) capture decisions that should remain
discoverable after the implementation or the original discussion changes.
They complement the roadmap: the roadmap says **what is next**, while an ADR
explains **why the current boundary or trade-off exists**.

## Statuses

- **Proposed** — under discussion; do not treat it as a public contract.
- **Accepted** — the current implementation and documentation should follow it.
- **Superseded** — replaced by a newer ADR; retain it for historical context.
- **Rejected** — considered and intentionally not adopted.

## Creating an ADR

1. Copy [`0000-template.md`](0000-template.md) to the next zero-padded number.
2. Use a short, stable title and set the status/date.
3. Describe the context, decision, consequences, and rejected alternatives.
4. Update the implementation and user-facing documentation in the same change
when the decision changes a public contract.
5. Link a superseding ADR instead of rewriting an accepted historical record.

## Accepted decisions

- [0001 — Aggregate-first public headers and API boundary](0001-aggregate-first-public-headers.md)
- [0002 — Shared and dedicated asynchronous executors](0002-async-executor-model.md)
- [0003 — Immutable logger registry snapshots](0003-immutable-registry-snapshots.md)
- [0004 — TimeShield compatibility and dependency reuse](0004-timeshield-compatibility.md)
- [0005 — Benchmark evidence and comparison methodology](0005-benchmark-methodology.md)
81 changes: 81 additions & 0 deletions docs/future-plans.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Roadmap and delivery checklist — LogIt++

This file is the maintained roadmap, not a changelog. It deliberately separates
delivered capabilities from planned work and from ideas that are intentionally
delegated to user-defined `ILogger` implementations.

Legend:

- `[x]` delivered and covered by code/docs/tests;
- `[~]` available, but opt-in or platform-limited;
- `[ ]` planned work;
- `[-]` intentionally deferred, with no current commitment to implement it in
the core library.

## Delivered

- [x] Public aggregate-first header policy: `<logit.hpp>` is the supported
application entry point; module umbrellas and leaf-header contracts are
documented.
- [x] Public `logit::QueuePolicy` API and queue policy macros.
- [x] Immutable copy-on-write logger registry snapshots on the production hot
path, with atomic logger state and the existing execution mutex retained for
formatter/backend safety.
- [~] Dedicated per-backend worker threads via
`Config::use_dedicated_executor=true`. The default remains the shared
`TaskExecutor`; unsupported platform backends keep their documented
limitations.
- [x] Queue capacity, overflow policies, drop counters, resize behavior, and
flush/shutdown coverage.
- [x] MDC/NDC context, structured records, stored-log readers/subscribers, and
runtime log-level controls.
- [x] TimeShield `2.0.x` compatibility (minimum `2.0.0`) and dependency-target
reuse for build-tree and installed-package consumers.
- [x] Benchmark methodology and regression infrastructure: prepared-record hot
path A/B, public `LOGIT_INFO(...)` smoke benchmark, queue/CSV validation,
delayed-sink flush regression, and CI coverage.
- [x] Doxygen generation, GitHub Pages publication, header/layout smoke tests,
and the comparison guide for spdlog, Quill, Boost.Log, glog, and IceCream-Cpp.

## Next planned work

- [ ] **Release 1.0.2** — prepare changelog/release notes, verify package
overlays, generate the non-`-dev` documentation, tag the release, and verify
the published Pages site.
- [ ] **Binary logging research** — choose a versioned binary record format,
define compatibility/versioning rules, and prototype a reader before adding
a production backend.
- [ ] **Transparent compressed-file reads** — make `read_log_file()` and
`read_log_files()` read `.gz`/`.zst` entries when the corresponding feature is
enabled, with platform-specific tests.
- [ ] **Configuration loading** — design a versioned JSON/properties mapping to
the existing backend configuration. Treat file watching/hot reload as a
follow-up, not part of the first configuration API.
- [ ] **Extended filtering** — evaluate source/file, message, tag/MDC, and
range filters; define their cost and ordering before adding public API.
- [ ] **Benchmark follow-up** — add a genuinely formatted public-macro scenario,
a versioned fixture containing compiler/toolchain/commit/queue/flush metadata,
and a broader 1/4/16/32-producer matrix. Keep publication numbers tied to a
fixed machine and toolchain.
- [ ] **Concurrency fast-path research** — only after documenting a formal
thread-safety capability for formatters/backends. Do not remove `exec_mx`
based on benchmark results alone.

## Intentionally deferred

- [-] **Database/SQLite appender** — currently better implemented as a custom
`ILogger`; revisit if a common portable schema and maintenance owner emerge.
- [-] **Telnet/TCP appender** — application-specific transport and access
policy; implement as a custom backend unless a supported protocol is agreed.
- [-] **Main-thread GUI appender** — event-loop integration is framework and
platform specific; revisit when LogIt++ ships a GUI viewer.

## How to update this document

Move an item to `[x]` only when the implementation, tests, and user-facing
documentation agree. Use an ADR in [`docs/adr`](https://github.com/LimiNode/log-it-cpp/tree/main/docs/adr) for architectural
decisions or compatibility changes; keep this file focused on status and next
steps. Record measurements with their environment instead of turning one local
run into a universal performance claim.

Last reviewed: 2026-09-14.
1 change: 1 addition & 0 deletions docs/mainpage.dox
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ int main() {
- \ref benchmarks — benchmark methodology and historical snapshot.
- \ref api_reference — detailed macro, formatting, configuration, and extension reference.
- \ref comparison — comparison with other C++ logging libraries and trade-offs.
- Architecture decisions — the source repository's [`docs/adr/`](https://github.com/LimiNode/log-it-cpp/tree/main/docs/adr) records the rationale for public boundaries, executors, snapshots, and compatibility.

\section feature_summary Feature summary

Expand Down
5 changes: 5 additions & 0 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ dependency requirements are described in the [`Backend matrix`](backends.html).
the historical snapshot disclaimer.
- **Choosing a logging library** — [`Comparison with other C++ logging libraries`](comparison.html),
including trade-offs and the scope of the comparison.
- **Architecture decisions** — [`Architecture Decision Records`](https://github.com/LimiNode/log-it-cpp/tree/main/docs/adr),
including public API boundaries, executor ownership, snapshots, and
dependency compatibility.
- **Roadmap** — [`delivery checklist`](https://github.com/LimiNode/log-it-cpp/blob/main/docs/future-plans.md),
separating delivered, planned, and intentionally deferred work.
- **Examples** — browse the `examples/` directory in the source repository;
each optional example states the feature macro it requires.

Expand Down
Loading