{"id":44572920,"url":"https://github.com/simulieren/adonisjs-server-stats","last_synced_at":"2026-04-03T10:03:26.419Z","repository":{"id":338348706,"uuid":"1157341372","full_name":"simulieren/adonisjs-server-stats","owner":"simulieren","description":"Laravel Telescope-inspired dev toolbar and real-time server monitor for AdonisJS v6","archived":false,"fork":false,"pushed_at":"2026-02-20T07:25:14.000Z","size":14688,"stargazers_count":14,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-20T10:14:59.101Z","etag":null,"topics":["adonisjs","adonisjs-package","debug","dev-toolbar","devtools","metrics","server-monitoring","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/adonisjs-server-stats","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simulieren.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T17:54:18.000Z","updated_at":"2026-02-20T10:10:47.000Z","dependencies_parsed_at":"2026-02-19T07:01:02.302Z","dependency_job_id":null,"html_url":"https://github.com/simulieren/adonisjs-server-stats","commit_stats":null,"previous_names":["simulieren/adonisjs-server-stats"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/simulieren/adonisjs-server-stats","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simulieren%2Fadonisjs-server-stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simulieren%2Fadonisjs-server-stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simulieren%2Fadonisjs-server-stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simulieren%2Fadonisjs-server-stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simulieren","download_url":"https://codeload.github.com/simulieren/adonisjs-server-stats/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simulieren%2Fadonisjs-server-stats/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29851615,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-25T22:37:40.667Z","status":"online","status_checked_at":"2026-02-26T02:00:06.774Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["adonisjs","adonisjs-package","debug","dev-toolbar","devtools","metrics","server-monitoring","typescript"],"created_at":"2026-02-14T03:48:04.729Z","updated_at":"2026-04-03T10:03:26.403Z","avatar_url":"https://github.com/simulieren.png","language":"TypeScript","readme":"# adonisjs-server-stats\n\n[![npm version](https://img.shields.io/npm/v/adonisjs-server-stats.svg)](https://www.npmjs.com/package/adonisjs-server-stats)\n[![npm downloads](https://img.shields.io/npm/dm/adonisjs-server-stats.svg)](https://www.npmjs.com/package/adonisjs-server-stats)\n[![license](https://img.shields.io/npm/l/adonisjs-server-stats.svg)](https://github.com/simulieren/adonisjs-server-stats/blob/main/LICENSE)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9+-blue.svg)](https://www.typescriptlang.org/)\n[![AdonisJS](https://img.shields.io/badge/AdonisJS-v6-5A45FF.svg)](https://adonisjs.com/)\n[![AdonisJS](https://img.shields.io/badge/AdonisJS-v7-5A45FF.svg)](https://adonisjs.com/)\n\nA Laravel Telescope-inspired dev toolbar and real-time server monitor for **AdonisJS v6 \u0026 v7**.\n\nDrop a single Edge tag into your layout and get a live stats bar showing CPU, memory, requests/sec, database pool, Redis, queues, and logs -- plus a full debug toolbar with SQL query inspection, event tracing, route listing, live log tailing, and custom panels.\n\nZero frontend dependencies. Zero build step. Just `@serverStats()` and go.\n\n**New (alpha):** Native [React \u0026 Vue components](#react--vue-inertiajs--alpha) for Inertia.js apps — same features, framework-native.\n\n![adonisjs-server-stats demo](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/demo.gif)\n\n## Screenshots\n\n**Debug toolbar** -- expandable panels for deep inspection:\n\n| Queries                                                                                                                                                                  | Events                                                                                                                                                             |\n| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| ![Queries panel showing SQL queries with duration and model info](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/debug-queries.png) | ![Events panel showing application events with payload data](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/debug-events.png) |\n\n| Routes                                                                                                                                                            | Logs                                                                                                                                                              |\n| ----------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| ![Routes panel showing all registered routes with handlers](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/debug-routes.png) | ![Logs panel with level filtering and request ID correlation](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/debug-logs.png) |\n\n| Emails (custom pane)                                                                                                                                           |\n| -------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| ![Emails panel showing sent emails with delivery status](https://raw.githubusercontent.com/simulieren/adonisjs-server-stats/main/screenshots/debug-emails.png) |\n\n## Features\n\n- **Live stats bar** -- CPU, memory, event loop lag, HTTP throughput, DB pool, Redis, queues, logs\n- **Debug toolbar** -- SQL queries, events, emails, routes, logs with search and filtering\n- **Request tracing** -- per-request waterfall timeline showing DB queries, events, and custom spans\n- **Custom panes** -- add your own tabs (webhooks, emails, cache, anything) with a simple config\n- **Full-page dashboard** -- dedicated page at `/__stats` with overview cards, charts, request history, query analysis, EXPLAIN plans, cache/queue/config inspection, and saved filters\n- **Pluggable collectors** -- use built-in collectors or write your own\n- **Visibility control** -- show only to admins, specific roles, or in dev mode\n- **SSE broadcasting** -- real-time updates via AdonisJS Transmit\n- **Prometheus export** -- expose all metrics as Prometheus gauges\n- **Self-contained** -- inline HTML/CSS/JS Edge tag, no external assets\n- **React \u0026 Vue support (alpha)** -- native Inertia.js components with the same features as Edge\n- **Graceful degradation** -- missing optional dependencies are handled automatically\n- **Theme support** -- dark and light themes across dashboard, debug panel, and stats bar with system preference detection and manual toggle\n\n## Installation\n\n```bash\nnpm install adonisjs-server-stats\n```\n\n## Quick Start\n\n### 1. Register providers\n\n```ts\n// adonisrc.ts\nproviders: [\n  () =\u003e import('adonisjs-server-stats/provider'),\n]\n```\n\n### 2. Register middleware\n\n```ts\n// start/kernel.ts\nserver.use([() =\u003e import('adonisjs-server-stats/middleware')])\n```\n\n### 3. Create config\n\n```ts\n// config/server_stats.ts\nimport { defineConfig } from 'adonisjs-server-stats'\n\nexport default defineConfig({})\n```\n\nThat's it -- zero config required. Collectors are auto-detected from your installed packages (Lucid, Redis, BullMQ, etc.) and enabled automatically. All other options have sensible defaults.\n\n**Common setup** -- add access control and enable the toolbar/dashboard:\n\n```ts\n// config/server_stats.ts\nimport { defineConfig } from 'adonisjs-server-stats'\n\nexport default defineConfig({\n  authorize: (ctx) =\u003e ctx.auth?.user?.role === 'admin',\n  toolbar: true,\n  dashboard: true,\n})\n```\n\n\u003e **Tip: Enable query capture** -- Lucid only emits `db:query` events when `debug: true` is set on the connection. Without it, the Queries panel will be empty.\n\u003e\n\u003e ```ts\n\u003e // config/database.ts\n\u003e connections: {\n\u003e   postgres: {\n\u003e     client: 'pg',\n\u003e     debug: app.inDev,  // ← enables query capture in development\n\u003e     connection: { ... },\n\u003e   },\n\u003e }\n\u003e ```\n\n**Full control** -- override auto-detection with explicit collectors:\n\n```ts\n// config/server_stats.ts\nimport env from '#start/env'\nimport { defineConfig } from 'adonisjs-server-stats'\nimport {\n  processCollector,\n  systemCollector,\n  httpCollector,\n  dbPoolCollector,\n  redisCollector,\n  queueCollector,\n  logCollector,\n  appCollector,\n} from 'adonisjs-server-stats/collectors'\n\nexport default defineConfig({\n  pollInterval: 3000,\n  collectors: [\n    processCollector(),\n    systemCollector(),\n    httpCollector({ maxRecords: 10_000 }),\n    dbPoolCollector({ connectionName: 'postgres' }),\n    redisCollector(),\n    queueCollector({\n      queueName: 'default',\n      connection: {\n        host: env.get('QUEUE_REDIS_HOST'),\n        port: env.get('QUEUE_REDIS_PORT'),\n        password: env.get('QUEUE_REDIS_PASSWORD'),\n      },\n    }),\n    logCollector(),\n    appCollector(),\n  ],\n})\n```\n\n### 4. Render the stats bar\n\nThat's it for setup -- **all API routes are auto-registered by the package**. No controllers or route definitions needed. On startup you'll see:\n\n```\n[server-stats] auto-registered routes: /admin/api/server-stats, /admin/api/debug/*, /__stats/*\n```\n\nAll routes are gated by the `authorize` callback if configured (see [Visibility Control](#visibility-control-authorize)).\n\n**Edge** (add before `\u003c/body\u003e`):\n\n```edge\n@serverStats()\n```\n\n---\n\n## Config Reference\n\n### `ServerStatsConfig` (recommended)\n\nAll fields are optional. `defineConfig({})` works with zero configuration.\n\n| Option          | Type                              | Default                     | Description                                                      |\n| --------------- | --------------------------------- | --------------------------- | ---------------------------------------------------------------- |\n| `pollInterval`  | `number`                          | `3000`                      | Collection + broadcast interval (ms)                             |\n| `collectors`    | `'auto' \\| MetricCollector[]`     | `'auto'`                    | `'auto'` probes installed packages; or pass an explicit array    |\n| `realtime`      | `boolean`                         | `true`                      | `true` = SSE via Transmit, `false` = poll-only                   |\n| `statsEndpoint` | `string \\| false`                 | `'/admin/api/server-stats'` | HTTP endpoint. `false` to disable.                               |\n| `authorize`     | `(ctx) =\u003e boolean`                | --                          | Per-request visibility guard                                     |\n| `onStats`       | `(stats) =\u003e void`                 | --                          | Callback after each collection tick                              |\n| `toolbar`       | `boolean \\| ToolbarConfig`        | --                          | `true` to enable with defaults, or pass a `ToolbarConfig` object |\n| `dashboard`     | `boolean \\| DashboardConfig`      | --                          | `true` to enable at `/__stats`, or pass a `DashboardConfig`      |\n| `verbose`       | `boolean`                         | `false`                     | Log initialization details (collectors, routes, etc) to console  |\n| `advanced`      | `AdvancedConfig`                  | --                          | Rarely-needed options (channel name, db path, buffer sizes, etc) |\n\n### `ToolbarConfig`\n\n| Option               | Type       | Default                                           | Description                                     |\n| -------------------- | ---------- | ------------------------------------------------- | ----------------------------------------------- |\n| `slowQueryThreshold` | `number`   | `100`                                             | Slow query threshold (ms)                        |\n| `tracing`            | `boolean`  | `true`                                            | Enable per-request tracing with timeline         |\n| `persist`            | `boolean`  | `false`                                           | Persist debug data to disk across restarts       |\n| `panes`              | `DebugPane[]` | --                                             | Custom debug panel tabs                          |\n| `excludeFromTracing` | `string[]` | `['/admin/api/debug', '/admin/api/server-stats']` | URL prefixes to exclude from tracing/persistence |\n\n### `DashboardConfig`\n\n| Option          | Type     | Default      | Description                            |\n| --------------- | -------- | ------------ | -------------------------------------- |\n| `path`          | `string` | `'/__stats'` | URL path for the dashboard page        |\n| `retentionDays` | `number` | `7`          | Days to keep historical data in SQLite |\n\n### `AdvancedConfig`\n\n| Option          | Type                | Default                                      | Description                                     |\n| --------------- | ------------------- | -------------------------------------------- | ----------------------------------------------- |\n| `skipInTest`    | `boolean`           | `true`                                       | Skip collection during tests                    |\n| `channelName`   | `string`            | `'admin/server-stats'`                       | Transmit channel name                           |\n| `debugEndpoint` | `string`            | `'/admin/api/debug'`                         | Base path for debug toolbar API endpoints       |\n| `renderer`      | `'preact' \\| 'vue'` | `'preact'`                                   | Client-side rendering library for Edge          |\n| `dbPath`        | `string`            | `'.adonisjs/server-stats/dashboard.sqlite3'` | Path to the SQLite database file                |\n| `persistPath`   | `string`            | `'.adonisjs/server-stats/debug-data.json'`   | Path for persisted debug data                   |\n| `maxQueries`    | `number`            | `500`                                        | Max SQL queries to buffer                       |\n| `maxEvents`     | `number`            | `200`                                        | Max events to buffer                            |\n| `maxEmails`     | `number`            | `100`                                        | Max emails to buffer                            |\n| `maxTraces`     | `number`            | `200`                                        | Max request traces to buffer                    |\n\n### Legacy config (deprecated)\n\nThe following field names still work but will show deprecation warnings at boot. They will be removed in the next major version.\n\n| Legacy Name   | Replacement                     | Notes                                        |\n| ------------- | ------------------------------- | -------------------------------------------- |\n| `intervalMs`  | `pollInterval`                  | Same type and default                        |\n| `transport`   | `realtime`                      | `'transmit'` = `true`, `'none'` = `false`    |\n| `channelName` | `advanced.channelName`          | Same type and default                        |\n| `endpoint`    | `statsEndpoint`                 | Same type and default                        |\n| `shouldShow`  | `authorize`                     | Same type and default                        |\n| `skipInTest`  | `advanced.skipInTest`           | Same type and default                        |\n| `devToolbar`  | `toolbar` + `dashboard` + `advanced` | Split into focused config objects       |\n\n### `DevToolbarOptions` (internal)\n\n\u003e **Note:** This is the internal, fully-expanded format. Most users should prefer the new `toolbar`, `dashboard`, and `advanced` options above -- they map to these fields automatically.\n\n| Option                 | Type                | Default                                           | Description                                                                                                                                                                                                  |\n| ---------------------- | ------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `enabled`              | `boolean`           | `false`                                           | Enable the dev toolbar                                                                                                                                                                                       |\n| `maxQueries`           | `number`            | `500`                                             | Max SQL queries to buffer                                                                                                                                                                                    |\n| `maxEvents`            | `number`            | `200`                                             | Max events to buffer                                                                                                                                                                                         |\n| `maxEmails`            | `number`            | `100`                                             | Max emails to buffer                                                                                                                                                                                         |\n| `slowQueryThresholdMs` | `number`            | `100`                                             | Slow query threshold (ms)                                                                                                                                                                                    |\n| `persistDebugData`     | `boolean \\| string` | `false`                                           | Persist debug data to disk across restarts. `true` writes to `.adonisjs/server-stats/debug-data.json`, or pass a custom path.                                                                                |\n| `tracing`              | `boolean`           | `true`                                            | Enable per-request tracing with timeline visualization                                                                                                                                                       |\n| `maxTraces`            | `number`            | `200`                                             | Max request traces to buffer                                                                                                                                                                                 |\n| `dashboard`            | `boolean`           | `false`                                           | Enable the full-page dashboard (requires `better-sqlite3`)                                                                                                                                                   |\n| `dashboardPath`        | `string`            | `'/__stats'`                                      | URL path for the dashboard page                                                                                                                                                                              |\n| `retentionDays`        | `number`            | `7`                                               | Days to keep historical data in SQLite                                                                                                                                                                       |\n| `dbPath`               | `string`            | `'.adonisjs/server-stats/dashboard.sqlite3'`      | Path to the SQLite database file (relative to app root)                                                                                                                                                      |\n| `debugEndpoint`        | `string`            | `'/admin/api/debug'`                              | Base path for the debug toolbar API endpoints                                                                                                                                                                |\n| `excludeFromTracing`   | `string[]`          | `['/admin/api/debug', '/admin/api/server-stats']` | URL prefixes to exclude from tracing and dashboard persistence. Requests still count toward HTTP metrics but won't appear in the timeline or be stored. The stats endpoint is always excluded automatically. |\n| `panes`                | `DebugPane[]`       | --                                                | Custom debug panel tabs                                                                                                                                                                                      |\n\n---\n\n## Collectors\n\n\u003e When `collectors` is `'auto'` (the default), the package probes installed packages at boot and enables matching collectors automatically. On startup you'll see a log showing all 8 collectors with a checkmark or cross and which packages were found or missing. You only need to specify collectors explicitly if you want to customize their options.\n\nEach collector is a factory function that returns a `MetricCollector`. All collectors run in parallel each tick; missing peer dependencies are handled gracefully (the collector returns defaults instead of crashing).\n\n### Built-in Collectors\n\n| Collector                | Metrics                                                         | Options      | Peer Deps         |\n| ------------------------ | --------------------------------------------------------------- | ------------ | ----------------- |\n| `processCollector()`     | CPU %, event loop lag, heap/RSS memory, uptime, Node version    | none         | --                |\n| `systemCollector()`      | OS load averages, system memory, system uptime                  | none         | --                |\n| `httpCollector(opts?)`   | Requests/sec, avg response time, error rate, active connections | optional     | --                |\n| `dbPoolCollector(opts?)` | Pool used/free/pending/max connections                          | optional     | `@adonisjs/lucid` |\n| `redisCollector()`       | Status, memory, clients, keys, hit rate                         | none         | `@adonisjs/redis` |\n| `queueCollector(opts)`   | Active/waiting/delayed/failed jobs, worker count                | **required** | `bullmq`          |\n| `logCollector(opts?)`    | Errors/warnings/entries (5m window), entries/minute             | optional     | --                |\n| `appCollector()`         | Online users, pending webhooks, pending emails                  | none         | `@adonisjs/lucid` |\n\n### Collector Options\n\n```ts\nhttpCollector({\n  maxRecords: 10_000, // Circular buffer size (default: 10,000)\n  windowMs: 60_000, // Rolling window for rate calc (default: 60s)\n})\n\ndbPoolCollector({\n  connectionName: 'postgres', // Lucid connection name (default: 'postgres')\n})\n\nqueueCollector({\n  queueName: 'default',\n  connection: {\n    host: 'localhost',\n    port: 6379,\n    password: 'secret',\n  },\n})\n\n// Zero-config: hooks into AdonisJS Pino logger automatically\nlogCollector()\n\n// Or file-based fallback:\nlogCollector({ logPath: 'logs/adonisjs.log' })\n```\n\n### Custom Collectors\n\nImplement the `MetricCollector` interface to create your own:\n\n```ts\nimport type { MetricCollector } from 'adonisjs-server-stats'\n\nfunction diskCollector(): MetricCollector {\n  return {\n    name: 'disk',\n    async collect() {\n      const { availableSpace, totalSpace } = await getDiskInfo()\n      return {\n        diskAvailableGb: availableSpace / 1e9,\n        diskTotalGb: totalSpace / 1e9,\n        diskUsagePercent: ((totalSpace - availableSpace) / totalSpace) * 100,\n      }\n    },\n  }\n}\n\n// config/server_stats.ts\nexport default defineConfig({\n  collectors: [\n    processCollector(),\n    diskCollector(), // mix with built-in collectors\n  ],\n})\n```\n\nThe `MetricCollector` interface:\n\n```ts\ninterface MetricCollector {\n  name: string\n  start?(): void | Promise\u003cvoid\u003e\n  stop?(): void | Promise\u003cvoid\u003e\n  collect(): Record\u003cstring, MetricValue\u003e | Promise\u003cRecord\u003cstring, MetricValue\u003e\u003e\n}\n```\n\n---\n\n## Visibility Control (`authorize`)\n\nUse `authorize` to control who can see the stats bar and access all auto-registered API routes (stats, debug, dashboard). The callback receives the AdonisJS `HttpContext` and should return `true` to allow access, `false` to deny (403).\n\nBecause `authorize` runs **after** middleware (including auth), you have full access to `ctx.auth`.\n\n```ts\nexport default defineConfig({\n  // Only show in development\n  authorize: () =\u003e env.get('NODE_ENV'),\n})\n```\n\n```ts\nexport default defineConfig({\n  // Only show for logged-in admin users\n  authorize: (ctx) =\u003e ctx.auth?.user?.isAdmin === true,\n})\n```\n\n```ts\nexport default defineConfig({\n  // Only show for specific roles\n  authorize: (ctx) =\u003e {\n    const role = ctx.auth?.user?.role\n    return role === 'admin' || role === 'superadmin'\n  },\n})\n```\n\n\u003e **Tip:** When `authorize` is not set, the bar and all routes are accessible to everyone. In production you almost always want to set this.\n\u003e\n\u003e **Migration note:** `shouldShow` still works as a deprecated alias for `authorize`. Both have the same signature and behavior.\n\n---\n\n## Auto-Registered Routes\n\nAll API routes are registered automatically by the package during `boot()` -- no manual controllers or route definitions needed. Each route group is gated by the `authorize` callback if configured.\n\n### Stats bar endpoint\n\nRegistered when `statsEndpoint` is a string (default: `/admin/api/server-stats`). Returns the latest stats snapshot as JSON.\n\n### Debug toolbar routes\n\nRegistered when `toolbar` is enabled. Base path configurable via `advanced.debugEndpoint` (default: `/admin/api/debug`).\n\n| Method | Path                  | Description                              |\n| ------ | --------------------- | ---------------------------------------- |\n| GET    | `/queries`            | SQL queries with summary stats           |\n| GET    | `/events`             | Application events                       |\n| GET    | `/routes`             | Registered route table                   |\n| GET    | `/logs`               | Paginated log entries (up to 200)        |\n| GET    | `/emails`             | Captured emails (stripped HTML)          |\n| GET    | `/emails/:id/preview` | Email HTML preview                       |\n| GET    | `/traces`             | Request traces with log correlation      |\n| GET    | `/traces/:id`         | Trace detail with spans and related logs |\n| GET    | `/config`             | Debug store configuration                |\n| GET    | `/diagnostics`        | Provider diagnostics and status          |\n\n### Dashboard routes\n\nRegistered when `dashboard` is enabled. Base path configurable via `dashboard.path` (default: `/__stats`).\n\n| Method | Path                       | Description                       |\n| ------ | -------------------------- | --------------------------------- |\n| GET    | `/`                        | Dashboard page (HTML)             |\n| GET    | `/api/overview`            | Overview metrics                  |\n| GET    | `/api/overview/chart`      | Time-series chart data            |\n| GET    | `/api/requests`            | Paginated request history         |\n| GET    | `/api/requests/:id`        | Request detail with queries/trace |\n| GET    | `/api/queries`             | Paginated query list              |\n| GET    | `/api/queries/grouped`     | Queries grouped by normalized SQL |\n| GET    | `/api/queries/:id/explain` | EXPLAIN plan for a query          |\n| GET    | `/api/events`              | Paginated event list              |\n| GET    | `/api/routes`              | Route table                       |\n| GET    | `/api/logs`                | Paginated log entries             |\n| GET    | `/api/emails`              | Paginated email list              |\n| GET    | `/api/emails/:id/preview`  | Email HTML preview                |\n| GET    | `/api/traces`              | Paginated trace list              |\n| GET    | `/api/traces/:id`          | Trace detail with spans           |\n| GET    | `/api/cache`               | Cache stats and key listing       |\n| GET    | `/api/cache/:key`          | Cache key detail                  |\n| DELETE | `/api/cache/:key`          | Delete a cache key                |\n| GET    | `/api/jobs`                | Job queue overview                |\n| GET    | `/api/jobs/:id`            | Job detail                        |\n| POST   | `/api/jobs/:id/retry`      | Retry a failed job                |\n| GET    | `/api/config`              | App config (secrets redacted)     |\n| GET    | `/api/filters`             | Saved filters                     |\n| POST   | `/api/filters`             | Create saved filter               |\n| DELETE | `/api/filters/:id`         | Delete saved filter               |\n\n### Global middleware note\n\nAuto-registered routes bypass route-level middleware but are still subject to global/server middleware.\n\n**Session middleware:** If you have session middleware registered globally in `router.use()`, every polling request (every ~3 seconds) will trigger a `Set-Cookie` response. The package automatically strips `Set-Cookie` headers from its own routes to prevent cookie accumulation, but for cleanest results we recommend moving session middleware to a named route group:\n\n```ts\n// start/kernel.ts — remove session from router.use()\nrouter.use([\n  () =\u003e import('@adonisjs/core/bodyparser_middleware'),\n  // () =\u003e import('@adonisjs/session/session_middleware'),  ← remove\n  () =\u003e import('@adonisjs/shield/shield_middleware'),\n])\n\n// start/routes.ts — add to your route groups instead\nrouter.group(() =\u003e {\n  // your app routes here\n}).use(middleware.session())\n```\n\n**Auth middleware:** If you have auth middleware (like `silentAuth`) registered globally, each polling request will trigger a DB query every few seconds.\n\nTo avoid this, either:\n\n- Move auth middleware to a named route group instead of global middleware\n- Use the `authorize` callback for access control (recommended)\n\n---\n\n## Edge Tag\n\nThe `@serverStats()` Edge tag renders a self-contained stats bar with inline HTML, CSS, and JS -- no external assets, no build step.\n\n```edge\n\u003cbody\u003e\n  @inertia()\n  @serverStats()\n\u003c/body\u003e\n```\n\nFeatures:\n\n- Polls the stats API at the configured interval\n- Color-coded thresholds (green/amber/red)\n- SVG sparkline charts with gradient fills\n- Hover tooltips with min/max/avg stats\n- Show/hide toggle (persisted via localStorage)\n- Auto-hides for non-admin users (403 detection)\n- Scoped CSS (`.ss-` prefix)\n- Stale connection indicator (amber dot after 10s)\n\n---\n\n## React \u0026 Vue (Inertia.js) — Alpha\n\n\u003e **Alpha feature.** The React and Vue integrations are new and may have rough edges. Bug reports and feedback are very welcome — please [open an issue](https://github.com/simulieren/adonisjs-server-stats/issues).\n\nIf you're using **Inertia.js** with React or Vue instead of Edge templates, you can drop in the same stats bar, debug panel, and dashboard as fully native components. Same data, same styling, same features — just framework-native.\n\n### Install\n\nNo extra packages needed. The components ship inside the main package:\n\n```bash\nnpm install adonisjs-server-stats\n```\n\nPeer dependencies (all optional — install what you use):\n\n```bash\n# React\nnpm install react react-dom\n\n# Vue\nnpm install vue\n\n# Real-time updates (optional — falls back to polling)\nnpm install @adonisjs/transmit-client\n```\n\n### React\n\n```tsx\nimport { ServerStatsBar, DebugPanel, DashboardPage } from 'adonisjs-server-stats/react'\nimport 'adonisjs-server-stats/react/css'\n\n// Stats bar — drop into your layout\n\u003cServerStatsBar endpoint=\"/admin/api/server-stats\" pollInterval={3000} /\u003e\n\n// Debug panel — same layout, add below the stats bar\n\u003cDebugPanel debugEndpoint=\"/admin/api/debug\" /\u003e\n\n// Dashboard — use as a full Inertia page\n\u003cDashboardPage dashboardEndpoint=\"/__stats/api\" /\u003e\n```\n\nAvailable hooks:\n\n```tsx\nimport {\n  useServerStats,\n  useDebugData,\n  useDashboardData,\n  useTheme,\n  useFeatures,\n} from 'adonisjs-server-stats/react'\n```\n\n### Vue\n\n```vue\n\u003cscript setup\u003e\nimport { ServerStatsBar, DebugPanel, DashboardPage } from 'adonisjs-server-stats/vue'\nimport 'adonisjs-server-stats/vue/css'\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003c!-- Stats bar — drop into your layout --\u003e\n  \u003cServerStatsBar endpoint=\"/admin/api/server-stats\" :poll-interval=\"3000\" /\u003e\n\n  \u003c!-- Debug panel --\u003e\n  \u003cDebugPanel debug-endpoint=\"/admin/api/debug\" /\u003e\n\n  \u003c!-- Dashboard — use as a full Inertia page --\u003e\n  \u003cDashboardPage dashboard-endpoint=\"/__stats/api\" /\u003e\n\u003c/template\u003e\n```\n\nAvailable composables:\n\n```ts\nimport {\n  useServerStats,\n  useDebugData,\n  useDashboardData,\n  useTheme,\n  useFeatures,\n} from 'adonisjs-server-stats/vue'\n```\n\n### Shared building blocks (React)\n\nFor advanced composition, React also exports lower-level UI primitives:\n\n```tsx\nimport {\n  ThemeToggle,\n  Badge,\n  MethodBadge,\n  StatusBadge,\n  JsonViewer,\n  Tooltip,\n} from 'adonisjs-server-stats/react'\n```\n\n### Auth \u0026 visibility\n\nThe components auto-detect your auth setup:\n\n- **Cookie auth** (default Inertia setup) — requests use `credentials: 'include'` automatically\n- **Bearer token** — pass `authToken` as a prop to any component\n\nThe same `authorize` callback you configure on the server gates all API routes. If a user isn't authorized, the components detect the 403 and hide themselves.\n\n### Real-time updates\n\nIf `@adonisjs/transmit-client` is installed, the stats bar subscribes to SSE for instant updates. Otherwise it falls back to polling at the configured interval. No configuration needed — it just works.\n\n### Theme support\n\nThe React and Vue components share the same theme system as Edge. Dark/light preference syncs across all three UIs via `localStorage`, including cross-tab sync.\n\n### Known limitations (alpha)\n\n- The dashboard page is large — lazy-loading helps but initial bundle may be significant\n- Some edge cases in custom pane rendering may not be fully covered yet\n- Error boundaries are minimal — a bad API response may cause a blank panel\n- Only tested with React 18/19 and Vue 3.3+\n\nFound a bug? Have feedback? [Open an issue](https://github.com/simulieren/adonisjs-server-stats/issues) — it helps a lot.\n\n---\n\n## Dev Toolbar\n\nAdds a debug panel with SQL query inspection, event tracking, email capture with HTML preview, route table, live logs, and per-request tracing. Only active in non-production environments.\n\n```ts\nexport default defineConfig({\n  toolbar: {\n    slowQueryThreshold: 100,\n    tracing: true,\n    persist: true,\n  },\n})\n```\n\nDebug routes are auto-registered by the package at `/admin/api/debug/*` (configurable via `advanced.debugEndpoint`).\n\n\u003cdetails\u003e\n\u003csummary\u003eLegacy format (deprecated)\u003c/summary\u003e\n\n```ts\nexport default defineConfig({\n  devToolbar: {\n    enabled: true,\n    maxQueries: 500,\n    maxEvents: 200,\n    maxEmails: 100,\n    slowQueryThresholdMs: 100,\n    persistDebugData: true,\n    tracing: true,\n  },\n})\n```\n\n\u003c/details\u003e\n\n### Built-in Emails Tab\n\nThe debug toolbar captures all emails sent via AdonisJS mail (`mail:sending`, `mail:sent`, `mail:queued`, `queued:mail:error` events). Click any email row to preview its HTML in an iframe.\n\n\u003e **Note:** Email previews are rendered in an iframe. If your app uses `@adonisjs/shield` with the default `X-Frame-Options: DENY` header, the preview will be blocked. Change it to `SAMEORIGIN` in your shield config:\n\u003e\n\u003e ```ts\n\u003e // config/shield.ts\n\u003e xFrame: {\n\u003e   enabled: true,\n\u003e   action: 'SAMEORIGIN',\n\u003e },\n\u003e ```\n\n### Cross-Process Email Capture (Queue Workers)\n\nAdonisJS mail events (`mail:sending`, `mail:sent`, etc.) are process-local. If your app sends emails from **Bull queue workers** or other separate processes, the web server's email collector never sees them.\n\nThe provider handles this automatically via a **Redis pub/sub bridge**:\n\n1. In queue workers (`console` environment), the provider only starts a lightweight email bridge publisher — no debug store, routes, or dashboard overhead\n2. When an email is sent, the event is published to a Redis pub/sub channel\n3. In the web server (`web` environment), the provider subscribes to the same channel and ingests the email into both the debug panel and the dashboard\n\n**Requirements:**\n- `@adonisjs/redis` must be installed and configured (used for pub/sub between processes)\n- The provider must be registered **without** an `environment` restriction so it loads in all environments:\n\n```ts\n// adonisrc.ts\nproviders: [\n  () =\u003e import('adonisjs-server-stats/provider'), // runs in web + console\n]\n```\n\n\u003e **Note:** If you previously used separate `adonisjs-server-stats/email-bridge/provider` and `adonisjs-server-stats/log-stream/provider` registrations, you can replace all three with the single provider above. The email bridge and log stream functionality are now built into the main provider.\n\n### Persistent Debug Data\n\nEnable `toolbar.persist: true` (or the legacy `devToolbar.persistDebugData: true`) to save queries, events, and emails to `.adonisjs/server-stats/debug-data.json`. You can customize the path via `advanced.persistPath`. Data is:\n\n- **Loaded** on server startup (before collectors start)\n- **Flushed** every 30 seconds (handles crashes)\n- **Saved** on graceful shutdown\n\n### Request Tracing\n\nWhen `tracing: true` is set, the debug panel gains a **Timeline** tab that shows a waterfall view of every HTTP request -- which DB queries ran, in what order, and how long each took.\n\nTracing uses `AsyncLocalStorage` to automatically correlate operations to the request that triggered them. DB queries captured via `db:query` events and `console.warn` calls are automatically attached to the active request trace.\n\n#### How it works\n\n```\nGET /organizations/create    286ms\n├─ SELECT * FROM users          2ms  █\n├─ SELECT * FROM orgs           4ms    █\n├─ fetchMembers (custom)      180ms    ██████████████████\n└─ response sent                5ms                      ██\n```\n\n1. The **Timeline** tab shows a list of recent requests with method, URL, status code, duration, span count, and any warnings\n2. Click a request to see the **waterfall chart** -- each span is a horizontal bar positioned by time offset, color-coded by category\n3. Spans can be nested (a custom span wrapping DB queries will show them indented)\n\n#### Span categories\n\n| Category | Color  | Auto-captured          |\n| -------- | ------ | ---------------------- |\n| DB       | Purple | `db:query` events      |\n| Request  | Blue   | Full request lifecycle |\n| Mail     | Green  | --                     |\n| Event    | Amber  | --                     |\n| View     | Cyan   | --                     |\n| Custom   | Gray   | Via `trace()` helper   |\n\n#### Custom spans\n\nUse the `trace()` helper to wrap any async code in a named span:\n\n```ts\nimport { trace } from 'adonisjs-server-stats'\n\n// In a controller or service:\nconst result = await trace('organization.fetchMembers', async () =\u003e {\n  return OrganizationService.getMembers(orgId)\n})\n```\n\nIf tracing is disabled or no request is active, `trace()` executes the function directly with no overhead.\n\n#### Related Logs\n\nWhen viewing a trace detail (either in the debug panel Timeline tab or the dashboard), related log entries are automatically correlated using the HTTP request ID (`ctx.request.id()`). Any logs emitted during the request appear in a \"Related Logs\" section below the waterfall chart.\n\nThis works with both SQLite persistence (joins on `http_request_id`) and in-memory mode (scans the log file for matching `request_id` entries). No configuration needed — if your app uses AdonisJS request IDs, correlation happens automatically.\n\n### Full-Page Dashboard\n\nThe dashboard is a dedicated page that provides historical data, charts, query analysis, and integration inspectors -- all persisted to a local SQLite database. It's like having Laravel Telescope built into your dev toolbar.\n\n#### Prerequisites\n\nThe dashboard requires `better-sqlite3` for local data storage:\n\n```bash\nnpm install better-sqlite3\n```\n\nIf `better-sqlite3` is not installed, the dashboard will log a helpful message and disable itself gracefully -- the rest of the stats bar and debug toolbar continues to work.\n\n#### Enable the Dashboard\n\n```ts\n// config/server_stats.ts\nexport default defineConfig({\n  dashboard: true,\n})\n```\n\nRestart your dev server and visit **`/__stats`** (or your configured `dashboard.path`).\n\n#### Configuration\n\n```ts\nexport default defineConfig({\n  dashboard: {\n    path: '/__stats',\n    retentionDays: 7,\n  },\n  toolbar: {\n    tracing: true,\n    excludeFromTracing: ['/admin/api/debug'],\n  },\n  advanced: {\n    dbPath: '.adonisjs/server-stats/dashboard.sqlite3',\n  },\n})\n```\n\n#### Dashboard Sections\n\n| Section      | Description                                                                                                                                             |\n| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| **Overview** | Performance cards (avg/p95 response time, req/min, error rate) with sparkline charts and configurable time ranges (1h/6h/24h/7d)                        |\n| **Requests** | Paginated request history with method, URL, status, duration. Click for detail view with associated queries and trace                                   |\n| **Queries**  | All captured SQL queries with duration, model, connection. Grouped view shows query patterns by normalized SQL. EXPLAIN plan support for SELECT queries |\n| **Events**   | Application events captured from the AdonisJS emitter                                                                                                   |\n| **Routes**   | Full route table with methods, patterns, handlers, and middleware stacks                                                                                |\n| **Logs**     | Log history with level filtering, text search, and structured JSON field search (e.g. filter by `userId = 5`)                                           |\n| **Emails**   | Email history with sender, recipient, subject, status. Click for HTML preview in iframe                                                                 |\n| **Timeline** | Per-request waterfall timeline (requires `tracing: true`)                                                                                               |\n| **Cache**    | Redis key browser with SCAN-based listing, type-aware detail view, and server stats (requires `@adonisjs/redis`)                                        |\n| **Jobs**     | Queue overview with job listing, detail, and retry for failed jobs (requires `@rlanz/bull-queue`)                                                       |\n| **Config**   | Sanitized view of app configuration and environment variables. Secrets are auto-redacted                                                                |\n\n#### Access Control\n\nThe dashboard reuses the `authorize` callback from the main config. If set, all dashboard routes are gated by it -- unauthorized requests receive a 403.\n\n```ts\nexport default defineConfig({\n  authorize: (ctx) =\u003e ctx.auth?.user?.role === 'admin',\n  dashboard: true,\n})\n```\n\n#### Deep Links from Debug Panel\n\nWhen the dashboard is enabled, the debug panel gains link icons on query, event, email, and trace rows. Clicking them opens the dashboard in a new tab, navigating directly to the relevant section and item.\n\n#### Real-Time Updates\n\nThe dashboard supports real-time updates via two mechanisms:\n\n- **Transmit (SSE)**: If `@adonisjs/transmit` is installed, the dashboard subscribes to `server-stats/dashboard` for live overview updates\n- **Polling fallback**: If Transmit is not available, the dashboard polls the API at a configurable interval\n\n#### Data Storage\n\nThe dashboard uses a dedicated SQLite database (separate from your app's database) with 8 tables prefixed with `server_stats_`. The database is:\n\n- **Auto-migrated** on startup (no manual migration step)\n- **Self-contained** -- uses its own Knex connection, never touches your app's migration history\n- **Self-cleaning** -- old data is automatically purged based on `retentionDays`\n- **WAL mode** -- concurrent reads don't block writes\n\nThe SQLite file is created at the configured `advanced.dbPath` (default: `.adonisjs/server-stats/dashboard.sqlite3`). Add it to your `.gitignore`:\n\n```\n.adonisjs/server-stats/\n```\n\n#### Theme Support\n\nAll three UIs (dashboard, debug panel, and stats bar) support dark and light themes:\n\n- **System preference** -- automatically follows `prefers-color-scheme` (dark is default)\n- **Manual toggle** -- sun/moon button in the dashboard sidebar and debug panel tab bar\n- **Synced** -- theme choice is shared via `localStorage` across all three UIs, including cross-tab sync\n- **Scoped** -- CSS variables are scoped to their containers, so they won't leak into your app's styles\n\n---\n\n### Custom Debug Panes\n\nAdd custom tabs to the debug panel:\n\n```ts\nimport { defineConfig } from 'adonisjs-server-stats'\nimport type { DebugPane } from 'adonisjs-server-stats'\n\nconst webhooksPane: DebugPane = {\n  id: 'webhooks',\n  label: 'Webhooks',\n  endpoint: '/admin/api/debug/webhooks',\n  columns: [\n    { key: 'id', label: '#', width: '40px' },\n    { key: 'event', label: 'Event', searchable: true },\n    { key: 'url', label: 'URL', searchable: true },\n    {\n      key: 'status',\n      label: 'Status',\n      width: '80px',\n      format: 'badge',\n      badgeColorMap: { delivered: 'green', pending: 'amber', failed: 'red' },\n    },\n    { key: 'duration', label: 'Duration', width: '70px', format: 'duration' },\n    { key: 'timestamp', label: 'Time', width: '80px', format: 'timeAgo' },\n  ],\n  search: { placeholder: 'Filter webhooks by event or URL...' },\n  clearable: true,\n}\n\nexport default defineConfig({\n  toolbar: {\n    panes: [webhooksPane],\n  },\n})\n```\n\nThe endpoint must return JSON with the data array under a key matching the pane `id` (or `dataKey`):\n\n```ts\n// Controller\nasync webhooks({ response }: HttpContext) {\n  const events = await WebhookEvent.query().orderBy('created_at', 'desc').limit(200)\n  return response.json({ webhooks: events })\n}\n```\n\n#### `DebugPane` Options\n\n| Option      | Type                | Default | Description                               |\n| ----------- | ------------------- | ------- | ----------------------------------------- |\n| `id`        | `string`            | --      | Unique identifier (also default data key) |\n| `label`     | `string`            | --      | Tab display name                          |\n| `endpoint`  | `string`            | --      | API endpoint URL                          |\n| `columns`   | `DebugPaneColumn[]` | --      | Column definitions                        |\n| `search`    | `{ placeholder }`   | --      | Enable search bar                         |\n| `dataKey`   | `string`            | `id`    | JSON key for data array (dot notation OK) |\n| `fetchOnce` | `boolean`           | `false` | Cache after first fetch                   |\n| `clearable` | `boolean`           | `false` | Show Clear button                         |\n\n#### `DebugPaneColumn` Options\n\n| Option          | Type                     | Default  | Description                           |\n| --------------- | ------------------------ | -------- | ------------------------------------- |\n| `key`           | `string`                 | --       | JSON field name                       |\n| `label`         | `string`                 | --       | Column header text                    |\n| `width`         | `string`                 | auto     | CSS width (e.g. `'60px'`)             |\n| `format`        | `DebugPaneFormatType`    | `'text'` | Cell format (see table below)         |\n| `searchable`    | `boolean`                | `false`  | Include in search filtering           |\n| `filterable`    | `boolean`                | `false`  | Click to set as search filter         |\n| `badgeColorMap` | `Record\u003cstring, string\u003e` | --       | Value-to-color map for `badge` format |\n\n#### Format Types\n\n| Format     | Renders As                       | Expected Input          |\n| ---------- | -------------------------------- | ----------------------- |\n| `text`     | Escaped plain text               | any                     |\n| `time`     | `HH:MM:SS.mmm`                   | Unix timestamp (ms)     |\n| `timeAgo`  | `3s ago`, `2m ago`               | Unix timestamp (ms)     |\n| `duration` | `X.XXms` with color coding       | number (ms)             |\n| `method`   | HTTP method pill badge           | `'GET'`, `'POST'`, etc. |\n| `json`     | Compact preview, click to expand | object or array         |\n| `badge`    | Colored pill via `badgeColorMap` | string                  |\n\nBadge colors: `green`, `amber`, `red`, `blue`, `purple`, `muted`\n\n---\n\n## Prometheus Integration\n\nExport all metrics as Prometheus gauges. Requires `@julr/adonisjs-prometheus`.\n\n```ts\n// config/prometheus.ts\nimport { defineConfig } from '@julr/adonisjs-prometheus'\nimport { httpCollector } from '@julr/adonisjs-prometheus/collectors/http_collector'\nimport { serverStatsCollector } from 'adonisjs-server-stats/prometheus'\n\nexport default defineConfig({\n  endpoint: '/metrics',\n  collectors: [httpCollector(), serverStatsCollector()],\n})\n```\n\nGauges are updated automatically on each collection tick.\n\n---\n\n## Log Stream\n\nThe log stream module watches a JSON log file and broadcasts new entries via Transmit (SSE).\n\n**Two purposes:**\n\n1. Provides error/warning counts to the stats bar via `logCollector()`\n2. Broadcasts individual log entries to a Transmit channel via `LogStreamProvider`\n\nStandalone usage:\n\n```ts\nimport { LogStreamService } from 'adonisjs-server-stats/log-stream'\n\nconst service = new LogStreamService('logs/app.log', (entry) =\u003e {\n  console.log('New log entry:', entry)\n})\n\nawait service.start()\n// later...\nservice.stop()\n```\n\n---\n\n## TypeScript\n\nAll types are exported for consumer use:\n\n```ts\n// Core types\nimport type {\n  ServerStats,\n  ServerStatsConfig,\n  ResolvedServerStatsConfig,\n  MetricCollector,\n  MetricValue,\n  LogStats,\n  DevToolbarOptions,\n  ToolbarConfig,\n  DashboardConfig,\n  AdvancedConfig,\n} from 'adonisjs-server-stats'\n\n// Debug types\nimport type {\n  DebugPane,\n  DebugPaneColumn,\n  DebugPaneFormatType,\n  DebugPaneSearch,\n  BadgeColor,\n  QueryRecord,\n  EventRecord,\n  EmailRecord,\n  RouteRecord,\n  TraceSpan,\n  TraceRecord,\n} from 'adonisjs-server-stats'\n\n// Dashboard types\nimport type {\n  RequestFilters,\n  QueryFilters,\n  EventFilters,\n  EmailFilters,\n  LogFilters,\n  TraceFilters,\n  PaginatedResult,\n} from 'adonisjs-server-stats'\n\n// Dashboard store (for advanced use)\nimport { DashboardStore } from 'adonisjs-server-stats'\n\n// Trace helper\nimport { trace } from 'adonisjs-server-stats'\n\n// Collector option types\nimport type {\n  HttpCollectorOptions,\n  DbPoolCollectorOptions,\n  QueueCollectorOptions,\n  QueueRedisConnection,\n  LogCollectorOptions,\n} from 'adonisjs-server-stats/collectors'\n```\n\n---\n\n## Peer Dependencies\n\nAll integrations use lazy `import()` -- missing peer deps won't crash the app. The corresponding collector simply returns defaults.\n\n| Dependency                  | Required By                                         |\n| --------------------------- | --------------------------------------------------- |\n| `@adonisjs/core`            | Everything (required)                               |\n| `@adonisjs/lucid`           | `dbPoolCollector`, `appCollector`, dashboard        |\n| `@adonisjs/redis`           | `redisCollector`, dashboard cache inspector         |\n| `@adonisjs/transmit`        | Provider (SSE broadcast), dashboard real-time       |\n| `@adonisjs/transmit-client` | React/Vue real-time updates (falls back to polling) |\n| `@julr/adonisjs-prometheus` | `serverStatsCollector`                              |\n| `bullmq`                    | `queueCollector`                                    |\n| `better-sqlite3`            | Dashboard (`dashboard: true`)                       |\n| `edge.js`                   | Edge tag                                            |\n| `react`, `react-dom`        | React components (alpha)                            |\n| `vue`                       | Vue components (alpha)                              |\n\n## License\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimulieren%2Fadonisjs-server-stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimulieren%2Fadonisjs-server-stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimulieren%2Fadonisjs-server-stats/lists"}