@hasna/logs 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/README.md +73 -0
- package/dashboard/bun.lock +526 -0
- package/dashboard/eslint.config.js +23 -0
- package/dashboard/index.html +13 -0
- package/dashboard/package.json +32 -0
- package/dashboard/public/favicon.svg +1 -0
- package/dashboard/public/icons.svg +24 -0
- package/dashboard/src/App.css +184 -0
- package/dashboard/src/App.tsx +49 -0
- package/dashboard/src/api.ts +33 -0
- package/dashboard/src/assets/hero.png +0 -0
- package/dashboard/src/assets/react.svg +1 -0
- package/dashboard/src/assets/vite.svg +1 -0
- package/dashboard/src/index.css +111 -0
- package/dashboard/src/main.tsx +10 -0
- package/dashboard/src/pages/Alerts.tsx +69 -0
- package/dashboard/src/pages/Issues.tsx +50 -0
- package/dashboard/src/pages/Perf.tsx +75 -0
- package/dashboard/src/pages/Projects.tsx +67 -0
- package/dashboard/src/pages/Summary.tsx +67 -0
- package/dashboard/src/pages/Tail.tsx +65 -0
- package/dashboard/tsconfig.app.json +28 -0
- package/dashboard/tsconfig.json +7 -0
- package/dashboard/tsconfig.node.json +26 -0
- package/dashboard/vite.config.ts +14 -0
- package/dist/cli/index.js +116 -12
- package/dist/mcp/index.js +306 -100
- package/dist/server/index.js +592 -7
- package/package.json +12 -2
- package/sdk/package.json +3 -2
- package/sdk/src/index.ts +1 -1
- package/sdk/src/types.ts +56 -0
- package/src/cli/index.ts +114 -4
- package/src/db/index.ts +10 -0
- package/src/db/migrations/001_alert_rules.ts +21 -0
- package/src/db/migrations/002_issues.ts +21 -0
- package/src/db/migrations/003_retention.ts +15 -0
- package/src/db/migrations/004_page_auth.ts +13 -0
- package/src/lib/alerts.test.ts +67 -0
- package/src/lib/alerts.ts +117 -0
- package/src/lib/compare.test.ts +52 -0
- package/src/lib/compare.ts +85 -0
- package/src/lib/diagnose.test.ts +55 -0
- package/src/lib/diagnose.ts +76 -0
- package/src/lib/export.test.ts +66 -0
- package/src/lib/export.ts +65 -0
- package/src/lib/health.test.ts +48 -0
- package/src/lib/health.ts +51 -0
- package/src/lib/ingest.ts +25 -2
- package/src/lib/issues.test.ts +79 -0
- package/src/lib/issues.ts +70 -0
- package/src/lib/page-auth.test.ts +54 -0
- package/src/lib/page-auth.ts +48 -0
- package/src/lib/retention.test.ts +42 -0
- package/src/lib/retention.ts +62 -0
- package/src/lib/scanner.ts +21 -2
- package/src/lib/scheduler.ts +6 -0
- package/src/lib/session-context.ts +28 -0
- package/src/mcp/index.ts +133 -89
- package/src/server/index.ts +12 -1
- package/src/server/routes/alerts.ts +32 -0
- package/src/server/routes/issues.ts +43 -0
- package/src/server/routes/logs.ts +21 -0
- package/src/server/routes/projects.ts +25 -0
- package/src/server/routes/stream.ts +43 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Hono } from "hono"
|
|
2
|
+
import { streamSSE } from "hono/streaming"
|
|
3
|
+
import type { Database } from "bun:sqlite"
|
|
4
|
+
import type { LogLevel, LogRow } from "../../types/index.ts"
|
|
5
|
+
|
|
6
|
+
export function streamRoutes(db: Database) {
|
|
7
|
+
const app = new Hono()
|
|
8
|
+
|
|
9
|
+
// GET /api/logs/stream?project_id=&level=&service=
|
|
10
|
+
app.get("/", (c) => {
|
|
11
|
+
const { project_id, level, service } = c.req.query()
|
|
12
|
+
|
|
13
|
+
return streamSSE(c, async (stream) => {
|
|
14
|
+
let lastId: string | null = null
|
|
15
|
+
|
|
16
|
+
// Seed lastId with the most recent log so we only stream new ones
|
|
17
|
+
const latest = db.prepare("SELECT id FROM logs ORDER BY timestamp DESC LIMIT 1").get() as { id: string } | null
|
|
18
|
+
lastId = latest?.id ?? null
|
|
19
|
+
|
|
20
|
+
while (true) {
|
|
21
|
+
const conditions: string[] = []
|
|
22
|
+
const params: Record<string, unknown> = {}
|
|
23
|
+
|
|
24
|
+
if (lastId) { conditions.push("rowid > (SELECT rowid FROM logs WHERE id = $lastId)"); params.$lastId = lastId }
|
|
25
|
+
if (project_id) { conditions.push("project_id = $project_id"); params.$project_id = project_id }
|
|
26
|
+
if (level) { conditions.push("level IN (" + level.split(",").map((l, i) => `$l${i}`).join(",") + ")"); level.split(",").forEach((l, i) => { params[`$l${i}`] = l }) }
|
|
27
|
+
if (service) { conditions.push("service = $service"); params.$service = service }
|
|
28
|
+
|
|
29
|
+
const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : ""
|
|
30
|
+
const rows = db.prepare(`SELECT * FROM logs ${where} ORDER BY timestamp ASC LIMIT 50`).all(params) as LogRow[]
|
|
31
|
+
|
|
32
|
+
for (const row of rows) {
|
|
33
|
+
await stream.writeSSE({ data: JSON.stringify(row), id: row.id, event: row.level })
|
|
34
|
+
lastId = row.id
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await stream.sleep(500)
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
return app
|
|
43
|
+
}
|