@hasna/logs 0.3.16 → 0.3.18

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/dist/mcp/index.js CHANGED
@@ -17,11 +17,12 @@ import {
17
17
  listIssues,
18
18
  listPages,
19
19
  listProjects,
20
+ registerCloudTools,
20
21
  resolveProjectId,
21
22
  scoreLabel,
22
23
  summarizeLogs,
23
24
  updateIssueStatus
24
- } from "../index-6zrkek5y.js";
25
+ } from "../index-hwabsrfh.js";
25
26
  import {
26
27
  createJob,
27
28
  listJobs
@@ -6527,7 +6528,7 @@ var require_dist = __commonJS((exports, module) => {
6527
6528
  var require_package = __commonJS((exports, module) => {
6528
6529
  module.exports = {
6529
6530
  name: "@hasna/logs",
6530
- version: "0.3.16",
6531
+ version: "0.3.18",
6531
6532
  description: "Log aggregation + browser script + headless page scanner + performance monitoring for AI agents",
6532
6533
  type: "module",
6533
6534
  main: "./dist/index.js",
@@ -6567,7 +6568,7 @@ var require_package = __commonJS((exports, module) => {
6567
6568
  author: "Andrei Hasna <andrei@hasna.com>",
6568
6569
  license: "Apache-2.0",
6569
6570
  dependencies: {
6570
- "@hasna/cloud": "^0.1.0",
6571
+ "@hasna/cloud": "^0.1.24",
6571
6572
  "@modelcontextprotocol/sdk": "^1.12.1",
6572
6573
  commander: "^14.0.0",
6573
6574
  hono: "^4.7.11",
@@ -24376,4 +24377,5 @@ server.tool("list_agents", "List all registered agents.", {}, async () => {
24376
24377
  return { content: [{ type: "text", text: JSON.stringify([..._logsAgents.values()]) }] };
24377
24378
  });
24378
24379
  var transport = new StdioServerTransport;
24380
+ registerCloudTools(server, "logs");
24379
24381
  await server.connect(transport);
@@ -6,7 +6,7 @@ import {
6
6
  setPageAuth,
7
7
  setRetentionPolicy,
8
8
  startScheduler
9
- } from "../index-5qwba140.js";
9
+ } from "../index-8pwbytc6.js";
10
10
  import {
11
11
  getHealth
12
12
  } from "../index-cpvq9np9.js";
@@ -31,7 +31,7 @@ import {
31
31
  updateAlertRule,
32
32
  updateIssueStatus,
33
33
  updateProject
34
- } from "../index-6zrkek5y.js";
34
+ } from "../index-hwabsrfh.js";
35
35
  import {
36
36
  createJob,
37
37
  deleteJob,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/logs",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
4
4
  "description": "Log aggregation + browser script + headless page scanner + performance monitoring for AI agents",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -40,7 +40,7 @@
40
40
  "author": "Andrei Hasna <andrei@hasna.com>",
41
41
  "license": "Apache-2.0",
42
42
  "dependencies": {
43
- "@hasna/cloud": "^0.1.0",
43
+ "@hasna/cloud": "^0.1.24",
44
44
  "@modelcontextprotocol/sdk": "^1.12.1",
45
45
  "commander": "^14.0.0",
46
46
  "hono": "^4.7.11",
@@ -56,4 +56,4 @@
56
56
  "@types/react": "^19.1.4",
57
57
  "typescript": "^5.9.3"
58
58
  }
59
- }
59
+ }
package/src/lib/ingest.ts CHANGED
@@ -1,11 +1,11 @@
1
- import type { Database } from "bun:sqlite"
1
+ import type { DbAdapter } from "@hasna/cloud"
2
2
  import type { LogEntry, LogRow } from "../types/index.ts"
3
3
  import { upsertIssue } from "./issues.ts"
4
4
  import { evaluateAlerts } from "./alerts.ts"
5
5
 
6
6
  const ERROR_LEVELS = new Set(["warn", "error", "fatal"])
7
7
 
8
- export function ingestLog(db: Database, entry: LogEntry): LogRow {
8
+ export function ingestLog(db: DbAdapter, entry: LogEntry): LogRow {
9
9
  const stmt = db.prepare(`
10
10
  INSERT INTO logs (project_id, page_id, level, source, service, message, trace_id, session_id, agent, url, stack_trace, metadata)
11
11
  VALUES ($project_id, $page_id, $level, $source, $service, $message, $trace_id, $session_id, $agent, $url, $stack_trace, $metadata)
@@ -37,7 +37,7 @@ export function ingestLog(db: Database, entry: LogEntry): LogRow {
37
37
  return row
38
38
  }
39
39
 
40
- export function ingestBatch(db: Database, entries: LogEntry[], sharedTraceId?: string | null): LogRow[] {
40
+ export function ingestBatch(db: DbAdapter, entries: LogEntry[], sharedTraceId?: string | null): LogRow[] {
41
41
  // Apply shared trace_id to entries that don't have their own
42
42
  if (sharedTraceId) {
43
43
  entries = entries.map(e => e.trace_id ? e : { ...e, trace_id: sharedTraceId })
@@ -47,8 +47,9 @@ export function ingestBatch(db: Database, entries: LogEntry[], sharedTraceId?: s
47
47
  VALUES ($project_id, $page_id, $level, $source, $service, $message, $trace_id, $session_id, $agent, $url, $stack_trace, $metadata)
48
48
  RETURNING *
49
49
  `)
50
- const tx = db.transaction((items: LogEntry[]) =>
51
- items.map(entry =>
50
+ // @hasna/cloud executes the callback inside the transaction immediately.
51
+ const rows = db.transaction(() =>
52
+ entries.map(entry =>
52
53
  insert.get({
53
54
  $project_id: entry.project_id ?? null,
54
55
  $page_id: entry.page_id ?? null,
@@ -65,7 +66,6 @@ export function ingestBatch(db: Database, entries: LogEntry[], sharedTraceId?: s
65
66
  }) as LogRow
66
67
  )
67
68
  )
68
- const rows = tx(entries)
69
69
 
70
70
  // Issue grouping for error-level entries (outside transaction for perf)
71
71
  for (const entry of entries) {
package/src/mcp/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4
+ import { registerCloudTools } from "@hasna/cloud"
4
5
  import { z } from "zod"
5
6
  import { getDb } from "../db/index.ts"
6
7
  import { ingestBatch, ingestLog } from "../lib/ingest.ts"
@@ -403,4 +404,5 @@ server.tool("list_agents", "List all registered agents.", {}, async () => {
403
404
  })
404
405
 
405
406
  const transport = new StdioServerTransport()
407
+ registerCloudTools(server, "logs")
406
408
  await server.connect(transport)
@@ -1,10 +0,0 @@
1
- // @bun
2
- import {
3
- exportToCsv,
4
- exportToJson
5
- } from "./index-eh9bkbpa.js";
6
- import"./index-g8dczzvv.js";
7
- export {
8
- exportToJson,
9
- exportToCsv
10
- };
@@ -1,8 +0,0 @@
1
- // @bun
2
- import {
3
- getHealth
4
- } from "./index-xjn8gam3.js";
5
- import"./index-re3ntm60.js";
6
- export {
7
- getHealth
8
- };
@@ -1,8 +0,0 @@
1
- // @bun
2
- import {
3
- getHealth
4
- } from "./index-yb8yd4j6.js";
5
- import"./index-g8dczzvv.js";
6
- export {
7
- getHealth
8
- };
@@ -1,45 +0,0 @@
1
- // @bun
2
- import {
3
- parseTime
4
- } from "./index-997bkzr2.js";
5
-
6
- // src/lib/count.ts
7
- function countLogs(db, opts) {
8
- const conditions = [];
9
- const params = {};
10
- if (opts.project_id) {
11
- conditions.push("project_id = $p");
12
- params.$p = opts.project_id;
13
- }
14
- if (opts.service) {
15
- conditions.push("service = $service");
16
- params.$service = opts.service;
17
- }
18
- if (opts.level) {
19
- conditions.push("level = $level");
20
- params.$level = opts.level;
21
- }
22
- const since = parseTime(opts.since);
23
- const until = parseTime(opts.until);
24
- if (since) {
25
- conditions.push("timestamp >= $since");
26
- params.$since = since;
27
- }
28
- if (until) {
29
- conditions.push("timestamp <= $until");
30
- params.$until = until;
31
- }
32
- const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";
33
- const byLevel = db.prepare(`SELECT level, COUNT(*) as c FROM logs ${where} GROUP BY level`).all(params);
34
- const by_level = Object.fromEntries(byLevel.map((r) => [r.level, r.c]));
35
- const total = byLevel.reduce((s, r) => s + r.c, 0);
36
- return {
37
- total,
38
- errors: by_level["error"] ?? 0,
39
- warns: by_level["warn"] ?? 0,
40
- fatals: by_level["fatal"] ?? 0,
41
- by_level
42
- };
43
- }
44
-
45
- export { countLogs };