# How 5ire’s Usage Analytics Feature Tracks API Calls and Token Consumption

> Learn how 5ire tracks API calls and token consumption using local SQLite databases and real-time analytics. Get clear insights into your model usage.

- Repository: [Ironben/5ire](https://github.com/nanbingxyz/5ire)
- Tags: how-to-guide
- Published: 2026-03-07

---

**The 5ire application instruments every chat session with model-specific token counters, persists the data to a local SQLite database, and aggregates costs by provider and model for real-time analytics.**

The 5ire open-source chat client provides built-in usage analytics to help users monitor their AI spending. According to the nanbingxyz/5ire repository, the usage analytics feature tracks API calls and token consumption through a five-stage pipeline that spans token counting, database persistence, and statistical aggregation.

## Token Counting with Model-Specific Helpers

Every API call begins with **token counting** to measure input and output usage. When a user submits a prompt, the application calls `useToken().countInput()`, and after receiving the model’s reply, it calls `countOutput()`.

In [`src/hooks/useToken.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/hooks/useToken.ts), the hook selects the appropriate tokenizer based on the active model. The implementation delegates to model-specific utilities defined in [`src/utils/token.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/utils/token.ts), including `countGPTTokens`, `countTokensOfGemini`, `countTokensOfMoonshot`, and `countTokenOfLlama`.

```typescript
// Token counting during chat sessions (src/hooks/useToken.ts)
const inputTokens = await useToken().countInput(prompt);
const outputTokens = await useToken().countOutput(reply);

```

These helpers normalize token calculation across OpenAI, Gemini, Moonshot, and Llama models, ensuring accurate consumption metrics regardless of the provider.

## Persisting Usage Data to SQLite

After token counts are calculated, the chat component persists the record to local storage. The `useUsageStore` in [`src/stores/useUsageStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useUsageStore.ts) exposes a `create()` method that writes a row into the SQLite `usages` table.

The chat page at [`src/renderer/pages/chat/index.tsx`](https://github.com/nanbingxyz/5ire/blob/main/src/renderer/pages/chat/index.tsx) triggers this persistence immediately after the model finishes generating a response:

```typescript
// Recording usage after each chat response (src/renderer/pages/chat/index.tsx)
useUsageStore.getState().create({
  provider: providerCtx.name,
  model: modelCtx.label,
  inputTokens,
  outputTokens,
});

```

### Database Schema

The `usages` table is defined in [`src/main/sqlite.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/main/sqlite.ts) (lines 33‑44) during application startup. It stores the provider name, model label, token counts, per-token pricing for cost analysis, and a Unix timestamp:

```sql
-- SQLite schema for usage tracking (src/main/sqlite.ts)
CREATE TABLE IF NOT EXISTS "usages" (
  "id" text(31),
  "provider" text,
  "model" text,
  "InputTokens" integer,
  "outputTokens" integer,
  "inputPrice" number,
  "outputPrice" NUMBER,
  "createdAt" integer,
  PRIMARY KEY ("id")
);

```

## Aggregating Statistics and Rendering the UI

The **Usage** page queries aggregated statistics via the `statistics(start, end)` method in `useUsageStore`. This method executes a SQL query that sums `inputTokens` and `outputTokens`, then calculates monetary cost by applying the stored per-token prices.

```typescript
// Aggregating usage by date range (src/stores/useUsageStore.ts)
await window.electron.db.all(`
  SELECT provider, model,
    sum(inputTokens) inputTokens,
    sum(outputTokens) outputTokens,
    round(sum(inputTokens * inputPrice / 1000), 4) AS inputCost,
    round(sum(outputTokens * outputPrice / 1000), 4) AS outputCost
  FROM usages
  WHERE createdAt >= ? AND createdAt <= ?
  GROUP BY provider, model
`, [startDateUnix, endDateUnix]);

```

The React page at [`src/renderer/pages/usage/index.tsx`](https://github.com/nanbingxyz/5ire/blob/main/src/renderer/pages/usage/index.tsx) loads these aggregates within a `useEffect` hook, groups the rows by provider, and passes the data to a `Grid` component for visualization. Users can select start and end dates, and the UI automatically refreshes the charts and tables to reflect the filtered range.

```typescript
// Loading and displaying stats in the UI (src/renderer/pages/usage/index.tsx)
const rows = await useUsageStore.getState().statistics(startDateUnix, endDateUnix);
const $statistics = groupBy(rows, 'provider');
setStatistics($statistics);

```

## Summary

- **Token counting** happens via the `useToken` hook, which delegates to model-specific helpers like `countGPTTokens` and `countTokensOfGemini` in [`src/utils/token.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/utils/token.ts).
- **Usage records** are stored in a local SQLite `usages` table defined in [`src/main/sqlite.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/main/sqlite.ts), capturing provider, model, token counts, and per-token pricing.
- **Persistence** is triggered by the chat component at [`src/renderer/pages/chat/index.tsx`](https://github.com/nanbingxyz/5ire/blob/main/src/renderer/pages/chat/index.tsx) calling `useUsageStore.getState().create()` after each model response.
- **Aggregation** is performed by the `statistics()` method in [`src/stores/useUsageStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useUsageStore.ts), which groups data by provider and model and calculates costs per 1,000 tokens.
- **Visualization** is handled by the Usage page at [`src/renderer/pages/usage/index.tsx`](https://github.com/nanbingxyz/5ire/blob/main/src/renderer/pages/usage/index.tsx), which renders date-filtered analytics using React state and grid components.

## Frequently Asked Questions

### How does 5ire calculate token counts for different AI providers?

The application uses the `useToken` hook in [`src/hooks/useToken.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/hooks/useToken.ts) to select the appropriate tokenizer. It delegates to provider-specific functions—`countGPTTokens` for OpenAI models, `countTokensOfGemini` for Google, `countTokensOfMoonshot`, and `countTokenOfLlama`—ensuring accurate counts regardless of the underlying API.

### Where does 5ire store usage analytics data?

All usage data is written to a local SQLite database. The `usages` table, created during app startup in [`src/main/sqlite.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/main/sqlite.ts), stores each API call’s provider, model, input and output token counts, per-token prices, and timestamp.

### How does 5ire calculate the monetary cost of API calls?

Cost calculation happens during SQL aggregation. The `statistics()` method in [`src/stores/useUsageStore.ts`](https://github.com/nanbingxyz/5ire/blob/main/src/stores/useUsageStore.ts) runs a query that sums `(inputTokens * inputPrice / 1000)` and `(outputTokens * outputPrice / 1000)`, rounding to four decimal places to produce the final input and output costs per provider-model combination.

### Can users filter usage analytics by specific time periods?

Yes. The Usage page accepts start and end date parameters, converts them to Unix timestamps, and passes them to `useUsageStore.getState().statistics(startDateUnix, endDateUnix)`. The underlying SQL query filters the `usages` table using `createdAt >= ? AND createdAt <= ?`, allowing users to view analytics for any custom date range.