# tracy

> Logs for Ktor services shaped for a coding agent to read. One native binary and one SQLite file; MCP is the primary read path, not a bolt-on.

Page: https://kotlin.website/tracy

## Why it exists

Between "`kubectl logs` is enough" and "let's run Loki, Promtail and Grafana" there is nothing.
tracy is one self-contained binary and one SQLite file — no JVM, no Elasticsearch, no shipper —
and its primary reader is a coding agent rather than a person with a browser.

## What you get

- **End-to-end traces.** You have a `traceId`, you get the whole chain: a tree of spans with
  durations plus every log line of that request, across every service, in one call.
  Correlation travels as a standard W3C `traceparent`.
- **Business entity lookup.** Support never brings a `traceId`; they bring an `order_id`. Mark
  a field as an entity key and you get that entity's history across services and across
  unrelated traces.
- **Templates and data separated at write time**, so exact event frequencies are countable
  later instead of reverse-engineered out of rendered strings.
- **FTS5 search** with the trigram tokenizer, plus time-window queries across services.
- **Seven read-only MCP tools** with a hard context budget, a two-phase content release and a
  static screen over untrusted text — log content is attacker-influenced data being handed to
  a model.

## Install

Run the server:

```bash
docker run -p 8080:8080 -e TRACY_INGEST_KEY=dev-key ghcr.io/youndie/tracy:latest
```

Add the agent to a Ktor service:

```kotlin
repositories { maven("https://reposilite.kotlin.website/snapshots") }
dependencies { implementation("io.github.youndie.tracy:agent:<VERSION>") }
```

## Where it actually is

Running on a staging cluster with four services reporting into it, 293 tests, read over MCP
daily. Those four services are **quiet** — a day of them is on the order of a hundred
kilobytes — so the volume figures are still arithmetic rather than measurements.
