Skip to main content

Crate tailtriage_core

Crate tailtriage_core 

Source
Expand description

§tailtriage-core

tailtriage-core is the framework-agnostic capture foundation for tailtriage.

Use it when you want explicit request lifecycle instrumentation and bounded JSON artifacts without controller, Axum, or Tokio runtime-sampler APIs unless you add them separately.

§What this crate does

tailtriage-core owns capture-side lifecycle semantics:

  • request admission
  • queue/stage/inflight instrumentation
  • explicit request completion
  • bounded in-memory retention
  • JSON run artifact writing

For in-process analysis/report generation, use tailtriage-analyzer. For command-line analysis of saved artifacts, use tailtriage-cli.

§Crate selection

Use tailtriage-core when you want the smallest framework-agnostic capture surface.

Use tailtriage when you want the recommended default entry point: an aggregator/re-export crate with optional integrations behind features.

§Installation

cargo add tailtriage-core

§Quick start

use tailtriage_core::Tailtriage;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let run = Tailtriage::builder("checkout-service")
        .output("tailtriage-run.json")
        .build()?;

    let started = run.begin_request("/checkout");
    started.completion.finish_ok();

    run.shutdown()?;
    Ok(())
}

§Request lifecycle

begin_request(...) / begin_request_with(...) returns StartedRequest with:

  • started.handle for queue/stage/inflight instrumentation
  • started.completion for explicit finish

For Arc<Tailtriage> flows that move request handles across spawned tasks or helper layers, use begin_request_owned(...) / begin_request_with_owned(...). Owned handles keep the same lifecycle rule: instrumentation does not finish the request, and the completion token must be finished exactly once.

use tailtriage_core::{RequestOptions, Tailtriage};

async fn demo() -> Result<(), Box<dyn std::error::Error>> {
    let run = Tailtriage::builder("checkout-service")
        .output("tailtriage-run.json")
        .build()?;

    let started = run.begin_request_with(
        "/checkout",
        RequestOptions::new().request_id("req-1").kind("http"),
    );
    let req = started.handle.clone();

    req.queue("ingress").await_on(async {}).await;
    req.stage("db")
        .await_on(async { Ok::<(), std::io::Error>(()) })
        .await?;

    started.completion.finish_ok();
    run.shutdown()?;
    Ok(())
}

§Output sinks

tailtriage-core captures run data and finalizes through a sink. It does not perform analysis/report generation.

  • LocalJsonSink (or builder .output(...)) writes Run artifact JSON to disk.
  • MemorySink stores finalized typed Run values in memory.
  • DiscardSink finalizes lifecycle and drops the finalized Run without persisting output.

MemorySink stores only the last finalized Run; each new finalized run replaces the previous stored value.

Use MemorySink when you want in-process analysis. DiscardSink drops finalized runs; use MemorySink instead when the finalized Run should be analyzed in process.

use tailtriage_core::{MemorySink, Tailtriage};

let sink = MemorySink::new();
let run = Tailtriage::builder("checkout-service")
    .sink(sink.clone())
    .build()?;

let started = run.begin_request("/checkout");
started.completion.finish_ok();
run.shutdown()?;

let finalized = sink.last_run();

§Two easy-to-miss helpers

For infallible async work, StageTimer::await_value(...) avoids a dummy Result:

let value = req.stage("cache").await_value(async { 42 }).await;

When queue depth is known at enqueue time, QueueTimer::with_depth_at_start(...) records it directly:

req.queue("ingress")
    .with_depth_at_start(12)
    .await_on(async {})
    .await;

§Lifecycle contract

  • queue(...), stage(...), and inflight(...) do not finish requests.
  • Every admitted request must be finished exactly once.
  • Dropping a completion token does not auto-finish.
  • Non-strict lifecycle: shutdown() writes the artifact and records unfinished-request warnings/metadata.
  • strict_lifecycle(true): unfinished requests cause shutdown() to return an error and no artifact is written.

