# let Jev score OpenTelemetry logs before a bigger LLM sees them

> Source: <https://dev.to/reachjalil/let-jev-score-opentelemetry-logs-before-a-bigger-llm-sees-them-196d>
> Published: 2026-09-17 06:07:50+00:00

Health checks. Cache hits. A payment failure hiding in the middle. If every OpenTelemetry log goes into a reasoning model, you pay for noise before the investigation starts.

**Jev Logs** is a small open-source layer that puts [TypeSafe’s Jev](https://typesafe.ai/) in front of those logs. Jev makes the first decision: how useful is this record, how urgent is it, and does it deserve a more expensive model?

I wrote it. MIT licensed. Independent not a TypeSafe, Vercel, or OpenTelemetry product.

**A little intelligence between your logs and your LLM bill.**

  Score, prioritize, and route OpenTelemetry logs with Jev. Keep the signal. Keep your stack

[**Website**](https://jevlogs.com) ·
  [**Guide**](https://jevlogs.com/guide/) ·
  [**llms.txt**](https://jevlogs.com/llms.txt) ·
  [**npm**](https://www.npmjs.com/package/jevlogs) ·
  **Feedback**

Health checks. Cache hits. A payment failure hiding in the middle. Sending every event to a reasoning model adds cost before the investigation even starts.

**Jev Logs makes the first decision:** how useful is this log, how urgent is it, and does it deserve deeper analysis? It uses [TypeSafe’s Jev](https://typesafe.ai/) through the Vercel AI SDK, with a small TypeScript API and an OpenTelemetry exporter wrapper.

| A small layer | What you get | 
|---|---|
| **Score the signal** | A 0–100 diagnostic-value score, priority, and actionable probability. | 
| **Keep your pipeline** | Wrap your existing exporter; preserve resource, scope, timestamps, and trace context. | 
| **Start with visibility** | Annotation mode keeps every record and attaches `jev.*` attributes. | 
| **Spend** |  | 

Jev is built for structured choices, not paragraphs. For each log, Jev Logs asks it for:

`critical`, `high`, `normal`, `low`)` analyze` or `retain`
Your archive still gets every record. The analysis branch only needs the ones Jev (or a rule, or a conservative fallback) says are worth it.

A log may skip deeper analysis only when **all three** are true: priority is `low`, value is 25 or below, and actionable probability is under `0.1`. Errors, `jev.protected` records, timeouts, and provider failures stay eligible. Nothing in the SDK deletes your logs.

Offline demo. No key. No network.

```
npx jevlogs
0 / 100  low      RETAIN   GET /health returned 200 in 2ms
  25 / 100  low      RETAIN   Cache hit for product:482
 100 / 100  critical ANALYZE  Payment capture failed after three retries
  75 / 100  high     ANALYZE  Database connection pool at 94% capacity
```

That walkthrough uses fixed answers so you can see the shape. It does not call Jev.

Real Jev, still on your machine:

```
export AI_GATEWAY_API_KEY=your-vercel-ai-gateway-key

npx jevlogs --live --sample
npx jevlogs --live --file ./app.log --limit 20
```

`--live` alone starts a local OTLP HTTP/JSON receiver on `http://127.0.0.1:4318/v1/logs`. Point your app at it; Jev Logs prints one JSON decision per record and can forward annotated batches to the collector you already run. Node.js 22+.

```
npm install jevlogs
js
import { createJevLogs } from "jevlogs";

const jev = createJevLogs();
const decision = await jev.triage({
  body: "Database connection pool at 94% capacity",
  severityText: "WARN",
});

console.log(decision);
// value · priority · route · actionableProbability · reason
```

Skip health checks without spending a Jev call:

``` js
const jev = createJevLogs({
  rules: [{ name: "health", match: "^GET /health", route: "retain" }],
});
```

Wrap the exporter you have. Annotation mode keeps every log and attaches `jev.*` attributes.

``` js
import {
  LoggerProvider,
  BatchLogRecordProcessor,
  ConsoleLogRecordExporter,
} from "@opentelemetry/sdk-logs";
import { JevLogExporter } from "jevlogs";

const provider = new LoggerProvider({
  processors: [
    new BatchLogRecordProcessor({
      exporter: new JevLogExporter({
        exporter: new ConsoleLogRecordExporter(),
        mode: "annotate",
      }),
      maxExportBatchSize: 16,
    }),
  ],
});
```

Keep that archive processor. Add a second exporter with `mode: "analysis-only"` when you actually want to drop low-value records from the LLM path. **Annotation alone does not cut the bill** — the downstream pipeline has to honor `route`.

A second giant completion per log is the thing this is trying to avoid. Jev’s published rate is cheap structured evaluation (TypeSafe lists **$0.042/M input**, free output). You pay Jev for a small decision, then pay GPT-class analysis only for the selected slice.

The README has an illustrative table: 1M logs/month, if 10% still need analysis, a **$1,000** GPT-4.1-style bill models down to about **$129** including Jev triage. That is **not** a measured production result. Measure incident recall on *your* logs before you filter.

No hosted dashboard. No log storage. No Collector plugin. No root-cause write-up. Preview software: `jevlogs` on npm, TypeScript first, CI on the repo. Jev itself is a hosted model via Vercel AI Gateway; this repo is the **integration**.

`jevlogs`
If you try it, I want feedback on the Jev scoring/routing shape and whether wrapping an exporter is the right split vs the local receiver. Issues with sanitized examples are welcome.