Finalization timestamps:

  • Active snapshot() output is not finalized (metadata.finalized_at_unix_ms == None).
  • shutdown() writes final artifacts with both:
    • metadata.finished_at_unix_ms set to shutdown time
    • metadata.finalized_at_unix_ms set to that same timestamp
  • Older artifacts may deserialize with metadata.finalized_at_unix_ms == None.
  • When finalized_at_unix_ms is present, prefer that field as the finalization signal; finished_at_unix_ms remains for backward compatibility.

§Capture modes

Modes change retention defaults only. They do not change lifecycle semantics and do not auto-start runtime sampling.

  • CaptureMode::Light
  • CaptureMode::Investigation

Override limits with:

  • capture_limits(...) (full override)
  • capture_limits_override(...) (field-level override)

§What this crate does not do

This crate does not provide:

  • repeated arm/disarm controller windows
  • Tokio runtime sampling
  • Axum middleware/extractors
  • analysis/report generation

Use sibling crates for those surfaces: tailtriage-controller, tailtriage-tokio, tailtriage-axum, tailtriage-analyzer, and tailtriage-cli.

Structs§

CaptureLimits
Limits that bound in-memory capture growth for one run.
CaptureLimitsOverride
Field-level capture limit overrides applied on top of mode defaults.
DiscardSink
Sink that finalizes capture lifecycle without writing a run artifact.
EffectiveCoreConfig
Stable, resolved core configuration used by one capture run.
EffectiveTokioSamplerConfig
Stable, resolved Tokio runtime sampler configuration used by one run.
InFlightSnapshot
Point-in-time in-flight gauge reading.
InflightGuard
RAII guard tracking one in-flight unit for a named gauge.
LocalJsonSink
Local file sink that writes one JSON document per run at shutdown.
MemorySink
In-memory sink that stores only the last finalized run.
OwnedRequestCompletion
Completion-facing request token backed by Arc<Tailtriage>.
OwnedRequestHandle
Instrumentation-facing request handle backed by Arc<Tailtriage>.
OwnedStartedRequest
Split request lifecycle start result backed by Arc<Tailtriage>.
QueueEvent
Queue wait measurement for a request waiting on a queue/permit.
QueueTimer
Thin wrapper for recording queue-wait latency around one await point.
RequestCompletion
Completion-facing request token.
RequestEvent
Per-request timing and status.
RequestHandle
Instrumentation-facing request handle.
RequestOptions
Optional request start settings used by crate::Tailtriage::begin_request_with.
Run
A full output artifact for one tailtriage capture run.
RunMetadata
Top-level metadata for one capture run.
RuntimeSnapshot
Point-in-time runtime metrics sample.
StageEvent
Timing record for one named stage.
StageTimer
Thin wrapper for recording stage latency around one await point.
StartedRequest
Split request lifecycle start result.
Tailtriage
Per-run collector that records request events and writes the final artifact.
TailtriageBuilder
Builder for constructing a crate::Tailtriage run.
TruncationSummary
Per-section counters indicating dropped samples due to capture limits.
UnfinishedRequestSample
One unfinished request sample captured for lifecycle warnings.
UnfinishedRequests
Summary of unfinished requests detected at shutdown.

Enums§

BuildError
Errors emitted while building one tailtriage capture instance.
CaptureMode
Capture mode used during a run.
Outcome
Logical request outcome categories used by the public API.
RunEndReason
Run lifecycle end reason recorded in artifact metadata.
RuntimeSamplerRegistrationError
Error returned when registering Tokio runtime sampler metadata.
SinkError
Errors emitted while writing run artifacts.

Constants§

SCHEMA_VERSION
Current schema version for Run JSON artifacts.

Traits§

RunSink
A sink that persists the final run artifact produced at shutdown.

Functions§

system_time_to_unix_ms
Converts a SystemTime to unix epoch milliseconds.
unix_time_ms
Returns the current unix epoch timestamp in milliseconds.